1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14 
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 
20 #include "lua_api/l_particles.h"
21 #include "lua_api/l_object.h"
22 #include "lua_api/l_internal.h"
23 #include "common/c_converter.h"
24 #include "common/c_content.h"
25 #include "server.h"
26 #include "particles.h"
27 
28 // add_particle({pos=, velocity=, acceleration=, expirationtime=,
29 //     size=, collisiondetection=, collision_removal=, object_collision=,
30 //     vertical=, texture=, player=})
31 // pos/velocity/acceleration = {x=num, y=num, z=num}
32 // expirationtime = num (seconds)
33 // size = num
34 // collisiondetection = bool
35 // collision_removal = bool
36 // object_collision = bool
37 // vertical = bool
38 // texture = e.g."default_wood.png"
39 // animation = TileAnimation definition
40 // glow = num
l_add_particle(lua_State * L)41 int ModApiParticles::l_add_particle(lua_State *L)
42 {
43 	NO_MAP_LOCK_REQUIRED;
44 
45 	// Get parameters
46 	struct ParticleParameters p;
47 	std::string playername;
48 
49 	if (lua_gettop(L) > 1) // deprecated
50 	{
51 		log_deprecated(L, "Deprecated add_particle call with "
52 			"individual parameters instead of definition");
53 		p.pos = check_v3f(L, 1);
54 		p.vel = check_v3f(L, 2);
55 		p.acc = check_v3f(L, 3);
56 		p.expirationtime = luaL_checknumber(L, 4);
57 		p.size = luaL_checknumber(L, 5);
58 		p.collisiondetection = readParam<bool>(L, 6);
59 		p.texture = luaL_checkstring(L, 7);
60 		if (lua_gettop(L) == 8) // only spawn for a single player
61 			playername = luaL_checkstring(L, 8);
62 	}
63 	else if (lua_istable(L, 1))
64 	{
65 		lua_getfield(L, 1, "pos");
66 		if (lua_istable(L, -1))
67 			p.pos = check_v3f(L, -1);
68 		lua_pop(L, 1);
69 
70 		lua_getfield(L, 1, "vel");
71 		if (lua_istable(L, -1)) {
72 			p.vel = check_v3f(L, -1);
73 			log_deprecated(L, "The use of vel is deprecated. "
74 				"Use velocity instead");
75 		}
76 		lua_pop(L, 1);
77 
78 		lua_getfield(L, 1, "velocity");
79 		if (lua_istable(L, -1))
80 			p.vel = check_v3f(L, -1);
81 		lua_pop(L, 1);
82 
83 		lua_getfield(L, 1, "acc");
84 		if (lua_istable(L, -1)) {
85 			p.acc = check_v3f(L, -1);
86 			log_deprecated(L, "The use of acc is deprecated. "
87 				"Use acceleration instead");
88 		}
89 		lua_pop(L, 1);
90 
91 		lua_getfield(L, 1, "acceleration");
92 		if (lua_istable(L, -1))
93 			p.acc = check_v3f(L, -1);
94 		lua_pop(L, 1);
95 
96 		p.expirationtime = getfloatfield_default(L, 1, "expirationtime",
97 			p.expirationtime);
98 		p.size = getfloatfield_default(L, 1, "size", p.size);
99 		p.collisiondetection = getboolfield_default(L, 1,
100 			"collisiondetection", p.collisiondetection);
101 		p.collision_removal = getboolfield_default(L, 1,
102 			"collision_removal", p.collision_removal);
103 		p.object_collision = getboolfield_default(L, 1,
104 			"object_collision", p.object_collision);
105 		p.vertical = getboolfield_default(L, 1, "vertical", p.vertical);
106 
107 		lua_getfield(L, 1, "animation");
108 		p.animation = read_animation_definition(L, -1);
109 		lua_pop(L, 1);
110 
111 		p.texture = getstringfield_default(L, 1, "texture", p.texture);
112 		p.glow = getintfield_default(L, 1, "glow", p.glow);
113 
114 		lua_getfield(L, 1, "node");
115 		if (lua_istable(L, -1))
116 			p.node = readnode(L, -1, getGameDef(L)->ndef());
117 		lua_pop(L, 1);
118 
119 		p.node_tile = getintfield_default(L, 1, "node_tile", p.node_tile);
120 
121 		playername = getstringfield_default(L, 1, "playername", "");
122 	}
123 
124 	getServer(L)->spawnParticle(playername, p);
125 	return 1;
126 }
127 
128 // add_particlespawner({amount=, time=,
129 //				minpos=, maxpos=,
130 //				minvel=, maxvel=,
131 //				minacc=, maxacc=,
132 //				minexptime=, maxexptime=,
133 //				minsize=, maxsize=,
134 //				collisiondetection=,
135 //				collision_removal=,
136 //				object_collision=,
137 //				vertical=,
138 //				texture=,
139 //				player=})
140 // minpos/maxpos/minvel/maxvel/minacc/maxacc = {x=num, y=num, z=num}
141 // minexptime/maxexptime = num (seconds)
142 // minsize/maxsize = num
143 // collisiondetection = bool
144 // collision_removal = bool
145 // object_collision = bool
146 // vertical = bool
147 // texture = e.g."default_wood.png"
148 // animation = TileAnimation definition
149 // glow = num
l_add_particlespawner(lua_State * L)150 int ModApiParticles::l_add_particlespawner(lua_State *L)
151 {
152 	NO_MAP_LOCK_REQUIRED;
153 
154 	// Get parameters
155 	ParticleSpawnerParameters p;
156 	ServerActiveObject *attached = NULL;
157 	std::string playername;
158 
159 	if (lua_gettop(L) > 1) //deprecated
160 	{
161 		log_deprecated(L, "Deprecated add_particlespawner call with "
162 			"individual parameters instead of definition");
163 		p.amount = luaL_checknumber(L, 1);
164 		p.time = luaL_checknumber(L, 2);
165 		p.minpos = check_v3f(L, 3);
166 		p.maxpos = check_v3f(L, 4);
167 		p.minvel = check_v3f(L, 5);
168 		p.maxvel = check_v3f(L, 6);
169 		p.minacc = check_v3f(L, 7);
170 		p.maxacc = check_v3f(L, 8);
171 		p.minexptime = luaL_checknumber(L, 9);
172 		p.maxexptime = luaL_checknumber(L, 10);
173 		p.minsize = luaL_checknumber(L, 11);
174 		p.maxsize = luaL_checknumber(L, 12);
175 		p.collisiondetection = readParam<bool>(L, 13);
176 		p.texture = luaL_checkstring(L, 14);
177 		if (lua_gettop(L) == 15) // only spawn for a single player
178 			playername = luaL_checkstring(L, 15);
179 	}
180 	else if (lua_istable(L, 1))
181 	{
182 		p.amount = getintfield_default(L, 1, "amount", p.amount);
183 		p.time = getfloatfield_default(L, 1, "time", p.time);
184 
185 		lua_getfield(L, 1, "minpos");
186 		if (lua_istable(L, -1))
187 			p.minpos = check_v3f(L, -1);
188 		lua_pop(L, 1);
189 
190 		lua_getfield(L, 1, "maxpos");
191 		if (lua_istable(L, -1))
192 			p.maxpos = check_v3f(L, -1);
193 		lua_pop(L, 1);
194 
195 		lua_getfield(L, 1, "minvel");
196 		if (lua_istable(L, -1))
197 			p.minvel = check_v3f(L, -1);
198 		lua_pop(L, 1);
199 
200 		lua_getfield(L, 1, "maxvel");
201 		if (lua_istable(L, -1))
202 			p.maxvel = check_v3f(L, -1);
203 		lua_pop(L, 1);
204 
205 		lua_getfield(L, 1, "minacc");
206 		if (lua_istable(L, -1))
207 			p.minacc = check_v3f(L, -1);
208 		lua_pop(L, 1);
209 
210 		lua_getfield(L, 1, "maxacc");
211 		if (lua_istable(L, -1))
212 			p.maxacc = check_v3f(L, -1);
213 		lua_pop(L, 1);
214 
215 		p.minexptime = getfloatfield_default(L, 1, "minexptime", p.minexptime);
216 		p.maxexptime = getfloatfield_default(L, 1, "maxexptime", p.maxexptime);
217 		p.minsize = getfloatfield_default(L, 1, "minsize", p.minsize);
218 		p.maxsize = getfloatfield_default(L, 1, "maxsize", p.maxsize);
219 		p.collisiondetection = getboolfield_default(L, 1,
220 			"collisiondetection", p.collisiondetection);
221 		p.collision_removal = getboolfield_default(L, 1,
222 			"collision_removal", p.collision_removal);
223 		p.object_collision = getboolfield_default(L, 1,
224 			"object_collision", p.object_collision);
225 
226 		lua_getfield(L, 1, "animation");
227 		p.animation = read_animation_definition(L, -1);
228 		lua_pop(L, 1);
229 
230 		lua_getfield(L, 1, "attached");
231 		if (!lua_isnil(L, -1)) {
232 			ObjectRef *ref = ObjectRef::checkobject(L, -1);
233 			lua_pop(L, 1);
234 			attached = ObjectRef::getobject(ref);
235 		}
236 
237 		p.vertical = getboolfield_default(L, 1, "vertical", p.vertical);
238 		p.texture = getstringfield_default(L, 1, "texture", p.texture);
239 		playername = getstringfield_default(L, 1, "playername", "");
240 		p.glow = getintfield_default(L, 1, "glow", p.glow);
241 
242 		lua_getfield(L, 1, "node");
243 		if (lua_istable(L, -1))
244 			p.node = readnode(L, -1, getGameDef(L)->ndef());
245 		lua_pop(L, 1);
246 
247 		p.node_tile = getintfield_default(L, 1, "node_tile", p.node_tile);
248 	}
249 
250 	u32 id = getServer(L)->addParticleSpawner(p, attached, playername);
251 	lua_pushnumber(L, id);
252 
253 	return 1;
254 }
255 
256 // delete_particlespawner(id, player)
257 // player (string) is optional
l_delete_particlespawner(lua_State * L)258 int ModApiParticles::l_delete_particlespawner(lua_State *L)
259 {
260 	NO_MAP_LOCK_REQUIRED;
261 
262 	// Get parameters
263 	u32 id = luaL_checknumber(L, 1);
264 	std::string playername;
265 	if (lua_gettop(L) == 2) {
266 		playername = luaL_checkstring(L, 2);
267 	}
268 
269 	getServer(L)->deleteParticleSpawner(playername, id);
270 	return 1;
271 }
272 
Initialize(lua_State * L,int top)273 void ModApiParticles::Initialize(lua_State *L, int top)
274 {
275 	API_FCT(add_particle);
276 	API_FCT(add_particlespawner);
277 	API_FCT(delete_particlespawner);
278 }
279 
280