l_vmanip.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. /*
  2. Minetest
  3. Copyright (C) 2013 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include <map>
  17. #include "lua_api/l_vmanip.h"
  18. #include "lua_api/l_internal.h"
  19. #include "common/c_content.h"
  20. #include "common/c_converter.h"
  21. #include "common/c_packer.h"
  22. #include "emerge.h"
  23. #include "environment.h"
  24. #include "map.h"
  25. #include "mapblock.h"
  26. #include "server.h"
  27. #include "mapgen/mapgen.h"
  28. #include "voxelalgorithms.h"
  29. // garbage collector
  30. int LuaVoxelManip::gc_object(lua_State *L)
  31. {
  32. LuaVoxelManip *o = *(LuaVoxelManip **)(lua_touserdata(L, 1));
  33. delete o;
  34. return 0;
  35. }
  36. int LuaVoxelManip::l_read_from_map(lua_State *L)
  37. {
  38. MAP_LOCK_REQUIRED;
  39. LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
  40. MMVManip *vm = o->vm;
  41. if (vm->isOrphan())
  42. return 0;
  43. v3s16 bp1 = getNodeBlockPos(check_v3s16(L, 2));
  44. v3s16 bp2 = getNodeBlockPos(check_v3s16(L, 3));
  45. sortBoxVerticies(bp1, bp2);
  46. vm->initialEmerge(bp1, bp2);
  47. push_v3s16(L, vm->m_area.MinEdge);
  48. push_v3s16(L, vm->m_area.MaxEdge);
  49. return 2;
  50. }
  51. int LuaVoxelManip::l_get_data(lua_State *L)
  52. {
  53. NO_MAP_LOCK_REQUIRED;
  54. LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
  55. bool use_buffer = lua_istable(L, 2);
  56. MMVManip *vm = o->vm;
  57. u32 volume = vm->m_area.getVolume();
  58. if (use_buffer)
  59. lua_pushvalue(L, 2);
  60. else
  61. lua_createtable(L, volume, 0);
  62. for (u32 i = 0; i != volume; i++) {
  63. lua_Integer cid = vm->m_data[i].getContent();
  64. lua_pushinteger(L, cid);
  65. lua_rawseti(L, -2, i + 1);
  66. }
  67. return 1;
  68. }
  69. int LuaVoxelManip::l_set_data(lua_State *L)
  70. {
  71. NO_MAP_LOCK_REQUIRED;
  72. LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
  73. MMVManip *vm = o->vm;
  74. if (!lua_istable(L, 2))
  75. throw LuaError("VoxelManip:set_data called with missing parameter");
  76. u32 volume = vm->m_area.getVolume();
  77. for (u32 i = 0; i != volume; i++) {
  78. lua_rawgeti(L, 2, i + 1);
  79. content_t c = lua_tointeger(L, -1);
  80. vm->m_data[i].setContent(c);
  81. lua_pop(L, 1);
  82. }
  83. return 0;
  84. }
  85. int LuaVoxelManip::l_write_to_map(lua_State *L)
  86. {
  87. MAP_LOCK_REQUIRED;
  88. LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
  89. bool update_light = !lua_isboolean(L, 2) || readParam<bool>(L, 2);
  90. GET_ENV_PTR;
  91. ServerMap *map = &(env->getServerMap());
  92. std::map<v3s16, MapBlock*> modified_blocks;
  93. if (o->is_mapgen_vm || !update_light) {
  94. o->vm->blitBackAll(&modified_blocks);
  95. } else {
  96. voxalgo::blit_back_with_light(map, o->vm, &modified_blocks);
  97. }
  98. MapEditEvent event;
  99. event.type = MEET_OTHER;
  100. for (const auto &it : modified_blocks)
  101. event.modified_blocks.insert(it.first);
  102. map->dispatchEvent(event);
  103. return 0;
  104. }
  105. int LuaVoxelManip::l_get_node_at(lua_State *L)
  106. {
  107. NO_MAP_LOCK_REQUIRED;
  108. LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
  109. v3s16 pos = check_v3s16(L, 2);
  110. pushnode(L, o->vm->getNodeNoExNoEmerge(pos));
  111. return 1;
  112. }
  113. int LuaVoxelManip::l_set_node_at(lua_State *L)
  114. {
  115. NO_MAP_LOCK_REQUIRED;
  116. LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
  117. v3s16 pos = check_v3s16(L, 2);
  118. MapNode n = readnode(L, 3);
  119. o->vm->setNodeNoEmerge(pos, n);
  120. return 0;
  121. }
  122. int LuaVoxelManip::l_update_liquids(lua_State *L)
  123. {
  124. GET_ENV_PTR;
  125. LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
  126. ServerMap *map = &(env->getServerMap());
  127. const NodeDefManager *ndef = getServer(L)->getNodeDefManager();
  128. MMVManip *vm = o->vm;
  129. Mapgen mg;
  130. mg.vm = vm;
  131. mg.ndef = ndef;
  132. mg.updateLiquid(&map->m_transforming_liquid,
  133. vm->m_area.MinEdge, vm->m_area.MaxEdge);
  134. return 0;
  135. }
  136. int LuaVoxelManip::l_calc_lighting(lua_State *L)
  137. {
  138. NO_MAP_LOCK_REQUIRED;
  139. LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
  140. if (!o->is_mapgen_vm) {
  141. warningstream << "VoxelManip:calc_lighting called for a non-mapgen "
  142. "VoxelManip object" << std::endl;
  143. return 0;
  144. }
  145. const NodeDefManager *ndef = getServer(L)->getNodeDefManager();
  146. EmergeManager *emerge = getServer(L)->getEmergeManager();
  147. MMVManip *vm = o->vm;
  148. v3s16 yblock = v3s16(0, 1, 0) * MAP_BLOCKSIZE;
  149. v3s16 fpmin = vm->m_area.MinEdge;
  150. v3s16 fpmax = vm->m_area.MaxEdge;
  151. v3s16 pmin = lua_istable(L, 2) ? check_v3s16(L, 2) : fpmin + yblock;
  152. v3s16 pmax = lua_istable(L, 3) ? check_v3s16(L, 3) : fpmax - yblock;
  153. bool propagate_shadow = !lua_isboolean(L, 4) || readParam<bool>(L, 4);
  154. sortBoxVerticies(pmin, pmax);
  155. if (!vm->m_area.contains(VoxelArea(pmin, pmax)))
  156. throw LuaError("Specified voxel area out of VoxelManipulator bounds");
  157. Mapgen mg;
  158. mg.vm = vm;
  159. mg.ndef = ndef;
  160. mg.water_level = emerge->mgparams->water_level;
  161. mg.calcLighting(pmin, pmax, fpmin, fpmax, propagate_shadow);
  162. return 0;
  163. }
  164. int LuaVoxelManip::l_set_lighting(lua_State *L)
  165. {
  166. NO_MAP_LOCK_REQUIRED;
  167. LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
  168. if (!o->is_mapgen_vm) {
  169. warningstream << "VoxelManip:set_lighting called for a non-mapgen "
  170. "VoxelManip object" << std::endl;
  171. return 0;
  172. }
  173. if (!lua_istable(L, 2))
  174. throw LuaError("VoxelManip:set_lighting called with missing parameter");
  175. u8 light;
  176. light = (getintfield_default(L, 2, "day", 0) & 0x0F);
  177. light |= (getintfield_default(L, 2, "night", 0) & 0x0F) << 4;
  178. MMVManip *vm = o->vm;
  179. v3s16 yblock = v3s16(0, 1, 0) * MAP_BLOCKSIZE;
  180. v3s16 pmin = lua_istable(L, 3) ? check_v3s16(L, 3) : vm->m_area.MinEdge + yblock;
  181. v3s16 pmax = lua_istable(L, 4) ? check_v3s16(L, 4) : vm->m_area.MaxEdge - yblock;
  182. sortBoxVerticies(pmin, pmax);
  183. if (!vm->m_area.contains(VoxelArea(pmin, pmax)))
  184. throw LuaError("Specified voxel area out of VoxelManipulator bounds");
  185. Mapgen mg;
  186. mg.vm = vm;
  187. mg.setLighting(light, pmin, pmax);
  188. return 0;
  189. }
  190. int LuaVoxelManip::l_get_light_data(lua_State *L)
  191. {
  192. NO_MAP_LOCK_REQUIRED;
  193. LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
  194. bool use_buffer = lua_istable(L, 2);
  195. MMVManip *vm = o->vm;
  196. u32 volume = vm->m_area.getVolume();
  197. if (use_buffer)
  198. lua_pushvalue(L, 2);
  199. else
  200. lua_createtable(L, volume, 0);
  201. for (u32 i = 0; i != volume; i++) {
  202. lua_Integer light = vm->m_data[i].param1;
  203. lua_pushinteger(L, light);
  204. lua_rawseti(L, -2, i + 1);
  205. }
  206. return 1;
  207. }
  208. int LuaVoxelManip::l_set_light_data(lua_State *L)
  209. {
  210. NO_MAP_LOCK_REQUIRED;
  211. LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
  212. MMVManip *vm = o->vm;
  213. if (!lua_istable(L, 2))
  214. throw LuaError("VoxelManip:set_light_data called with missing "
  215. "parameter");
  216. u32 volume = vm->m_area.getVolume();
  217. for (u32 i = 0; i != volume; i++) {
  218. lua_rawgeti(L, 2, i + 1);
  219. u8 light = lua_tointeger(L, -1);
  220. vm->m_data[i].param1 = light;
  221. lua_pop(L, 1);
  222. }
  223. return 0;
  224. }
  225. int LuaVoxelManip::l_get_param2_data(lua_State *L)
  226. {
  227. NO_MAP_LOCK_REQUIRED;
  228. LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
  229. bool use_buffer = lua_istable(L, 2);
  230. MMVManip *vm = o->vm;
  231. u32 volume = vm->m_area.getVolume();
  232. if (use_buffer)
  233. lua_pushvalue(L, 2);
  234. else
  235. lua_createtable(L, volume, 0);
  236. for (u32 i = 0; i != volume; i++) {
  237. lua_Integer param2 = vm->m_data[i].param2;
  238. lua_pushinteger(L, param2);
  239. lua_rawseti(L, -2, i + 1);
  240. }
  241. return 1;
  242. }
  243. int LuaVoxelManip::l_set_param2_data(lua_State *L)
  244. {
  245. NO_MAP_LOCK_REQUIRED;
  246. LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
  247. MMVManip *vm = o->vm;
  248. if (!lua_istable(L, 2))
  249. throw LuaError("VoxelManip:set_param2_data called with missing "
  250. "parameter");
  251. u32 volume = vm->m_area.getVolume();
  252. for (u32 i = 0; i != volume; i++) {
  253. lua_rawgeti(L, 2, i + 1);
  254. u8 param2 = lua_tointeger(L, -1);
  255. vm->m_data[i].param2 = param2;
  256. lua_pop(L, 1);
  257. }
  258. return 0;
  259. }
  260. int LuaVoxelManip::l_update_map(lua_State *L)
  261. {
  262. return 0;
  263. }
  264. int LuaVoxelManip::l_was_modified(lua_State *L)
  265. {
  266. NO_MAP_LOCK_REQUIRED;
  267. LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
  268. MMVManip *vm = o->vm;
  269. lua_pushboolean(L, vm->m_is_dirty);
  270. return 1;
  271. }
  272. int LuaVoxelManip::l_get_emerged_area(lua_State *L)
  273. {
  274. NO_MAP_LOCK_REQUIRED;
  275. LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
  276. push_v3s16(L, o->vm->m_area.MinEdge);
  277. push_v3s16(L, o->vm->m_area.MaxEdge);
  278. return 2;
  279. }
  280. LuaVoxelManip::LuaVoxelManip(MMVManip *mmvm, bool is_mg_vm) :
  281. is_mapgen_vm(is_mg_vm),
  282. vm(mmvm)
  283. {
  284. }
  285. LuaVoxelManip::LuaVoxelManip(Map *map) : vm(new MMVManip(map))
  286. {
  287. }
  288. LuaVoxelManip::LuaVoxelManip(Map *map, v3s16 p1, v3s16 p2)
  289. {
  290. vm = new MMVManip(map);
  291. v3s16 bp1 = getNodeBlockPos(p1);
  292. v3s16 bp2 = getNodeBlockPos(p2);
  293. sortBoxVerticies(bp1, bp2);
  294. vm->initialEmerge(bp1, bp2);
  295. }
  296. LuaVoxelManip::~LuaVoxelManip()
  297. {
  298. if (!is_mapgen_vm)
  299. delete vm;
  300. }
  301. // LuaVoxelManip()
  302. // Creates an LuaVoxelManip and leaves it on top of stack
  303. int LuaVoxelManip::create_object(lua_State *L)
  304. {
  305. GET_ENV_PTR;
  306. Map *map = &(env->getMap());
  307. LuaVoxelManip *o = (lua_istable(L, 1) && lua_istable(L, 2)) ?
  308. new LuaVoxelManip(map, check_v3s16(L, 1), check_v3s16(L, 2)) :
  309. new LuaVoxelManip(map);
  310. *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
  311. luaL_getmetatable(L, className);
  312. lua_setmetatable(L, -2);
  313. return 1;
  314. }
  315. void *LuaVoxelManip::packIn(lua_State *L, int idx)
  316. {
  317. LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, idx);
  318. if (o->is_mapgen_vm)
  319. throw LuaError("nope");
  320. return o->vm->clone();
  321. }
  322. void LuaVoxelManip::packOut(lua_State *L, void *ptr)
  323. {
  324. MMVManip *vm = reinterpret_cast<MMVManip*>(ptr);
  325. if (!L) {
  326. delete vm;
  327. return;
  328. }
  329. // Associate vmanip with map if the Lua env has one
  330. Environment *env = getEnv(L);
  331. if (env)
  332. vm->reparent(&(env->getMap()));
  333. LuaVoxelManip *o = new LuaVoxelManip(vm, false);
  334. *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
  335. luaL_getmetatable(L, className);
  336. lua_setmetatable(L, -2);
  337. }
  338. void LuaVoxelManip::Register(lua_State *L)
  339. {
  340. static const luaL_Reg metamethods[] = {
  341. {"__gc", gc_object},
  342. {0, 0}
  343. };
  344. registerClass(L, className, methods, metamethods);
  345. // Can be created from Lua (VoxelManip())
  346. lua_register(L, className, create_object);
  347. script_register_packer(L, className, packIn, packOut);
  348. }
  349. const char LuaVoxelManip::className[] = "VoxelManip";
  350. const luaL_Reg LuaVoxelManip::methods[] = {
  351. luamethod(LuaVoxelManip, read_from_map),
  352. luamethod(LuaVoxelManip, get_data),
  353. luamethod(LuaVoxelManip, set_data),
  354. luamethod(LuaVoxelManip, get_node_at),
  355. luamethod(LuaVoxelManip, set_node_at),
  356. luamethod(LuaVoxelManip, write_to_map),
  357. luamethod(LuaVoxelManip, update_map),
  358. luamethod(LuaVoxelManip, update_liquids),
  359. luamethod(LuaVoxelManip, calc_lighting),
  360. luamethod(LuaVoxelManip, set_lighting),
  361. luamethod(LuaVoxelManip, get_light_data),
  362. luamethod(LuaVoxelManip, set_light_data),
  363. luamethod(LuaVoxelManip, get_param2_data),
  364. luamethod(LuaVoxelManip, set_param2_data),
  365. luamethod(LuaVoxelManip, was_modified),
  366. luamethod(LuaVoxelManip, get_emerged_area),
  367. {0,0}
  368. };