Skip to content

Commit

Permalink
Revert "Revert CSM particles commit to fix particle spawner bug for 5…
Browse files Browse the repository at this point in the history
….0.0 (#8288)"

This reverts commit 01cd63b.
  • Loading branch information
nerzhul committed Feb 26, 2019
1 parent 911db0e commit 111f1dc
Show file tree
Hide file tree
Showing 10 changed files with 337 additions and 8 deletions.
1 change: 1 addition & 0 deletions build/android/jni/Android.mk
Expand Up @@ -353,6 +353,7 @@ LOCAL_SRC_FILES += \
jni/src/script/lua_api/l_object.cpp \
jni/src/script/lua_api/l_playermeta.cpp \
jni/src/script/lua_api/l_particles.cpp \
jni/src/script/lua_api/l_particles_local.cpp\
jni/src/script/lua_api/l_rollback.cpp \
jni/src/script/lua_api/l_server.cpp \
jni/src/script/lua_api/l_settings.cpp \
Expand Down
65 changes: 65 additions & 0 deletions doc/client_lua_api.txt
Expand Up @@ -789,6 +789,16 @@ Call these functions only at load time!
should listen from incoming messages with `minetest.register_on_modchannel_message`
call to receive incoming messages. Warning, this function is asynchronous.

### Particles
* `minetest.add_particle(particle definition)`

* `minetest.add_particlespawner(particlespawner definition)`
* Add a `ParticleSpawner`, an object that spawns an amount of particles over `time` seconds
* Returns an `id`, and -1 if adding didn't succeed

* `minetest.delete_particlespawner(id)`
* Delete `ParticleSpawner` with `id` (return value from `minetest.add_particlespawner`)

### Misc.
* `minetest.parse_json(string[, nullvalue])`: returns something
* Convert a string containing JSON data into the Lua equivalent
Expand Down Expand Up @@ -1308,3 +1318,58 @@ Displays distance to selected world position.
* `text`: Distance suffix. Can be blank.
* `number:` An integer containing the RGB value of the color used to draw the text.
* `world_pos`: World position of the waypoint.

### Particle definition (`add_particle`)

{
pos = {x=0, y=0, z=0},
velocity = {x=0, y=0, z=0},
acceleration = {x=0, y=0, z=0},
-- ^ Spawn particle at pos with velocity and acceleration
expirationtime = 1,
-- ^ Disappears after expirationtime seconds
size = 1,
collisiondetection = false,
-- ^ collisiondetection: if true collides with physical objects
collision_removal = false,
-- ^ collision_removal: if true then particle is removed when it collides,
-- ^ requires collisiondetection = true to have any effect
vertical = false,
-- ^ vertical: if true faces player using y axis only
texture = "image.png",
-- ^ Uses texture (string)
animation = {Tile Animation definition},
-- ^ optional, specifies how to animate the particle texture
glow = 0
-- ^ optional, specify particle self-luminescence in darkness
}

### `ParticleSpawner` definition (`add_particlespawner`)

{
amount = 1,
time = 1,
-- ^ If time is 0 has infinite lifespan and spawns the amount on a per-second base
minpos = {x=0, y=0, z=0},
maxpos = {x=0, y=0, z=0},
minvel = {x=0, y=0, z=0},
maxvel = {x=0, y=0, z=0},
minacc = {x=0, y=0, z=0},
maxacc = {x=0, y=0, z=0},
minexptime = 1,
maxexptime = 1,
minsize = 1,
maxsize = 1,
-- ^ The particle's properties are random values in between the bounds:
-- ^ minpos/maxpos, minvel/maxvel (velocity), minacc/maxacc (acceleration),
-- ^ minsize/maxsize, minexptime/maxexptime (expirationtime)
collisiondetection = false,
-- ^ collisiondetection: if true uses collision detection
collision_removal = false,
-- ^ collision_removal: if true then particle is removed when it collides,
-- ^ requires collisiondetection = true to have any effect
vertical = false,
-- ^ vertical: if true faces player using y axis only
texture = "image.png",
-- ^ Uses texture (string)
}
6 changes: 4 additions & 2 deletions src/client/client.h
Expand Up @@ -565,8 +565,10 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
// And relations to objects
std::unordered_map<int, u16> m_sounds_to_objects;

// HUD
// Mapping from server hud ids to internal hud ids
// CSM/client IDs to SSM/server IDs Mapping
// Map server particle spawner IDs to client IDs
std::unordered_map<u32, u32> m_particles_server_to_client;
// Map server hud ids to client hud ids
std::unordered_map<u32, u32> m_hud_server_to_client;

// Privileges
Expand Down
8 changes: 8 additions & 0 deletions src/client/particles.h
Expand Up @@ -196,6 +196,14 @@ friend class ParticleSpawner;
void addNodeParticle(IGameDef *gamedef, LocalPlayer *player, v3s16 pos,
const MapNode &n, const ContentFeatures &f);

u32 getSpawnerId() const
{
for (u32 id = 0;; ++id) { // look for unused particlespawner id
if (m_particle_spawners.find(id) == m_particle_spawners.end())
return id;
}
}

protected:
void addParticle(Particle* toadd);

Expand Down
22 changes: 16 additions & 6 deletions src/network/clientpackethandler.cpp
Expand Up @@ -977,15 +977,15 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
float minsize;
float maxsize;
bool collisiondetection;
u32 id;
u32 server_id;

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

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

*pkt >> id;
*pkt >> server_id;

bool vertical = false;
bool collision_removal = false;
Expand All @@ -1007,6 +1007,9 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
object_collision = readU8(is);
} catch (...) {}

u32 client_id = m_particle_manager.getSpawnerId();
m_particles_server_to_client[server_id] = client_id;

ClientEvent *event = new ClientEvent();
event->type = CE_ADD_PARTICLESPAWNER;
event->add_particlespawner.amount = amount;
Expand All @@ -1027,7 +1030,7 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
event->add_particlespawner.attached_id = attached_id;
event->add_particlespawner.vertical = vertical;
event->add_particlespawner.texture = new std::string(texture);
event->add_particlespawner.id = id;
event->add_particlespawner.id = client_id;
event->add_particlespawner.animation = animation;
event->add_particlespawner.glow = glow;

Expand All @@ -1037,12 +1040,19 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)

void Client::handleCommand_DeleteParticleSpawner(NetworkPacket* pkt)
{
u32 id;
*pkt >> id;
u32 server_id;
*pkt >> server_id;

u32 client_id;
auto i = m_particles_server_to_client.find(server_id);
if (i != m_particles_server_to_client.end())
client_id = i->second;
else
return;

ClientEvent *event = new ClientEvent();
event->type = CE_DELETE_PARTICLESPAWNER;
event->delete_particlespawner.id = id;
event->delete_particlespawner.id = client_id;

m_client_event_queue.push(event);
}
Expand Down
1 change: 1 addition & 0 deletions src/script/lua_api/CMakeLists.txt
Expand Up @@ -31,6 +31,7 @@ set(client_SCRIPT_LUA_API_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/l_localplayer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_mainmenu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_minimap.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_particles_local.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_sound.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_storage.cpp
PARENT_SCOPE)
206 changes: 206 additions & 0 deletions src/script/lua_api/l_particles_local.cpp
@@ -0,0 +1,206 @@
/*
Minetest
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2017 red-001 <red-001@outlook.ie>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "lua_api/l_particles_local.h"
#include "common/c_content.h"
#include "common/c_converter.h"
#include "lua_api/l_internal.h"
#include "lua_api/l_object.h"
#include "client/particles.h"
#include "client/client.h"
#include "client/clientevent.h"

int ModApiParticlesLocal::l_add_particle(lua_State *L)
{
luaL_checktype(L, 1, LUA_TTABLE);

// Get parameters
v3f pos, vel, acc;
float expirationtime, size;
bool collisiondetection, vertical, collision_removal;

struct TileAnimationParams animation;
animation.type = TAT_NONE;

std::string texture;

u8 glow;

lua_getfield(L, 1, "pos");
pos = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
lua_pop(L, 1);

lua_getfield(L, 1, "velocity");
vel = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
lua_pop(L, 1);

lua_getfield(L, 1, "acceleration");
acc = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
lua_pop(L, 1);

expirationtime = getfloatfield_default(L, 1, "expirationtime", 1);
size = getfloatfield_default(L, 1, "size", 1);
collisiondetection = getboolfield_default(L, 1, "collisiondetection", false);
collision_removal = getboolfield_default(L, 1, "collision_removal", false);
vertical = getboolfield_default(L, 1, "vertical", false);

lua_getfield(L, 1, "animation");
animation = read_animation_definition(L, -1);
lua_pop(L, 1);

texture = getstringfield_default(L, 1, "texture", "");

glow = getintfield_default(L, 1, "glow", 0);

ClientEvent *event = new ClientEvent();
event->type = CE_SPAWN_PARTICLE;
event->spawn_particle.pos = new v3f (pos);
event->spawn_particle.vel = new v3f (vel);
event->spawn_particle.acc = new v3f (acc);
event->spawn_particle.expirationtime = expirationtime;
event->spawn_particle.size = size;
event->spawn_particle.collisiondetection = collisiondetection;
event->spawn_particle.collision_removal = collision_removal;
event->spawn_particle.vertical = vertical;
event->spawn_particle.texture = new std::string(texture);
event->spawn_particle.animation = animation;
event->spawn_particle.glow = glow;
getClient(L)->pushToEventQueue(event);

return 0;
}

int ModApiParticlesLocal::l_add_particlespawner(lua_State *L)
{
luaL_checktype(L, 1, LUA_TTABLE);
// Get parameters
u16 amount;
v3f minpos, maxpos, minvel, maxvel, minacc, maxacc;
float time, minexptime, maxexptime, minsize, maxsize;
bool collisiondetection, vertical, collision_removal;

struct TileAnimationParams animation;
animation.type = TAT_NONE;
// TODO: Implement this when there is a way to get an objectref.
// ServerActiveObject *attached = NULL;
std::string texture;
u8 glow;

amount = getintfield_default(L, 1, "amount", 1);
time = getfloatfield_default(L, 1, "time", 1);

lua_getfield(L, 1, "minpos");
minpos = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
lua_pop(L, 1);

lua_getfield(L, 1, "maxpos");
maxpos = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
lua_pop(L, 1);

lua_getfield(L, 1, "minvel");
minvel = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
lua_pop(L, 1);

lua_getfield(L, 1, "maxvel");
maxvel = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
lua_pop(L, 1);

lua_getfield(L, 1, "minacc");
minacc = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
lua_pop(L, 1);

lua_getfield(L, 1, "maxacc");
maxacc = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
lua_pop(L, 1);

minexptime = getfloatfield_default(L, 1, "minexptime", 1);
maxexptime = getfloatfield_default(L, 1, "maxexptime", 1);
minsize = getfloatfield_default(L, 1, "minsize", 1);
maxsize = getfloatfield_default(L, 1, "maxsize", 1);

collisiondetection = getboolfield_default(L, 1, "collisiondetection", false);
collision_removal = getboolfield_default(L, 1, "collision_removal", false);
vertical = getboolfield_default(L, 1, "vertical", false);

lua_getfield(L, 1, "animation");
animation = read_animation_definition(L, -1);
lua_pop(L, 1);

// TODO: Implement this when a way to get an objectref on the client is added
// lua_getfield(L, 1, "attached");
// if (!lua_isnil(L, -1)) {
// ObjectRef *ref = ObjectRef::checkobject(L, -1);
// lua_pop(L, 1);
// attached = ObjectRef::getobject(ref);
// }

texture = getstringfield_default(L, 1, "texture", "");
glow = getintfield_default(L, 1, "glow", 0);

u32 id = getClient(L)->getParticleManager()->getSpawnerId();

ClientEvent *event = new ClientEvent();
event->type = CE_ADD_PARTICLESPAWNER;
event->add_particlespawner.amount = amount;
event->add_particlespawner.spawntime = time;
event->add_particlespawner.minpos = new v3f (minpos);
event->add_particlespawner.maxpos = new v3f (maxpos);
event->add_particlespawner.minvel = new v3f (minvel);
event->add_particlespawner.maxvel = new v3f (maxvel);
event->add_particlespawner.minacc = new v3f (minacc);
event->add_particlespawner.maxacc = new v3f (maxacc);
event->add_particlespawner.minexptime = minexptime;
event->add_particlespawner.maxexptime = maxexptime;
event->add_particlespawner.minsize = minsize;
event->add_particlespawner.maxsize = maxsize;
event->add_particlespawner.collisiondetection = collisiondetection;
event->add_particlespawner.collision_removal = collision_removal;
event->add_particlespawner.attached_id = 0;
event->add_particlespawner.vertical = vertical;
event->add_particlespawner.texture = new std::string(texture);
event->add_particlespawner.id = id;
event->add_particlespawner.animation = animation;
event->add_particlespawner.glow = glow;

getClient(L)->pushToEventQueue(event);
lua_pushnumber(L, id);

return 1;
}

int ModApiParticlesLocal::l_delete_particlespawner(lua_State *L)
{
// Get parameters
u32 id = luaL_checknumber(L, 1);

ClientEvent *event = new ClientEvent();
event->type = CE_DELETE_PARTICLESPAWNER;
event->delete_particlespawner.id = id;

getClient(L)->pushToEventQueue(event);
return 0;
}

void ModApiParticlesLocal::Initialize(lua_State *L, int top)
{
API_FCT(add_particle);
API_FCT(add_particlespawner);
API_FCT(delete_particlespawner);
}

0 comments on commit 111f1dc

Please sign in to comment.