Skip to content

Commit e1ff5b1

Browse files
JeijaPilzAdam
authored andcommittedMar 23, 2013
Allow spawning particles from the server, from lua
Spawn single particles or make use of ParticleSpawner for many randomly spawned particles. Accessible in Lua using minetest.spawn_particle and minetest.add_particlespawner. Increase Protocol Version to 17. Conflicts: src/clientserver.h
1 parent ab57fda commit e1ff5b1

13 files changed

+1059
-55
lines changed
 

‎doc/lua_api.txt

+31
Original file line numberDiff line numberDiff line change
@@ -1028,6 +1028,37 @@ minetest.get_ban_description(ip_or_name) -> ban description (string)
10281028
minetest.ban_player(name) -> ban a player
10291029
minetest.unban_player_or_ip(name) -> unban player or IP address
10301030

1031+
Particles:
1032+
minetest.add_particle(pos, velocity, acceleration, expirationtime,
1033+
size, collisiondetection, texture, playername)
1034+
^ Spawn particle at pos with velocity and acceleration
1035+
^ Disappears after expirationtime seconds
1036+
^ collisiondetection: if true collides with physical objects
1037+
^ Uses texture (string)
1038+
^ Playername is optional, if specified spawns particle only on the player's client
1039+
1040+
minetest.add_particlespawner(amount, time,
1041+
minpos, maxpos,
1042+
minvel, maxvel,
1043+
minacc, maxacc,
1044+
minexptime, maxexptime,
1045+
minsize, maxsize,
1046+
collisiondetection, texture, playername)
1047+
^ Add a particlespawner, an object that spawns an amount of particles over time seconds
1048+
^ The particle's properties are random values in between the boundings:
1049+
^ minpos/maxpos, minvel/maxvel (velocity), minacc/maxacc (acceleration),
1050+
^ minsize/maxsize, minexptime/maxexptime (expirationtime)
1051+
^ collisiondetection: if true uses collisiondetection
1052+
^ Uses texture (string)
1053+
^ Playername is optional, if specified spawns particle only on the player's client
1054+
^ If time is 0 has infinite lifespan and spawns the amount on a per-second base
1055+
^ Returns and id
1056+
1057+
minetest.delete_particlespawner(id, player)
1058+
^ Delete ParticleSpawner with id (return value from add_particlespawner)
1059+
^ If playername is specified, only deletes on the player's client,
1060+
^ otherwise on all clients
1061+
10311062
Random:
10321063
minetest.get_connected_players() -> list of ObjectRefs
10331064
minetest.hash_node_position({x=,y=,z=}) -> 48-bit integer

‎src/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ set(common_SRCS
219219
scriptapi_object.cpp
220220
scriptapi_nodemeta.cpp
221221
scriptapi_inventory.cpp
222+
scriptapi_particles.cpp
222223
scriptapi.cpp
223224
script.cpp
224225
log.cpp

‎src/client.cpp

+83
Original file line numberDiff line numberDiff line change
@@ -1936,6 +1936,89 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
19361936
event.show_formspec.formname = new std::string(formname);
19371937
m_client_event_queue.push_back(event);
19381938
}
1939+
else if(command == TOCLIENT_SPAWN_PARTICLE)
1940+
{
1941+
std::string datastring((char*)&data[2], datasize-2);
1942+
std::istringstream is(datastring, std::ios_base::binary);
1943+
1944+
v3f pos = readV3F1000(is);
1945+
v3f vel = readV3F1000(is);
1946+
v3f acc = readV3F1000(is);
1947+
float expirationtime = readF1000(is);
1948+
float size = readF1000(is);
1949+
bool collisiondetection = readU8(is);
1950+
std::string texture = deSerializeLongString(is);
1951+
1952+
ClientEvent event;
1953+
event.type = CE_SPAWN_PARTICLE;
1954+
event.spawn_particle.pos = new v3f (pos);
1955+
event.spawn_particle.vel = new v3f (vel);
1956+
event.spawn_particle.acc = new v3f (acc);
1957+
1958+
event.spawn_particle.expirationtime = expirationtime;
1959+
event.spawn_particle.size = size;
1960+
event.add_particlespawner.collisiondetection =
1961+
collisiondetection;
1962+
event.spawn_particle.texture = new std::string(texture);
1963+
1964+
m_client_event_queue.push_back(event);
1965+
}
1966+
else if(command == TOCLIENT_ADD_PARTICLESPAWNER)
1967+
{
1968+
std::string datastring((char*)&data[2], datasize-2);
1969+
std::istringstream is(datastring, std::ios_base::binary);
1970+
1971+
u16 amount = readU16(is);
1972+
float spawntime = readF1000(is);
1973+
v3f minpos = readV3F1000(is);
1974+
v3f maxpos = readV3F1000(is);
1975+
v3f minvel = readV3F1000(is);
1976+
v3f maxvel = readV3F1000(is);
1977+
v3f minacc = readV3F1000(is);
1978+
v3f maxacc = readV3F1000(is);
1979+
float minexptime = readF1000(is);
1980+
float maxexptime = readF1000(is);
1981+
float minsize = readF1000(is);
1982+
float maxsize = readF1000(is);
1983+
bool collisiondetection = readU8(is);
1984+
std::string texture = deSerializeLongString(is);
1985+
u32 id = readU32(is);
1986+
1987+
ClientEvent event;
1988+
event.type = CE_ADD_PARTICLESPAWNER;
1989+
event.add_particlespawner.amount = amount;
1990+
event.add_particlespawner.spawntime = spawntime;
1991+
1992+
event.add_particlespawner.minpos = new v3f (minpos);
1993+
event.add_particlespawner.maxpos = new v3f (maxpos);
1994+
event.add_particlespawner.minvel = new v3f (minvel);
1995+
event.add_particlespawner.maxvel = new v3f (maxvel);
1996+
event.add_particlespawner.minacc = new v3f (minacc);
1997+
event.add_particlespawner.maxacc = new v3f (maxacc);
1998+
1999+
event.add_particlespawner.minexptime = minexptime;
2000+
event.add_particlespawner.maxexptime = maxexptime;
2001+
event.add_particlespawner.minsize = minsize;
2002+
event.add_particlespawner.maxsize = maxsize;
2003+
event.add_particlespawner.collisiondetection = collisiondetection;
2004+
event.add_particlespawner.texture = new std::string(texture);
2005+
event.add_particlespawner.id = id;
2006+
2007+
m_client_event_queue.push_back(event);
2008+
}
2009+
else if(command == TOCLIENT_DELETE_PARTICLESPAWNER)
2010+
{
2011+
std::string datastring((char*)&data[2], datasize-2);
2012+
std::istringstream is(datastring, std::ios_base::binary);
2013+
2014+
u32 id = readU16(is);
2015+
2016+
ClientEvent event;
2017+
event.type = CE_DELETE_PARTICLESPAWNER;
2018+
event.delete_particlespawner.id = id;
2019+
2020+
m_client_event_queue.push_back(event);
2021+
}
19392022
else
19402023
{
19412024
infostream<<"Client: Ignoring unknown command "

‎src/client.h

+33-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,10 @@ enum ClientEventType
157157
CE_PLAYER_FORCE_MOVE,
158158
CE_DEATHSCREEN,
159159
CE_TEXTURES_UPDATED,
160-
CE_SHOW_FORMSPEC
160+
CE_SHOW_FORMSPEC,
161+
CE_SPAWN_PARTICLE,
162+
CE_ADD_PARTICLESPAWNER,
163+
CE_DELETE_PARTICLESPAWNER
161164
};
162165

163166
struct ClientEvent
@@ -185,6 +188,35 @@ struct ClientEvent
185188
} show_formspec;
186189
struct{
187190
} textures_updated;
191+
struct{
192+
v3f *pos;
193+
v3f *vel;
194+
v3f *acc;
195+
f32 expirationtime;
196+
f32 size;
197+
bool collisiondetection;
198+
std::string *texture;
199+
} spawn_particle;
200+
struct{
201+
u16 amount;
202+
f32 spawntime;
203+
v3f *minpos;
204+
v3f *maxpos;
205+
v3f *minvel;
206+
v3f *maxvel;
207+
v3f *minacc;
208+
v3f *maxacc;
209+
f32 minexptime;
210+
f32 maxexptime;
211+
f32 minsize;
212+
f32 maxsize;
213+
bool collisiondetection;
214+
std::string *texture;
215+
u32 id;
216+
} add_particlespawner;
217+
struct{
218+
u32 id;
219+
} delete_particlespawner;
188220
};
189221
};
190222

‎src/clientserver.h

+44
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed);
8282
PROTOCOL_VERSION 17:
8383
Serialization format change: include backface_culling flag in TileDef
8484
Added rightclickable field in nodedef
85+
TOCLIENT_SPAWN_PARTICLE
86+
TOCLIENT_ADD_PARTICLESPAWNER
87+
TOCLIENT_DELETE_PARTICLESPAWNER
8588
*/
8689

8790
#define LATEST_PROTOCOL_VERSION 17
@@ -359,6 +362,7 @@ enum ToClientCommand
359362
u8[len] name
360363
[2] serialized inventory
361364
*/
365+
362366
TOCLIENT_SHOW_FORMSPEC = 0x44,
363367
/*
364368
[0] u16 command
@@ -384,6 +388,46 @@ enum ToClientCommand
384388
f1000 movement_liquid_sink
385389
f1000 movement_gravity
386390
*/
391+
392+
TOCLIENT_SPAWN_PARTICLE = 0x46,
393+
/*
394+
u16 command
395+
v3f1000 pos
396+
v3f1000 velocity
397+
v3f1000 acceleration
398+
f1000 expirationtime
399+
f1000 size
400+
u8 bool collisiondetection
401+
u32 len
402+
u8[len] texture
403+
*/
404+
405+
TOCLIENT_ADD_PARTICLESPAWNER = 0x47,
406+
/*
407+
u16 command
408+
u16 amount
409+
f1000 spawntime
410+
v3f1000 minpos
411+
v3f1000 maxpos
412+
v3f1000 minvel
413+
v3f1000 maxvel
414+
v3f1000 minacc
415+
v3f1000 maxacc
416+
f1000 minexptime
417+
f1000 maxexptime
418+
f1000 minsize
419+
f1000 maxsize
420+
u8 bool collisiondetection
421+
u32 len
422+
u8[len] texture
423+
u32 id
424+
*/
425+
426+
TOCLIENT_DELETE_PARTICLESPAWNER = 0x48,
427+
/*
428+
u16 command
429+
u32 id
430+
*/
387431
};
388432

389433
enum ToServerCommand

‎src/game.cpp

+47-2
Original file line numberDiff line numberDiff line change
@@ -2186,6 +2186,47 @@ void the_game(
21862186
{
21872187
update_wielded_item_trigger = true;
21882188
}
2189+
else if(event.type == CE_SPAWN_PARTICLE)
2190+
{
2191+
LocalPlayer* player = client.getEnv().getLocalPlayer();
2192+
AtlasPointer ap =
2193+
gamedef->tsrc()->getTexture(*(event.spawn_particle.texture));
2194+
2195+
new Particle(gamedef, smgr, player, client.getEnv(),
2196+
*event.spawn_particle.pos,
2197+
*event.spawn_particle.vel,
2198+
*event.spawn_particle.acc,
2199+
event.spawn_particle.expirationtime,
2200+
event.spawn_particle.size,
2201+
event.spawn_particle.collisiondetection, ap);
2202+
}
2203+
else if(event.type == CE_ADD_PARTICLESPAWNER)
2204+
{
2205+
LocalPlayer* player = client.getEnv().getLocalPlayer();
2206+
AtlasPointer ap =
2207+
gamedef->tsrc()->getTexture(*(event.add_particlespawner.texture));
2208+
2209+
new ParticleSpawner(gamedef, smgr, player,
2210+
event.add_particlespawner.amount,
2211+
event.add_particlespawner.spawntime,
2212+
*event.add_particlespawner.minpos,
2213+
*event.add_particlespawner.maxpos,
2214+
*event.add_particlespawner.minvel,
2215+
*event.add_particlespawner.maxvel,
2216+
*event.add_particlespawner.minacc,
2217+
*event.add_particlespawner.maxacc,
2218+
event.add_particlespawner.minexptime,
2219+
event.add_particlespawner.maxexptime,
2220+
event.add_particlespawner.minsize,
2221+
event.add_particlespawner.maxsize,
2222+
event.add_particlespawner.collisiondetection,
2223+
ap,
2224+
event.add_particlespawner.id);
2225+
}
2226+
else if(event.type == CE_DELETE_PARTICLESPAWNER)
2227+
{
2228+
delete_particlespawner (event.delete_particlespawner.id);
2229+
}
21892230
}
21902231
}
21912232

@@ -2415,7 +2456,8 @@ void the_game(
24152456
const ContentFeatures &features =
24162457
client.getNodeDefManager()->get(n);
24172458
addPunchingParticles
2418-
(gamedef, smgr, player, nodepos, features.tiles);
2459+
(gamedef, smgr, player, client.getEnv(),
2460+
nodepos, features.tiles);
24192461
}
24202462
}
24212463

@@ -2453,7 +2495,8 @@ void the_game(
24532495
const ContentFeatures &features =
24542496
client.getNodeDefManager()->get(wasnode);
24552497
addDiggingParticles
2456-
(gamedef, smgr, player, nodepos, features.tiles);
2498+
(gamedef, smgr, player, client.getEnv(),
2499+
nodepos, features.tiles);
24572500
}
24582501

24592502
dig_time = 0;
@@ -2734,6 +2777,7 @@ void the_game(
27342777
*/
27352778

27362779
allparticles_step(dtime, client.getEnv());
2780+
allparticlespawners_step(dtime, client.getEnv());
27372781

27382782
/*
27392783
Fog
@@ -3220,6 +3264,7 @@ void the_game(
32203264
clouds->drop();
32213265
if(gui_chat_console)
32223266
gui_chat_console->drop();
3267+
clear_particles ();
32233268

32243269
/*
32253270
Draw a "shutting down" screen, which will be shown while the map

0 commit comments

Comments
 (0)
Please sign in to comment.