Revert "Revert CSM particles commit to fix particle spawner bug for 5.0.0 (#8288)"
authorLoïc Blot <loic.blot@unix-experience.fr>
Tue, 26 Feb 2019 07:53:53 +0000 (08:53 +0100)
committerLoïc Blot <loic.blot@unix-experience.fr>
Tue, 26 Feb 2019 07:53:53 +0000 (08:53 +0100)
This reverts commit 01cd63bd3bca0192dab2834faf414b022706a77e.

build/android/jni/Android.mk
doc/client_lua_api.txt
src/client/client.h
src/client/particles.h
src/network/clientpackethandler.cpp
src/script/lua_api/CMakeLists.txt
src/script/lua_api/l_particles_local.cpp [new file with mode: 0644]
src/script/lua_api/l_particles_local.h [new file with mode: 0644]
src/script/scripting_client.cpp
util/travis/clang-format-whitelist.txt

index 7f59b2723e8ae0d4fd64e866ace2f4c09d65a0ce..a8e0175101d9e823782aae7adcad7c152abafdd0 100644 (file)
@@ -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     \
index 9ee18be16af69aa29c55c62f7c49ae2b6a71e0ce..f0e585355d89cd4a2f27d5408726ccb4a2a383c8 100644 (file)
@@ -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
@@ -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)
+    }
index 57623f164731053ca7e898d55ee7497b97826d1d..60735f665300f8c3133b58464bac4d5b4acfdede 100644 (file)
@@ -565,8 +565,10 @@ private:
        // 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
index d1854ecbfffb555dcd10fb6b46b5ef3b2b75c0d4..3392e7e950ae9a860d2b39420f817840c713236f 100644 (file)
@@ -196,6 +196,14 @@ public:
        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);
 
index 3fadc3cb0d792558f7416d36165affe58fe26af5..2d02d07559c248c2627849b0efa66525ca9cde3f 100644 (file)
@@ -977,7 +977,7 @@ 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
@@ -985,7 +985,7 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
 
        std::string texture = pkt->readLongString();
 
-       *pkt >> id;
+       *pkt >> server_id;
 
        bool vertical          = false;
        bool collision_removal = false;
@@ -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;
@@ -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;
 
@@ -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);
 }
index 97e5ad1ec673e23693f4af17c1253e13b48aef17..32f6a2793d0437045fe477e6dfb2d1b149a16b52 100644 (file)
@@ -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)
diff --git a/src/script/lua_api/l_particles_local.cpp b/src/script/lua_api/l_particles_local.cpp
new file mode 100644 (file)
index 0000000..3c7a821
--- /dev/null
@@ -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);
+}
diff --git a/src/script/lua_api/l_particles_local.h b/src/script/lua_api/l_particles_local.h
new file mode 100644 (file)
index 0000000..5dff153
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+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_base.h"
+
+class ModApiParticlesLocal : public ModApiBase
+{
+private:
+       static int l_add_particle(lua_State *L);
+       static int l_add_particlespawner(lua_State *L);
+       static int l_delete_particlespawner(lua_State *L);
+
+public:
+       static void Initialize(lua_State *L, int top);
+};
index b6998427a8a3858e682ce793808bc5adf26b3b19..86e5f2874a482f4af69c2452f74dff9bf9fe466b 100644 (file)
@@ -23,8 +23,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "cpp_api/s_internal.h"
 #include "lua_api/l_client.h"
 #include "lua_api/l_env.h"
+#include "lua_api/l_item.h"
 #include "lua_api/l_minimap.h"
 #include "lua_api/l_modchannels.h"
+#include "lua_api/l_particles_local.h"
 #include "lua_api/l_storage.h"
 #include "lua_api/l_sound.h"
 #include "lua_api/l_util.h"
@@ -77,6 +79,7 @@ void ClientScripting::InitializeModApi(lua_State *L, int top)
        ModApiStorage::Initialize(L, top);
        ModApiEnvMod::InitializeClient(L, top);
        ModApiChannels::Initialize(L, top);
+       ModApiParticlesLocal::Initialize(L, top);
 }
 
 void ClientScripting::on_client_ready(LocalPlayer *localplayer)
index b22db485df7f4d3ed8ee4c49cbe355cbba2ebf34..e196daf732188c05b8815271d521f4897b453fc1 100644 (file)
@@ -367,6 +367,7 @@ src/script/lua_api/l_object.cpp
 src/script/lua_api/l_object.h
 src/script/lua_api/l_particles.cpp
 src/script/lua_api/l_particles.h
+src/script/lua_api/l_particles_local.cpp
 src/script/lua_api/l_rollback.cpp
 src/script/lua_api/l_rollback.h
 src/script/lua_api/l_server.cpp