Compare commits

..

6 Commits

Author SHA1 Message Date
cora 22ec7a65d8 optimize nether porticles 2022-01-14 18:15:11 +01:00
Lizzy Fleckenstein 4cfb65003b Fix reference dupes for droppers and dispensers 2022-01-14 18:15:11 +01:00
Lizzy Fleckenstein 5060e600d7 Fix reference dupe glitches 2022-01-14 18:15:11 +01:00
Lizzy Fleckenstein 20900cccd5 Fix anvil duplication glitch 2022-01-14 18:15:11 +01:00
Lizzy Fleckenstein 51f3869ffe Fix another anvil weirdness and dupe glitch 2022-01-14 18:15:11 +01:00
cora 89d63080be replace nether dust particles with p. spawners
mineclonia uses add_particle for nether dust resulting in a 10-fold
increase in network traffic when in the nether. Nether dust is not
configurable making it impossible to turn this off for server admins.
this commit replaces the add_particle method with particle spawners
2022-01-14 18:15:06 +01:00
12 changed files with 148 additions and 96 deletions

View File

@ -21,7 +21,7 @@ The basic digging time groups determine by which tools a node can be dug.
* `swordy=1`: Diggable by sword (any material), and this node is *not* a cobweb
* `swordy_cobweb=1`: Diggable by sword (any material), and this node is a cobweb
* `shearsy=1`: Diggable by shears, and this node is *not* wool
* `shearsy_wool=1`: Diggable by shears, and this node is wool
* `shearsy=wool=1`: Diggable by shears, and this node is wool
* `handy=1`: Breakable by hand and this node gives it useful drop when dug by hand. All nodes which are breakable by pickaxe, axe, shovel, sword or shears are also automatically breakable by hand, but not neccess
* `creative_breakable=1`: Block is breakable by hand in creative mode. This group is implied if the node belongs to any other digging group

View File

@ -1,36 +1,66 @@
mcl_weather.nether_dust = {}
mcl_weather.nether_dust.particles_count = 99
mcl_weather.nether_dust.particlespawners = {}
-- calculates coordinates and draw particles for Nether dust
mcl_weather.nether_dust.add_dust_particles = function(player)
for i=mcl_weather.nether_dust.particles_count, 1,-1 do
local rpx, rpy, rpz = mcl_weather.get_random_pos_by_player_look_dir(player)
minetest.add_particle({
pos = {x = rpx, y = rpy - math.random(6, 18), z = rpz},
velocity = {x = math.random(-30,30)*0.01, y = math.random(-15,15)*0.01, z = math.random(-30,30)*0.01},
acceleration = {x = math.random(-50,50)*0.02, y = math.random(-20,20)*0.02, z = math.random(-50,50)*0.02},
expirationtime = 3,
size = math.random(6,20)*0.01,
collisiondetection = false,
object_collision = false,
vertical = false,
glow = math.random(0,minetest.LIGHT_MAX),
texture = "mcl_particles_nether_dust"..tostring(i%3+1)..".png",
playername = player:get_player_name()
})
local psdef= {
amount = 150,
time = 0,
minpos = vector.new(-15,-15,-15),
maxpos =vector.new(15,15,15),
minvel = vector.new(-0.3,-0.15,-1),
maxvel = vector.new(0.3,0.15,0.3),
minacc = vector.new(-1,-0.4,-1),
maxacc = vector.new(1,0.4,1),
minexptime = 1,
maxexptime = 10,
minsize = 0.2,
maxsize = 0.7,
collisiondetection = false,
collision_removal = false,
object_collision = false,
vertical = false
}
local function check_player(player)
local name=player:get_player_name()
if mcl_worlds.has_dust(player:get_pos()) and not mcl_weather.nether_dust.particlespawners[name] then
return true
end
end
mcl_weather.nether_dust.add_particlespawners = function(player)
local name=player:get_player_name(name)
mcl_weather.nether_dust.particlespawners[name]={}
psdef.playername = name
psdef.attached = player
psdef.glow = math.random(0,minetest.LIGHT_MAX)
for i=1,3 do
psdef.texture="mcl_particles_nether_dust"..i..".png"
mcl_weather.nether_dust.particlespawners[name][i]=minetest.add_particlespawner(psdef)
end
end
local timer = 0
minetest.register_globalstep(function(dtime)
timer = timer + dtime
if timer < 0.7 then return end
timer = 0
for _, player in ipairs(minetest.get_connected_players()) do
if not mcl_worlds.has_dust(player:get_pos()) then
return false
mcl_weather.nether_dust.delete_particlespawners = function(player)
local name=player:get_player_name(name)
if mcl_weather.nether_dust.particlespawners[name] then
for i=1,3 do
minetest.delete_particlespawner(mcl_weather.nether_dust.particlespawners[name][i])
end
mcl_weather.nether_dust.add_dust_particles(player)
mcl_weather.nether_dust.particlespawners[name]=nil
end
end
mcl_worlds.register_on_dimension_change(function(player, dimension)
if check_player(player) then
return mcl_weather.nether_dust.add_particlespawners(player)
end
mcl_weather.nether_dust.delete_particlespawners(player)
end)
minetest.register_on_joinplayer(function(player)
if check_player(player) then
mcl_weather.nether_dust.add_particlespawners(player)
end
end)
minetest.register_on_leaveplayer(function(player)
mcl_weather.nether_dust.delete_particlespawners(player)
end)

View File

@ -82,7 +82,7 @@ local dispenserdef = {
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local meta = minetest.get_meta(pos)
local meta2 = meta
local meta2 = meta:to_table()
meta:from_table(oldmetadata)
local inv = meta:get_inventory()
for i=1, inv:get_size("main") do
@ -92,7 +92,7 @@ local dispenserdef = {
minetest.add_item(p, stack)
end
end
meta:from_table(meta2:to_table())
meta:from_table(meta2)
end,
_mcl_blast_resistance = 3.5,
_mcl_hardness = 3.5,

View File

@ -55,7 +55,7 @@ local dropperdef = {
sounds = mcl_sounds.node_sound_stone_defaults(),
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local meta = minetest.get_meta(pos)
local meta2 = meta
local meta2 = meta:to_table()
meta:from_table(oldmetadata)
local inv = meta:get_inventory()
for i=1, inv:get_size("main") do
@ -65,7 +65,7 @@ local dropperdef = {
minetest.add_item(p, stack)
end
end
meta:from_table(meta2:to_table())
meta:from_table(meta2)
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
local name = player:get_player_name()

View File

@ -53,7 +53,7 @@ local dropperdef = {
sounds = mcl_sounds.node_sound_stone_defaults(),
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local meta = minetest.get_meta(pos)
local meta2 = meta
local meta2 = meta:to_table()
meta:from_table(oldmetadata)
local inv = meta:get_inventory()
for i=1, inv:get_size("main") do
@ -63,7 +63,7 @@ local dropperdef = {
minetest.add_item(p, stack)
end
end
meta:from_table(meta2:to_table())
meta:from_table(meta2)
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
local name = player:get_player_name()

View File

@ -101,14 +101,14 @@ local function update_anvil_slots(meta)
end
local can_combine = mcl_enchanting.combine(input1, input2)
if can_combine then
-- Add tool health together plus a small bonus
if def1.type == "tool" and def2.type == "tool" then
local new_wear = calculate_repair(input1:get_wear(), input2:get_wear(), SAME_TOOL_REPAIR_BOOST)
input1:set_wear(new_wear)
end
name_item = input1
new_output = name_item
-- Tool + repair item
@ -318,11 +318,11 @@ local anvildef = {
_mcl_after_falling = damage_anvil_by_falling,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local meta = minetest.get_meta(pos)
local meta2 = meta
local meta = minetest.get_meta(pos)
local meta2 = meta:to_table()
meta:from_table(oldmetadata)
drop_anvil_items(pos, meta)
meta:from_table(meta2:to_table())
meta:from_table(meta2)
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
local name = player:get_player_name()

View File

@ -346,7 +346,7 @@ end
local drop_items_chest = function(pos, oldnode, oldmetadata)
local meta = minetest.get_meta(pos)
local meta2 = meta
local meta2 = meta:to_table()
if oldmetadata then
meta:from_table(oldmetadata)
end
@ -358,7 +358,7 @@ local drop_items_chest = function(pos, oldnode, oldmetadata)
minetest.add_item(p, stack)
end
end
meta:from_table(meta2:to_table())
meta:from_table(meta2)
end
local on_chest_blast = function(pos)

View File

@ -23,7 +23,7 @@ end
function mcl_enchanting.load_enchantments(itemstack, enchantments)
if not mcl_enchanting.is_book(itemstack:get_name()) then
mcl_enchanting.unload_enchantments(itemstack)
mcl_enchanting.unload_enchantments(itemstack)
for enchantment, level in pairs(enchantments or mcl_enchanting.get_enchantments(itemstack)) do
local enchantment_def = mcl_enchanting.enchantments[enchantment]
if enchantment_def.on_enchant then
@ -160,7 +160,7 @@ function mcl_enchanting.combine(itemstack, combine_with)
local itemname = itemstack:get_name()
local combine_name = combine_with:get_name()
local enchanted_itemname = mcl_enchanting.get_enchanted_itemstring(itemname)
if enchanted_itemname ~= mcl_enchanting.get_enchanted_itemstring(combine_name) and not mcl_enchanting.is_book(combine_name) then
if not enchanted_itemname or enchanted_itemname ~= mcl_enchanting.get_enchanted_itemstring(combine_name) and not mcl_enchanting.is_book(combine_name) then
return false
end
local enchantments = mcl_enchanting.get_enchantments(itemstack)

View File

@ -388,11 +388,12 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s
{ x=0, y=0, z=-1 },
{ x=0, y=0, z=1 },
}
local floorpos, floor
for n=#neighbors, 1, -1 do
local offset = neighbors[n]
local blockpos = vector.add(stempos, offset)
local floorpos = { x=blockpos.x, y=blockpos.y-1, z=blockpos.z }
local floor = minetest.get_node(floorpos)
floorpos = { x=blockpos.x, y=blockpos.y-1, z=blockpos.z }
floor = minetest.get_node(floorpos)
local block = minetest.get_node(blockpos)
local soilgroup = minetest.get_item_group(floor.name, "soil")
if not ((minetest.get_item_group(floor.name, "grass_block") == 1 or floor.name=="mcl_core:dirt" or soilgroup == 2 or soilgroup == 3) and block.name == "air") then
@ -406,8 +407,6 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s
local r = math.random(1, #neighbors)
local offset = neighbors[r]
local blockpos = vector.add(stempos, offset)
local floorpos = { x=blockpos.x, y=blockpos.y-1, z=blockpos.z }
local floor = minetest.get_node(floorpos)
local p2
if offset.x == 1 then
minetest.set_node(stempos, {name=connected_stem_names[1]})

View File

@ -451,7 +451,7 @@ minetest.register_node("mcl_furnaces:furnace", {
on_timer = furnace_node_timer,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local meta = minetest.get_meta(pos)
local meta2 = meta
local meta2 = meta:to_table()
meta:from_table(oldmetadata)
local inv = meta:get_inventory()
for _, listname in ipairs({"src", "dst", "fuel"}) do
@ -461,7 +461,7 @@ minetest.register_node("mcl_furnaces:furnace", {
minetest.add_item(p, stack)
end
end
meta:from_table(meta2:to_table())
meta:from_table(meta2)
end,
on_construct = function(pos)

View File

@ -61,7 +61,7 @@ local def_hopper = {
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local meta = minetest.get_meta(pos)
local meta2 = meta
local meta2 = meta:to_table()
meta:from_table(oldmetadata)
local inv = meta:get_inventory()
for i=1,inv:get_size("main") do
@ -71,7 +71,7 @@ local def_hopper = {
minetest.add_item(p, stack)
end
end
meta:from_table(meta2:to_table())
meta:from_table(meta2)
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
local name = player:get_player_name()

View File

@ -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