From 14dbb40da26d297bbe370d8e6757014a71e77eab Mon Sep 17 00:00:00 2001 From: cora Date: Fri, 17 Dec 2021 22:35:27 +0100 Subject: [PATCH] optimize nether porticles --- mods/ITEMS/mcl_portals/portal_nether.lua | 111 ++++++++++++++--------- 1 file changed, 67 insertions(+), 44 deletions(-) diff --git a/mods/ITEMS/mcl_portals/portal_nether.lua b/mods/ITEMS/mcl_portals/portal_nether.lua index 7e23a9f7..6c5c3037 100644 --- a/mods/ITEMS/mcl_portals/portal_nether.lua +++ b/mods/ITEMS/mcl_portals/portal_nether.lua @@ -29,6 +29,9 @@ if minetest.features.use_texture_alpha_string_modes then PORTAL_ALPHA = nil end +local PORTICLE_DISTANCE = 15 --how far to send particle spawners for the portalnodes +local porticlespawners = {} + -- Table of objects (including players) which recently teleported by a -- Nether portal. Those objects have a brief cooloff period before they -- can teleport again. This prevents annoying back-and-forth teleportation. @@ -59,6 +62,65 @@ local function nether_to_overworld(x) return LIMIT - math.abs(((x * OVERWORLD_TO_NETHER_SCALE + LIMIT) % (LIMIT*4)) - (LIMIT*2)) end +local function remove_particlespawner_at_position(playername,pos) + if not porticlespawners[minetest.pos_to_string(pos)] or porticlespawners[minetest.pos_to_string(pos)][playername] == nil then return end + minetest.delete_particlespawner(porticlespawners[minetest.pos_to_string(pos)][playername],playername) + porticlespawners[minetest.pos_to_string(pos)][playername]=nil +end + +local function add_particlespawner_at_position(player,pos,node) + if not porticlespawners[minetest.pos_to_string(pos)] then porticlespawners[minetest.pos_to_string(pos)] = {} end + if porticlespawners[minetest.pos_to_string(pos)][player:get_player_name()] ~= nil then return end + porticlespawners[minetest.pos_to_string(pos)][player:get_player_name()]=minetest.add_particlespawner({ + amount = node_particles_allowed_level + 1, + minpos = vector.add(pos, vector.new(-3,-3,-3)), + maxpos = vector.add(pos, vector.new(3,3,3)), + minvel = vector.new(-0.5,-0.5,-0.5), + maxvel = vector.new(0.5,0.5,0.5), + minacc = vector.new(-0.5,-0.5,-0.5), + maxacc = vector.new(0.5,0.5,0.5), + minexptime = 0.1, + maxexptime = 2.4, + minsize = 0.3, + maxsize = 1.8, + time=0, + collisiondetection = false, + texture = "mcl_particles_nether_portal.png", + playername = player:get_player_name(), + }) +end + +local function add_porticlespawners(pos,node) + --Add particlespawners for all players in range + for _,obj in pairs(minetest.get_connected_players()) do + if vector.distance(obj:get_pos(),pos) <= PORTICLE_DISTANCE then + add_particlespawner_at_position(obj,pos,node) + end + end +end + +local function remove_porticlespawners(pos,force) + --Remove particlespawners for all players out of range + -- force removes all particlespawners for the given position regardless of range + if porticlespawners[minetest.pos_to_string(pos)] then + for k,v in pairs(porticlespawners[minetest.pos_to_string(pos)]) do + local p=minetest.get_player_by_name(k) + local dst=PORTICLE_DISTANCE+1 --if player is logged off remove the particlespawner + if p and p:is_player() then + dst=vector.distance(p:get_pos(),pos) + end + if dst > PORTICLE_DISTANCE or force then + remove_particlespawner_at_position(k,pos) + end + end + end +end + +local function check_porticlespawners(pos,node) + add_porticlespawners(pos,node) + remove_porticlespawners(pos) +end + -- Destroy portal if pos (portal frame or portal node) got destroyed local function destroy_nether_portal(pos) local meta = minetest.get_meta(pos) @@ -77,6 +139,7 @@ local function destroy_nether_portal(pos) local node = minetest.get_node(pos) if node and (node.name == "mcl_portals:portal" and (orientation == nil or (node.param2 == orientation))) then minetest.log("action", "[mcl_portal] Destroying Nether portal at " .. minetest.pos_to_string(pos)) + remove_porticlespawners(pos,true) return minetest.remove_node(pos) end end @@ -769,56 +832,16 @@ local function teleport(obj, portal_pos) end end + minetest.register_abm({ label = "Nether portal teleportation and particles", nodenames = {"mcl_portals:portal"}, interval = 1, chance = 1, action = function(pos, node) - local o = node.param2 -- orientation - local d = math.random(0, 1) -- direction - local time = math.random() * 1.9 + 0.5 - local velocity, acceleration - if o == 1 then - velocity = {x = math.random() * 0.7 + 0.3, y = math.random() - 0.5, z = math.random() - 0.5} - acceleration = {x = math.random() * 1.1 + 0.3, y = math.random() - 0.5, z = math.random() - 0.5} - else - velocity = {x = math.random() - 0.5, y = math.random() - 0.5, z = math.random() * 0.7 + 0.3} - acceleration = {x = math.random() - 0.5, y = math.random() - 0.5, z = math.random() * 1.1 + 0.3} - end - local distance = vector.add(vector.multiply(velocity, time), vector.multiply(acceleration, time * time / 2)) - if d == 1 then - if o == 1 then - distance.x = -distance.x - velocity.x = -velocity.x - acceleration.x = -acceleration.x - else - distance.z = -distance.z - velocity.z = -velocity.z - acceleration.z = -acceleration.z - end - end - distance = vector.subtract(pos, distance) - for _, obj in ipairs(minetest.get_objects_inside_radius(pos, 15)) do - if obj:is_player() then - minetest.add_particlespawner({ - amount = node_particles_allowed_level + 1, - minpos = distance, - maxpos = distance, - minvel = velocity, - maxvel = velocity, - minacc = acceleration, - maxacc = acceleration, - minexptime = time, - maxexptime = time, - minsize = 0.3, - maxsize = 1.8, - collisiondetection = false, - texture = "mcl_particles_nether_portal.png", - playername = obj:get_player_name(), - }) - end - end + + check_porticlespawners(pos) + for _, obj in ipairs(minetest.get_objects_inside_radius(pos, 1)) do --maikerumine added for objects to travel local lua_entity = obj:get_luaentity() --maikerumine added for objects to travel if (obj:is_player() or lua_entity) and prevent_portal_chatter(obj) then