Skip to content

Commit 5dab742

Browse files
red-001nerzhul
authored andcommittedJan 20, 2018
[CSM] Add functions to create particles and particlespawners. (#6072)
1 parent da80e8a commit 5dab742

File tree

10 files changed

+341
-13
lines changed

10 files changed

+341
-13
lines changed
 

‎build/android/jni/Android.mk

+1
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ LOCAL_SRC_FILES += \
327327
jni/src/script/lua_api/l_noise.cpp \
328328
jni/src/script/lua_api/l_object.cpp \
329329
jni/src/script/lua_api/l_particles.cpp \
330+
jni/src/script/lua_api/l_particles_local.cpp\
330331
jni/src/script/lua_api/l_rollback.cpp \
331332
jni/src/script/lua_api/l_server.cpp \
332333
jni/src/script/lua_api/l_settings.cpp \

‎doc/client_lua_api.txt

+64
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,16 @@ Call these functions only at load time!
787787
* You should use a minetest.register_on_connect(function() ... end) to perform
788788
a successful channel join on client startup.
789789

790+
### Particles
791+
* `minetest.add_particle(particle definition)`
792+
793+
* `minetest.add_particlespawner(particlespawner definition)`
794+
* Add a `ParticleSpawner`, an object that spawns an amount of particles over `time` seconds
795+
* Returns an `id`, and -1 if adding didn't succeed
796+
797+
* `minetest.delete_particlespawner(id)`
798+
* Delete `ParticleSpawner` with `id` (return value from `minetest.add_particlespawner`)
799+
790800
### Misc.
791801
* `minetest.parse_json(string[, nullvalue])`: returns something
792802
* Convert a string containing JSON data into the Lua equivalent
@@ -1318,3 +1328,57 @@ Displays distance to selected world position.
13181328
* `number:` An integer containing the RGB value of the color used to draw the text.
13191329
* `world_pos`: World position of the waypoint.
13201330

1331+
### Particle definition (`add_particle`)
1332+
1333+
{
1334+
pos = {x=0, y=0, z=0},
1335+
velocity = {x=0, y=0, z=0},
1336+
acceleration = {x=0, y=0, z=0},
1337+
-- ^ Spawn particle at pos with velocity and acceleration
1338+
expirationtime = 1,
1339+
-- ^ Disappears after expirationtime seconds
1340+
size = 1,
1341+
collisiondetection = false,
1342+
-- ^ collisiondetection: if true collides with physical objects
1343+
collision_removal = false,
1344+
-- ^ collision_removal: if true then particle is removed when it collides,
1345+
-- ^ requires collisiondetection = true to have any effect
1346+
vertical = false,
1347+
-- ^ vertical: if true faces player using y axis only
1348+
texture = "image.png",
1349+
-- ^ Uses texture (string)
1350+
animation = {Tile Animation definition},
1351+
-- ^ optional, specifies how to animate the particle texture
1352+
glow = 0
1353+
-- ^ optional, specify particle self-luminescence in darkness
1354+
}
1355+
1356+
### `ParticleSpawner` definition (`add_particlespawner`)
1357+
1358+
{
1359+
amount = 1,
1360+
time = 1,
1361+
-- ^ If time is 0 has infinite lifespan and spawns the amount on a per-second base
1362+
minpos = {x=0, y=0, z=0},
1363+
maxpos = {x=0, y=0, z=0},
1364+
minvel = {x=0, y=0, z=0},
1365+
maxvel = {x=0, y=0, z=0},
1366+
minacc = {x=0, y=0, z=0},
1367+
maxacc = {x=0, y=0, z=0},
1368+
minexptime = 1,
1369+
maxexptime = 1,
1370+
minsize = 1,
1371+
maxsize = 1,
1372+
-- ^ The particle's properties are random values in between the bounds:
1373+
-- ^ minpos/maxpos, minvel/maxvel (velocity), minacc/maxacc (acceleration),
1374+
-- ^ minsize/maxsize, minexptime/maxexptime (expirationtime)
1375+
collisiondetection = false,
1376+
-- ^ collisiondetection: if true uses collision detection
1377+
collision_removal = false,
1378+
-- ^ collision_removal: if true then particle is removed when it collides,
1379+
-- ^ requires collisiondetection = true to have any effect
1380+
vertical = false,
1381+
-- ^ vertical: if true faces player using y axis only
1382+
texture = "image.png",
1383+
-- ^ Uses texture (string)
1384+
}

‎src/client.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -554,8 +554,10 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
554554
// And relations to objects
555555
std::unordered_map<int, u16> m_sounds_to_objects;
556556

557-
// HUD
558-
// Mapping from server hud ids to internal hud ids
557+
// CSM/client IDs to SSM/server IDs Mapping
558+
// Map server particle spawner IDs to client IDs
559+
std::unordered_map<u32, u32> m_particles_server_to_client;
560+
// Map server hud ids to client hud ids
559561
std::unordered_map<u32, u32> m_hud_server_to_client;
560562

561563
// Privileges

‎src/network/clientpackethandler.cpp

+16-6
Original file line numberDiff line numberDiff line change
@@ -956,15 +956,15 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
956956
float minsize;
957957
float maxsize;
958958
bool collisiondetection;
959-
u32 id;
959+
u32 server_id;
960960

961961
*pkt >> amount >> spawntime >> minpos >> maxpos >> minvel >> maxvel
962962
>> minacc >> maxacc >> minexptime >> maxexptime >> minsize
963963
>> maxsize >> collisiondetection;
964964

965965
std::string texture = pkt->readLongString();
966966

967-
*pkt >> id;
967+
*pkt >> server_id;
968968

969969
bool vertical = false;
970970
bool collision_removal = false;
@@ -984,6 +984,9 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
984984
glow = readU8(is);
985985
} catch (...) {}
986986

987+
u32 client_id = m_particle_manager.getSpawnerId();
988+
m_particles_server_to_client[server_id] = client_id;
989+
987990
ClientEvent *event = new ClientEvent();
988991
event->type = CE_ADD_PARTICLESPAWNER;
989992
event->add_particlespawner.amount = amount;
@@ -1003,7 +1006,7 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
10031006
event->add_particlespawner.attached_id = attached_id;
10041007
event->add_particlespawner.vertical = vertical;
10051008
event->add_particlespawner.texture = new std::string(texture);
1006-
event->add_particlespawner.id = id;
1009+
event->add_particlespawner.id = client_id;
10071010
event->add_particlespawner.animation = animation;
10081011
event->add_particlespawner.glow = glow;
10091012

@@ -1013,12 +1016,19 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
10131016

10141017
void Client::handleCommand_DeleteParticleSpawner(NetworkPacket* pkt)
10151018
{
1016-
u32 id;
1017-
*pkt >> id;
1019+
u32 server_id;
1020+
*pkt >> server_id;
1021+
1022+
u32 client_id;
1023+
auto i = m_particles_server_to_client.find(server_id);
1024+
if (i != m_particles_server_to_client.end())
1025+
client_id = i->second;
1026+
else
1027+
return;
10181028

10191029
ClientEvent *event = new ClientEvent();
10201030
event->type = CE_DELETE_PARTICLESPAWNER;
1021-
event->delete_particlespawner.id = id;
1031+
event->delete_particlespawner.id = client_id;
10221032

10231033
m_client_event_queue.push(event);
10241034
}

‎src/particles.h

+8
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,14 @@ friend class ParticleSpawner;
192192
void addNodeParticle(IGameDef *gamedef, LocalPlayer *player, v3s16 pos,
193193
const MapNode &n, const ContentFeatures &f);
194194

195+
u32 getSpawnerId() const
196+
{
197+
for (u32 id = 0;; ++id) { // look for unused particlespawner id
198+
if (m_particle_spawners.find(id) == m_particle_spawners.end())
199+
return id;
200+
}
201+
}
202+
195203
protected:
196204
void addParticle(Particle* toadd);
197205

‎src/script/lua_api/CMakeLists.txt

+6-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ set(common_SCRIPT_LUA_API_SRCS
33
${CMAKE_CURRENT_SOURCE_DIR}/l_base.cpp
44
${CMAKE_CURRENT_SOURCE_DIR}/l_craft.cpp
55
${CMAKE_CURRENT_SOURCE_DIR}/l_env.cpp
6+
${CMAKE_CURRENT_SOURCE_DIR}/l_http.cpp
67
${CMAKE_CURRENT_SOURCE_DIR}/l_inventory.cpp
78
${CMAKE_CURRENT_SOURCE_DIR}/l_item.cpp
89
${CMAKE_CURRENT_SOURCE_DIR}/l_itemstackmeta.cpp
@@ -16,19 +17,19 @@ set(common_SCRIPT_LUA_API_SRCS
1617
${CMAKE_CURRENT_SOURCE_DIR}/l_particles.cpp
1718
${CMAKE_CURRENT_SOURCE_DIR}/l_rollback.cpp
1819
${CMAKE_CURRENT_SOURCE_DIR}/l_server.cpp
20+
${CMAKE_CURRENT_SOURCE_DIR}/l_settings.cpp
1921
${CMAKE_CURRENT_SOURCE_DIR}/l_storage.cpp
2022
${CMAKE_CURRENT_SOURCE_DIR}/l_util.cpp
2123
${CMAKE_CURRENT_SOURCE_DIR}/l_vmanip.cpp
22-
${CMAKE_CURRENT_SOURCE_DIR}/l_settings.cpp
23-
${CMAKE_CURRENT_SOURCE_DIR}/l_http.cpp
2424
PARENT_SCOPE)
2525

2626
set(client_SCRIPT_LUA_API_SRCS
27+
${CMAKE_CURRENT_SOURCE_DIR}/l_camera.cpp
2728
${CMAKE_CURRENT_SOURCE_DIR}/l_client.cpp
29+
${CMAKE_CURRENT_SOURCE_DIR}/l_localplayer.cpp
2830
${CMAKE_CURRENT_SOURCE_DIR}/l_mainmenu.cpp
2931
${CMAKE_CURRENT_SOURCE_DIR}/l_minimap.cpp
30-
${CMAKE_CURRENT_SOURCE_DIR}/l_storage.cpp
32+
${CMAKE_CURRENT_SOURCE_DIR}/l_particles_local.cpp
3133
${CMAKE_CURRENT_SOURCE_DIR}/l_sound.cpp
32-
${CMAKE_CURRENT_SOURCE_DIR}/l_localplayer.cpp
33-
${CMAKE_CURRENT_SOURCE_DIR}/l_camera.cpp
34+
${CMAKE_CURRENT_SOURCE_DIR}/l_storage.cpp
3435
PARENT_SCOPE)
+206
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
/*
2+
Minetest
3+
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4+
Copyright (C) 2017 red-001 <red-001@outlook.ie>
5+
6+
This program is free software; you can redistribute it and/or modify
7+
it under the terms of the GNU Lesser General Public License as published by
8+
the Free Software Foundation; either version 2.1 of the License, or
9+
(at your option) any later version.
10+
11+
This program is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU Lesser General Public License for more details.
15+
16+
You should have received a copy of the GNU Lesser General Public License along
17+
with this program; if not, write to the Free Software Foundation, Inc.,
18+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19+
*/
20+
21+
#include "lua_api/l_particles_local.h"
22+
#include "common/c_content.h"
23+
#include "common/c_converter.h"
24+
#include "lua_api/l_internal.h"
25+
#include "lua_api/l_object.h"
26+
#include "particles.h"
27+
#include "client.h"
28+
#include "client/clientevent.h"
29+
30+
int ModApiParticlesLocal::l_add_particle(lua_State *L)
31+
{
32+
luaL_checktype(L, 1, LUA_TTABLE);
33+
34+
// Get parameters
35+
v3f pos, vel, acc;
36+
float expirationtime, size;
37+
bool collisiondetection, vertical, collision_removal;
38+
39+
struct TileAnimationParams animation;
40+
animation.type = TAT_NONE;
41+
42+
std::string texture;
43+
44+
u8 glow;
45+
46+
lua_getfield(L, 1, "pos");
47+
pos = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
48+
lua_pop(L, 1);
49+
50+
lua_getfield(L, 1, "velocity");
51+
vel = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
52+
lua_pop(L, 1);
53+
54+
lua_getfield(L, 1, "acceleration");
55+
acc = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
56+
lua_pop(L, 1);
57+
58+
expirationtime = getfloatfield_default(L, 1, "expirationtime", 1);
59+
size = getfloatfield_default(L, 1, "size", 1);
60+
collisiondetection = getboolfield_default(L, 1, "collisiondetection", false);
61+
collision_removal = getboolfield_default(L, 1, "collision_removal", false);
62+
vertical = getboolfield_default(L, 1, "vertical", false);
63+
64+
lua_getfield(L, 1, "animation");
65+
animation = read_animation_definition(L, -1);
66+
lua_pop(L, 1);
67+
68+
texture = getstringfield_default(L, 1, "texture", "");
69+
70+
glow = getintfield_default(L, 1, "glow", 0);
71+
72+
ClientEvent *event = new ClientEvent();
73+
event->type = CE_SPAWN_PARTICLE;
74+
event->spawn_particle.pos = new v3f (pos);
75+
event->spawn_particle.vel = new v3f (vel);
76+
event->spawn_particle.acc = new v3f (acc);
77+
event->spawn_particle.expirationtime = expirationtime;
78+
event->spawn_particle.size = size;
79+
event->spawn_particle.collisiondetection = collisiondetection;
80+
event->spawn_particle.collision_removal = collision_removal;
81+
event->spawn_particle.vertical = vertical;
82+
event->spawn_particle.texture = new std::string(texture);
83+
event->spawn_particle.animation = animation;
84+
event->spawn_particle.glow = glow;
85+
getClient(L)->pushToEventQueue(event);
86+
87+
return 0;
88+
}
89+
90+
int ModApiParticlesLocal::l_add_particlespawner(lua_State *L)
91+
{
92+
luaL_checktype(L, 1, LUA_TTABLE);
93+
// Get parameters
94+
u16 amount;
95+
v3f minpos, maxpos, minvel, maxvel, minacc, maxacc;
96+
float time, minexptime, maxexptime, minsize, maxsize;
97+
bool collisiondetection, vertical, collision_removal;
98+
99+
struct TileAnimationParams animation;
100+
animation.type = TAT_NONE;
101+
// TODO: Implement this when there is a way to get an objectref.
102+
// ServerActiveObject *attached = NULL;
103+
std::string texture;
104+
u8 glow;
105+
106+
amount = getintfield_default(L, 1, "amount", 1);
107+
time = getfloatfield_default(L, 1, "time", 1);
108+
109+
lua_getfield(L, 1, "minpos");
110+
minpos = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
111+
lua_pop(L, 1);
112+
113+
lua_getfield(L, 1, "maxpos");
114+
maxpos = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
115+
lua_pop(L, 1);
116+
117+
lua_getfield(L, 1, "minvel");
118+
minvel = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
119+
lua_pop(L, 1);
120+
121+
lua_getfield(L, 1, "maxvel");
122+
maxvel = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
123+
lua_pop(L, 1);
124+
125+
lua_getfield(L, 1, "minacc");
126+
minacc = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
127+
lua_pop(L, 1);
128+
129+
lua_getfield(L, 1, "maxacc");
130+
maxacc = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
131+
lua_pop(L, 1);
132+
133+
minexptime = getfloatfield_default(L, 1, "minexptime", 1);
134+
maxexptime = getfloatfield_default(L, 1, "maxexptime", 1);
135+
minsize = getfloatfield_default(L, 1, "minsize", 1);
136+
maxsize = getfloatfield_default(L, 1, "maxsize", 1);
137+
138+
collisiondetection = getboolfield_default(L, 1, "collisiondetection", false);
139+
collision_removal = getboolfield_default(L, 1, "collision_removal", false);
140+
vertical = getboolfield_default(L, 1, "vertical", false);
141+
142+
lua_getfield(L, 1, "animation");
143+
animation = read_animation_definition(L, -1);
144+
lua_pop(L, 1);
145+
146+
// TODO: Implement this when a way to get an objectref on the client is added
147+
// lua_getfield(L, 1, "attached");
148+
// if (!lua_isnil(L, -1)) {
149+
// ObjectRef *ref = ObjectRef::checkobject(L, -1);
150+
// lua_pop(L, 1);
151+
// attached = ObjectRef::getobject(ref);
152+
// }
153+
154+
texture = getstringfield_default(L, 1, "texture", "");
155+
glow = getintfield_default(L, 1, "glow", 0);
156+
157+
u32 id = getClient(L)->getParticleManager()->getSpawnerId();
158+
159+
ClientEvent *event = new ClientEvent();
160+
event->type = CE_ADD_PARTICLESPAWNER;
161+
event->add_particlespawner.amount = amount;
162+
event->add_particlespawner.spawntime = time;
163+
event->add_particlespawner.minpos = new v3f (minpos);
164+
event->add_particlespawner.maxpos = new v3f (maxpos);
165+
event->add_particlespawner.minvel = new v3f (minvel);
166+
event->add_particlespawner.maxvel = new v3f (maxvel);
167+
event->add_particlespawner.minacc = new v3f (minacc);
168+
event->add_particlespawner.maxacc = new v3f (maxacc);
169+
event->add_particlespawner.minexptime = minexptime;
170+
event->add_particlespawner.maxexptime = maxexptime;
171+
event->add_particlespawner.minsize = minsize;
172+
event->add_particlespawner.maxsize = maxsize;
173+
event->add_particlespawner.collisiondetection = collisiondetection;
174+
event->add_particlespawner.collision_removal = collision_removal;
175+
event->add_particlespawner.attached_id = 0;
176+
event->add_particlespawner.vertical = vertical;
177+
event->add_particlespawner.texture = new std::string(texture);
178+
event->add_particlespawner.id = id;
179+
event->add_particlespawner.animation = animation;
180+
event->add_particlespawner.glow = glow;
181+
182+
getClient(L)->pushToEventQueue(event);
183+
lua_pushnumber(L, id);
184+
185+
return 1;
186+
}
187+
188+
int ModApiParticlesLocal::l_delete_particlespawner(lua_State *L)
189+
{
190+
// Get parameters
191+
u32 id = luaL_checknumber(L, 1);
192+
193+
ClientEvent *event = new ClientEvent();
194+
event->type = CE_DELETE_PARTICLESPAWNER;
195+
event->delete_particlespawner.id = id;
196+
197+
getClient(L)->pushToEventQueue(event);
198+
return 0;
199+
}
200+
201+
void ModApiParticlesLocal::Initialize(lua_State *L, int top)
202+
{
203+
API_FCT(add_particle);
204+
API_FCT(add_particlespawner);
205+
API_FCT(delete_particlespawner);
206+
}
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
Minetest
3+
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4+
Copyright (C) 2017 red-001 <red-001@outlook.ie>
5+
6+
This program is free software; you can redistribute it and/or modify
7+
it under the terms of the GNU Lesser General Public License as published by
8+
the Free Software Foundation; either version 2.1 of the License, or
9+
(at your option) any later version.
10+
11+
This program is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU Lesser General Public License for more details.
15+
16+
You should have received a copy of the GNU Lesser General Public License along
17+
with this program; if not, write to the Free Software Foundation, Inc.,
18+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19+
*/
20+
21+
#include "lua_api/l_base.h"
22+
23+
class ModApiParticlesLocal : public ModApiBase
24+
{
25+
private:
26+
static int l_add_particle(lua_State *L);
27+
static int l_add_particlespawner(lua_State *L);
28+
static int l_delete_particlespawner(lua_State *L);
29+
30+
public:
31+
static void Initialize(lua_State *L, int top);
32+
};

‎src/script/scripting_client.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2323
#include "cpp_api/s_internal.h"
2424
#include "lua_api/l_client.h"
2525
#include "lua_api/l_env.h"
26+
#include "lua_api/l_item.h"
2627
#include "lua_api/l_minimap.h"
2728
#include "lua_api/l_modchannels.h"
29+
#include "lua_api/l_particles_local.h"
2830
#include "lua_api/l_storage.h"
2931
#include "lua_api/l_sound.h"
3032
#include "lua_api/l_util.h"
@@ -77,6 +79,7 @@ void ClientScripting::InitializeModApi(lua_State *L, int top)
7779
ModApiStorage::Initialize(L, top);
7880
ModApiEnvMod::InitializeClient(L, top);
7981
ModApiChannels::Initialize(L, top);
82+
ModApiParticlesLocal::Initialize(L, top);
8083
}
8184

8285
void ClientScripting::on_client_ready(LocalPlayer *localplayer)

‎util/travis/clang-format-whitelist.txt

+1
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ src/script/lua_api/l_object.cpp
294294
src/script/lua_api/l_object.h
295295
src/script/lua_api/l_particles.cpp
296296
src/script/lua_api/l_particles.h
297+
src/script/lua_api/l_particles_local.cpp
297298
src/script/lua_api/l_rollback.cpp
298299
src/script/lua_api/l_rollback.h
299300
src/script/lua_api/l_server.cpp

0 commit comments

Comments
 (0)