From a65db15b5caf92e1e18c07880ea62b8ff5ce61ff Mon Sep 17 00:00:00 2001 From: NO11 Date: Sat, 29 May 2021 19:21:15 +0000 Subject: [PATCH 01/14] Totem particle textures --- .../textures/mcl_particles_totem1.png | Bin 0 -> 148 bytes .../textures/mcl_particles_totem2.png | Bin 0 -> 154 bytes .../textures/mcl_particles_totem3.png | Bin 0 -> 155 bytes .../textures/mcl_particles_totem4.png | Bin 0 -> 165 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 mods/CORE/mcl_particles/textures/mcl_particles_totem1.png create mode 100644 mods/CORE/mcl_particles/textures/mcl_particles_totem2.png create mode 100644 mods/CORE/mcl_particles/textures/mcl_particles_totem3.png create mode 100644 mods/CORE/mcl_particles/textures/mcl_particles_totem4.png diff --git a/mods/CORE/mcl_particles/textures/mcl_particles_totem1.png b/mods/CORE/mcl_particles/textures/mcl_particles_totem1.png new file mode 100644 index 0000000000000000000000000000000000000000..15fe082e104d5d524ab2fa7b9af63c29c196756d GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{VY)RhkE7sn8Z%gG4~v=dyO{rUg@zkN*8 lL_xjdE1|%O$WD@{VY)RhkE rgruaTp-7@BgTe~DWM4f;{PWz literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_particles/textures/mcl_particles_totem3.png b/mods/CORE/mcl_particles/textures/mcl_particles_totem3.png new file mode 100644 index 0000000000000000000000000000000000000000..55d6f49d3543ca553e475954f6012306ea7ba0bf GIT binary patch literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{VY)RhkEp00i_>zopr0FK-$I{*Lx literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_particles/textures/mcl_particles_totem4.png b/mods/CORE/mcl_particles/textures/mcl_particles_totem4.png new file mode 100644 index 0000000000000000000000000000000000000000..d6e6502b7fd0c0d1a68c8afdcea112d4693e07db GIT binary patch literal 165 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{VY)RhkEpe+aVfI>!|E{-7*my;6|m<*JP|NZ~}UtaIv zi4z?QIU*T%Il0AfO%OE_e5|H6NyhJjZ%d842m^yIw+NSW@uBHJ-3*?telF{r5}E+c C1}gjj literal 0 HcmV?d00001 From 75e263debca16802eabb977cbae1f1895dd32bc5 Mon Sep 17 00:00:00 2001 From: NO11 Date: Sat, 29 May 2021 19:24:16 +0000 Subject: [PATCH 02/14] Add code for totem partciles --- mods/ITEMS/mcl_totems/init.lua | 48 ++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_totems/init.lua b/mods/ITEMS/mcl_totems/init.lua index 499d7362df..e64404c2c7 100644 --- a/mods/ITEMS/mcl_totems/init.lua +++ b/mods/ITEMS/mcl_totems/init.lua @@ -4,6 +4,41 @@ minetest.register_on_leaveplayer(function(player) hud_totem[player] = nil end) +-- Totem particle registration +-- TODO: real MC colors, these are randomly selected colors: +local colors = {"#7FFF00", "#698B22", "#BCEE68", "#EEEE00", "#C5F007"} +for c, color in pairs(colors) do + local colorizing = ".png^[colorize:"..color + for n = 1, 4 do + minetest.register_entity("mcl_totems:totem_particle"..n.."_color"..c, { + physical = true, + collide_with_objects = false, + collisionbox = {-0.02,-0.02,-0.02, 0.02,0.02,0.02}, + pointable = false, + visual = "sprite", + visual_size = {x=0.2, y=0.2}, + textures = {"mcl_particles_totem"..n..colorizing}, + spritediv = {x=1, y=1}, + initial_sprite_basepos = {x=0, y=0}, + static_save = false, + glow = 5, + on_activate = function(self, staticdata) + self.object:set_velocity({x = math.random(-4, 4)*math.random(), y = math.random(-1, 4)*math.random(), z = math.random(-4, 4)*math.random()}) + minetest.after(0.3, function() + self.object:set_acceleration({x=0, y=-4, z=0}) + self.object:set_velocity({x=0, y=0, z=0}) + end) + end, + on_step = function(self, dtime) + local r = math.random(1,80) + if r == 1 then + self.object:remove() + end + end + }) + end +end + -- Save the player from death when holding totem of undying in hand mcl_damage.register_modifier(function(obj, damage, reason) if obj:is_player() then @@ -32,7 +67,16 @@ mcl_damage.register_modifier(function(obj, damage, reason) -- Effects minetest.sound_play({name = "mcl_totems_totem", gain=1}, {pos=ppos, max_hear_distance=16}, true) - -- Big totem overlay + --Particles + for i = 1, 200 do + local particle = "mcl_totems:totem_particle"..math.random(1, 4).."_color"..math.random(1, 5) + minetest.after(math.random(1, 2)*math.random(), function() + local new_pos = obj:get_pos() + minetest.add_entity({x=new_pos.x, y=new_pos.y + 1, z=new_pos.z}, particle) + end) + end + + -- Big totem overlay if not hud_totem[obj] then hud_totem[obj] = obj:hud_add({ hud_elem_type = "image", @@ -55,4 +99,4 @@ mcl_damage.register_modifier(function(obj, damage, reason) end end end -end, 1000) +end, 1000) \ No newline at end of file From ee21a24fb61705bedfee8b2ad935b1e389018a58 Mon Sep 17 00:00:00 2001 From: NO11 Date: Mon, 7 Jun 2021 17:13:50 +0000 Subject: [PATCH 03/14] Don't register a separate entity for every particle --- mods/ITEMS/mcl_totems/init.lua | 60 ++++++++++++++++------------------ 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/mods/ITEMS/mcl_totems/init.lua b/mods/ITEMS/mcl_totems/init.lua index e64404c2c7..a6429f7b87 100644 --- a/mods/ITEMS/mcl_totems/init.lua +++ b/mods/ITEMS/mcl_totems/init.lua @@ -7,37 +7,34 @@ end) -- Totem particle registration -- TODO: real MC colors, these are randomly selected colors: local colors = {"#7FFF00", "#698B22", "#BCEE68", "#EEEE00", "#C5F007"} -for c, color in pairs(colors) do - local colorizing = ".png^[colorize:"..color - for n = 1, 4 do - minetest.register_entity("mcl_totems:totem_particle"..n.."_color"..c, { - physical = true, - collide_with_objects = false, - collisionbox = {-0.02,-0.02,-0.02, 0.02,0.02,0.02}, - pointable = false, - visual = "sprite", - visual_size = {x=0.2, y=0.2}, - textures = {"mcl_particles_totem"..n..colorizing}, - spritediv = {x=1, y=1}, - initial_sprite_basepos = {x=0, y=0}, - static_save = false, - glow = 5, - on_activate = function(self, staticdata) - self.object:set_velocity({x = math.random(-4, 4)*math.random(), y = math.random(-1, 4)*math.random(), z = math.random(-4, 4)*math.random()}) - minetest.after(0.3, function() - self.object:set_acceleration({x=0, y=-4, z=0}) - self.object:set_velocity({x=0, y=0, z=0}) - end) - end, - on_step = function(self, dtime) - local r = math.random(1,80) - if r == 1 then - self.object:remove() - end - end +minetest.register_entity("mcl_totems:totem_particle", { + physical = true, + collide_with_objects = false, + collisionbox = {-0.02,-0.02,-0.02, 0.02,0.02,0.02}, + pointable = false, + visual = "sprite", + visual_size = {x=0.2, y=0.2}, + spritediv = {x=1, y=1}, + initial_sprite_basepos = {x=0, y=0}, + static_save = false, + glow = 5, + on_activate = function(self, staticdata) + self.object:set_properties({ + textures = {"mcl_particles_totem"..math.random(1, 4)..".png^[colorize:"..colors[math.random(#colors)]} }) + self.object:set_velocity({x = math.random(-4, 4)*math.random(), y = math.random(-1, 4)*math.random(), z = math.random(-4, 4)*math.random()}) + minetest.after(0.3, function() + self.object:set_acceleration({x=0, y=-4, z=0}) + self.object:set_velocity({x=0, y=0, z=0}) + end) + end, + on_step = function(self, dtime) + local r = math.random(1,50) + if r == 1 then + self.object:remove() + end end -end +}) -- Save the player from death when holding totem of undying in hand mcl_damage.register_modifier(function(obj, damage, reason) @@ -68,11 +65,10 @@ mcl_damage.register_modifier(function(obj, damage, reason) minetest.sound_play({name = "mcl_totems_totem", gain=1}, {pos=ppos, max_hear_distance=16}, true) --Particles - for i = 1, 200 do - local particle = "mcl_totems:totem_particle"..math.random(1, 4).."_color"..math.random(1, 5) + for i = 1, 150 do minetest.after(math.random(1, 2)*math.random(), function() local new_pos = obj:get_pos() - minetest.add_entity({x=new_pos.x, y=new_pos.y + 1, z=new_pos.z}, particle) + minetest.add_entity({x = new_pos.x, y = new_pos.y + 1, z = new_pos.z}, "mcl_totems:totem_particle") end) end From 99ccd9ea4c77d09a7e4062f16819a3bbdff9fe53 Mon Sep 17 00:00:00 2001 From: NO11 Date: Tue, 8 Jun 2021 15:13:00 +0000 Subject: [PATCH 04/14] Fix possible crash --- mods/ITEMS/mcl_totems/init.lua | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/mods/ITEMS/mcl_totems/init.lua b/mods/ITEMS/mcl_totems/init.lua index a6429f7b87..1847d579b6 100644 --- a/mods/ITEMS/mcl_totems/init.lua +++ b/mods/ITEMS/mcl_totems/init.lua @@ -22,8 +22,11 @@ minetest.register_entity("mcl_totems:totem_particle", { self.object:set_properties({ textures = {"mcl_particles_totem"..math.random(1, 4)..".png^[colorize:"..colors[math.random(#colors)]} }) - self.object:set_velocity({x = math.random(-4, 4)*math.random(), y = math.random(-1, 4)*math.random(), z = math.random(-4, 4)*math.random()}) - minetest.after(0.3, function() + local t = math.random(1, 2)*math.random() + minetest.after(t, function() + self.object:set_velocity({x = math.random(-4, 4)*math.random(), y = math.random(-1, 4)*math.random(), z = math.random(-4, 4)*math.random()}) + end) + minetest.after(0.3 + t, function() self.object:set_acceleration({x=0, y=-4, z=0}) self.object:set_velocity({x=0, y=0, z=0}) end) @@ -65,12 +68,14 @@ mcl_damage.register_modifier(function(obj, damage, reason) minetest.sound_play({name = "mcl_totems_totem", gain=1}, {pos=ppos, max_hear_distance=16}, true) --Particles - for i = 1, 150 do - minetest.after(math.random(1, 2)*math.random(), function() - local new_pos = obj:get_pos() + + minetest.after(0.1, function() + local new_pos = obj:get_pos() + if not new_pos then return end + for i = 1, 150 do minetest.add_entity({x = new_pos.x, y = new_pos.y + 1, z = new_pos.z}, "mcl_totems:totem_particle") - end) - end + end + end) -- Big totem overlay if not hud_totem[obj] then From ee2fa60cae6f151720c1ac7949218f7fee6d4013 Mon Sep 17 00:00:00 2001 From: NO11 Date: Wed, 9 Jun 2021 14:47:42 +0000 Subject: [PATCH 05/14] local totem particle position --- mods/ITEMS/mcl_totems/init.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_totems/init.lua b/mods/ITEMS/mcl_totems/init.lua index 1847d579b6..ecdc20da07 100644 --- a/mods/ITEMS/mcl_totems/init.lua +++ b/mods/ITEMS/mcl_totems/init.lua @@ -72,8 +72,9 @@ mcl_damage.register_modifier(function(obj, damage, reason) minetest.after(0.1, function() local new_pos = obj:get_pos() if not new_pos then return end + local particlepos = {x = new_pos.x, y = new_pos.y + 1, z = new_pos.z} for i = 1, 150 do - minetest.add_entity({x = new_pos.x, y = new_pos.y + 1, z = new_pos.z}, "mcl_totems:totem_particle") + minetest.add_entity(particlepos, "mcl_totems:totem_particle") end end) From 509568b4b01e7529af9c8ad1e00980eba7bbd648 Mon Sep 17 00:00:00 2001 From: NO11 Date: Thu, 8 Jul 2021 16:49:19 +0000 Subject: [PATCH 06/14] Use real Minecraft colors for totem particles! --- mods/ITEMS/mcl_totems/init.lua | 38 ++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/mods/ITEMS/mcl_totems/init.lua b/mods/ITEMS/mcl_totems/init.lua index ecdc20da07..2311e88d70 100644 --- a/mods/ITEMS/mcl_totems/init.lua +++ b/mods/ITEMS/mcl_totems/init.lua @@ -5,8 +5,32 @@ minetest.register_on_leaveplayer(function(player) end) -- Totem particle registration --- TODO: real MC colors, these are randomly selected colors: -local colors = {"#7FFF00", "#698B22", "#BCEE68", "#EEEE00", "#C5F007"} +function rgb_to_hex(rgb) + local hexadecimal = "#" + + for key, value in pairs(rgb) do + local hex = "" + + while value > 0 do + local index = math.fmod(value, 16) + 1 + value = math.floor(value / 16) + hex = string.sub("0123456789ABCDEF", index, index) .. hex + end + + local len = string.len(hex) + + if len == 0 then + hex = "00" + elseif len == 1 then + hex = "0" .. hex + end + + hexadecimal = hexadecimal .. hex + end + + return hexadecimal +end + minetest.register_entity("mcl_totems:totem_particle", { physical = true, collide_with_objects = false, @@ -17,10 +41,16 @@ minetest.register_entity("mcl_totems:totem_particle", { spritediv = {x=1, y=1}, initial_sprite_basepos = {x=0, y=0}, static_save = false, - glow = 5, + glow = 14, on_activate = function(self, staticdata) + local color + if math.random(0, 3) == 0 then + color = rgb_to_hex({ (0.6 + math.random() * 0.2) * 255, (0.6 + math.random() * 0.3) * 255, (math.random() * 0.2) * 255 }) + else + color = rgb_to_hex({ (0.1 + math.random() * 0.4) * 255, (0.6 + math.random() * 0.3) * 255, (math.random() * 0.2) * 255 }) + end self.object:set_properties({ - textures = {"mcl_particles_totem"..math.random(1, 4)..".png^[colorize:"..colors[math.random(#colors)]} + textures = { "mcl_particles_totem"..math.random(1, 4)..".png^[colorize:"..color } }) local t = math.random(1, 2)*math.random() minetest.after(t, function() From 5ceb48fcb13ae20a4295cc7c0d4cbcfa30c26a8c Mon Sep 17 00:00:00 2001 From: NO11 Date: Mon, 12 Jul 2021 18:05:52 +0000 Subject: [PATCH 07/14] Faster rgb to hex --- mods/ITEMS/mcl_totems/init.lua | 61 +++++++++++----------------------- 1 file changed, 20 insertions(+), 41 deletions(-) diff --git a/mods/ITEMS/mcl_totems/init.lua b/mods/ITEMS/mcl_totems/init.lua index 2311e88d70..5f9b254a3d 100644 --- a/mods/ITEMS/mcl_totems/init.lua +++ b/mods/ITEMS/mcl_totems/init.lua @@ -5,64 +5,43 @@ minetest.register_on_leaveplayer(function(player) end) -- Totem particle registration -function rgb_to_hex(rgb) - local hexadecimal = "#" - for key, value in pairs(rgb) do - local hex = "" - - while value > 0 do - local index = math.fmod(value, 16) + 1 - value = math.floor(value / 16) - hex = string.sub("0123456789ABCDEF", index, index) .. hex - end - - local len = string.len(hex) - - if len == 0 then - hex = "00" - elseif len == 1 then - hex = "0" .. hex - end - - hexadecimal = hexadecimal .. hex - end - - return hexadecimal +function rgb_to_hex(r, g, b) + return string.format("%02x%02x%02x", r, g, b) end minetest.register_entity("mcl_totems:totem_particle", { physical = true, collide_with_objects = false, - collisionbox = {-0.02,-0.02,-0.02, 0.02,0.02,0.02}, + collisionbox = { -0.02, -0.02, -0.02, 0.02, 0.02, 0.02 }, pointable = false, visual = "sprite", - visual_size = {x=0.2, y=0.2}, - spritediv = {x=1, y=1}, - initial_sprite_basepos = {x=0, y=0}, + visual_size = { x = 0.2, y = 0.2 }, + spritediv = { x = 1, y = 1 }, + initial_sprite_basepos = { x = 0, y = 0 }, static_save = false, glow = 14, on_activate = function(self, staticdata) local color if math.random(0, 3) == 0 then - color = rgb_to_hex({ (0.6 + math.random() * 0.2) * 255, (0.6 + math.random() * 0.3) * 255, (math.random() * 0.2) * 255 }) + color = rgb_to_hex( 153 + math.random() * 51, 153 + math.random() * 76.5, math.random() * 51) else - color = rgb_to_hex({ (0.1 + math.random() * 0.4) * 255, (0.6 + math.random() * 0.3) * 255, (math.random() * 0.2) * 255 }) + color = rgb_to_hex(25.5 + math.random() * 102, 153 + math.random() * 76.5, math.random() * 51) end self.object:set_properties({ - textures = { "mcl_particles_totem"..math.random(1, 4)..".png^[colorize:"..color } + textures = { "mcl_particles_totem"..math.random(1, 4)..".png^[colorize:#"..color } }) local t = math.random(1, 2)*math.random() minetest.after(t, function() - self.object:set_velocity({x = math.random(-4, 4)*math.random(), y = math.random(-1, 4)*math.random(), z = math.random(-4, 4)*math.random()}) + self.object:set_velocity({ x = math.random(-4, 4) * math.random(), y = math.random(-1, 4) * math.random(), z = math.random(-4, 4) * math.random() }) end) minetest.after(0.3 + t, function() - self.object:set_acceleration({x=0, y=-4, z=0}) - self.object:set_velocity({x=0, y=0, z=0}) + self.object:set_acceleration({ x = 0, y = -4, z = 0 }) + self.object:set_velocity({ x = 0, y = 0, z = 0 }) end) end, on_step = function(self, dtime) - local r = math.random(1,50) + local r = math.random(1, 50) if r == 1 then self.object:remove() end @@ -79,7 +58,7 @@ mcl_damage.register_modifier(function(obj, damage, reason) local ppos = obj:get_pos() local pnname = minetest.get_node(ppos).name -- Some exceptions when _not_ to save the player - for n=1, #mobs_mc.misc.totem_fail_nodes do + for n = 1, #mobs_mc.misc.totem_fail_nodes do if pnname == mobs_mc.misc.totem_fail_nodes[n] then return end @@ -95,14 +74,14 @@ mcl_damage.register_modifier(function(obj, damage, reason) end -- Effects - minetest.sound_play({name = "mcl_totems_totem", gain=1}, {pos=ppos, max_hear_distance=16}, true) + minetest.sound_play({ name = "mcl_totems_totem", gain = 1 }, { pos = ppos, max_hear_distance = 16 }, true) --Particles minetest.after(0.1, function() local new_pos = obj:get_pos() if not new_pos then return end - local particlepos = {x = new_pos.x, y = new_pos.y + 1, z = new_pos.z} + local particlepos = { x = new_pos.x, y = new_pos.y + 1, z = new_pos.z } for i = 1, 150 do minetest.add_entity(particlepos, "mcl_totems:totem_particle") end @@ -113,9 +92,9 @@ mcl_damage.register_modifier(function(obj, damage, reason) hud_totem[obj] = obj:hud_add({ hud_elem_type = "image", text = "mcl_totems_totem.png", - position = { x=0.5, y=1 }, - scale = { x=17, y=17 }, - offset = { x=0, y=-178 }, + position = { x = 0.5, y = 1 }, + scale = { x = 17, y = 17 }, + offset = { x = 0, y = -178 }, z_index = 100, }) minetest.after(3, function() @@ -131,4 +110,4 @@ mcl_damage.register_modifier(function(obj, damage, reason) end end end -end, 1000) \ No newline at end of file +end, 1000) From 2b322a451f9ecd71918c9eeb6f40a386d031bfea Mon Sep 17 00:00:00 2001 From: NO11 Date: Thu, 26 Aug 2021 10:17:15 +0000 Subject: [PATCH 08/14] remove space --- mods/ITEMS/mcl_totems/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_totems/init.lua b/mods/ITEMS/mcl_totems/init.lua index 5f9b254a3d..2206fcb2aa 100644 --- a/mods/ITEMS/mcl_totems/init.lua +++ b/mods/ITEMS/mcl_totems/init.lua @@ -87,7 +87,7 @@ mcl_damage.register_modifier(function(obj, damage, reason) end end) - -- Big totem overlay + -- Big totem overlay if not hud_totem[obj] then hud_totem[obj] = obj:hud_add({ hud_elem_type = "image", From dafe860e56ac7ce866affe414fe7eef20b5fd3db Mon Sep 17 00:00:00 2001 From: NO11 Date: Sun, 24 Oct 2021 19:31:51 +0000 Subject: [PATCH 09/14] simple totem particles --- mods/ITEMS/mcl_totems/init.lua | 77 +++++++++------------------------- 1 file changed, 20 insertions(+), 57 deletions(-) diff --git a/mods/ITEMS/mcl_totems/init.lua b/mods/ITEMS/mcl_totems/init.lua index 2206fcb2aa..79b2c8de01 100644 --- a/mods/ITEMS/mcl_totems/init.lua +++ b/mods/ITEMS/mcl_totems/init.lua @@ -4,49 +4,7 @@ minetest.register_on_leaveplayer(function(player) hud_totem[player] = nil end) --- Totem particle registration - -function rgb_to_hex(r, g, b) - return string.format("%02x%02x%02x", r, g, b) -end - -minetest.register_entity("mcl_totems:totem_particle", { - physical = true, - collide_with_objects = false, - collisionbox = { -0.02, -0.02, -0.02, 0.02, 0.02, 0.02 }, - pointable = false, - visual = "sprite", - visual_size = { x = 0.2, y = 0.2 }, - spritediv = { x = 1, y = 1 }, - initial_sprite_basepos = { x = 0, y = 0 }, - static_save = false, - glow = 14, - on_activate = function(self, staticdata) - local color - if math.random(0, 3) == 0 then - color = rgb_to_hex( 153 + math.random() * 51, 153 + math.random() * 76.5, math.random() * 51) - else - color = rgb_to_hex(25.5 + math.random() * 102, 153 + math.random() * 76.5, math.random() * 51) - end - self.object:set_properties({ - textures = { "mcl_particles_totem"..math.random(1, 4)..".png^[colorize:#"..color } - }) - local t = math.random(1, 2)*math.random() - minetest.after(t, function() - self.object:set_velocity({ x = math.random(-4, 4) * math.random(), y = math.random(-1, 4) * math.random(), z = math.random(-4, 4) * math.random() }) - end) - minetest.after(0.3 + t, function() - self.object:set_acceleration({ x = 0, y = -4, z = 0 }) - self.object:set_velocity({ x = 0, y = 0, z = 0 }) - end) - end, - on_step = function(self, dtime) - local r = math.random(1, 50) - if r == 1 then - self.object:remove() - end - end -}) +local particle_colors = {"98BF22", "C49E09", "337D0B", "B0B021", "1E9200"} -- TODO: real MC colors -- Save the player from death when holding totem of undying in hand mcl_damage.register_modifier(function(obj, damage, reason) @@ -74,27 +32,32 @@ mcl_damage.register_modifier(function(obj, damage, reason) end -- Effects - minetest.sound_play({ name = "mcl_totems_totem", gain = 1 }, { pos = ppos, max_hear_distance = 16 }, true) - - --Particles + minetest.sound_play({name = "mcl_totems_totem", gain = 1}, {pos=ppos, max_hear_distance = 16}, true) - minetest.after(0.1, function() - local new_pos = obj:get_pos() - if not new_pos then return end - local particlepos = { x = new_pos.x, y = new_pos.y + 1, z = new_pos.z } - for i = 1, 150 do - minetest.add_entity(particlepos, "mcl_totems:totem_particle") - end - end) + for i = 1, 100 do + minetest.add_particle({ + pos = vector.offset(ppos, 0, math.random(-10, 10) / 10, 0), + velocity = vector.new(math.random(-15, 15) / 10, math.random(0, 15) / 10, math.random(-15, 15) / 10), + acceleration = vector.new(0, -math.random(1, 10) / 10, 0), + expirationtime = math.random(1, 3), + size = math.random(1, 2), + collisiondetection = true, + collision_removal = true, + object_collision = false, + texture = "mcl_particles_totem" .. math.random(1, 4) .. ".png^[colorize:#" .. particle_colors[math.random(#particle_colors)], + glow = 10, + }) + + end -- Big totem overlay if not hud_totem[obj] then hud_totem[obj] = obj:hud_add({ hud_elem_type = "image", text = "mcl_totems_totem.png", - position = { x = 0.5, y = 1 }, - scale = { x = 17, y = 17 }, - offset = { x = 0, y = -178 }, + position = {x = 0.5, y = 1}, + scale = {x = 17, y = 17}, + offset = {x = 0, y = -178}, z_index = 100, }) minetest.after(3, function() From 74890101520d4b04578dbc333aab38ea6cdf6eca Mon Sep 17 00:00:00 2001 From: NO11 Date: Mon, 25 Oct 2021 17:08:38 +0000 Subject: [PATCH 10/14] Use particlespawners instead of single particles --- mods/ITEMS/mcl_totems/init.lua | 37 +++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/mods/ITEMS/mcl_totems/init.lua b/mods/ITEMS/mcl_totems/init.lua index 79b2c8de01..aa188855fc 100644 --- a/mods/ITEMS/mcl_totems/init.lua +++ b/mods/ITEMS/mcl_totems/init.lua @@ -34,20 +34,29 @@ mcl_damage.register_modifier(function(obj, damage, reason) -- Effects minetest.sound_play({name = "mcl_totems_totem", gain = 1}, {pos=ppos, max_hear_distance = 16}, true) - for i = 1, 100 do - minetest.add_particle({ - pos = vector.offset(ppos, 0, math.random(-10, 10) / 10, 0), - velocity = vector.new(math.random(-15, 15) / 10, math.random(0, 15) / 10, math.random(-15, 15) / 10), - acceleration = vector.new(0, -math.random(1, 10) / 10, 0), - expirationtime = math.random(1, 3), - size = math.random(1, 2), - collisiondetection = true, - collision_removal = true, - object_collision = false, - texture = "mcl_particles_totem" .. math.random(1, 4) .. ".png^[colorize:#" .. particle_colors[math.random(#particle_colors)], - glow = 10, - }) - + for i = 1, 4 do + for c = 1, #particle_colors do + minetest.add_particlespawner({ + amount = math.round(100/(4 * #particle_colors)), + time = 1, + minpos = vector.offset(ppos, 0, -1, 0), + maxpos = vector.offset(ppos, 0, 1, 0), + minvel = vector.new(-1.5, 0, -1.5), + maxvel = vector.new(1.5, 1.5, 1.5), + minacc = vector.new(0, -0.1, 0), + maxacc = vector.new(0, -1, 0), + minexptime = 1, + maxexptime = 3, + minsize = 1, + maxsize = 2, + collisiondetection = true, + collision_removal = true, + object_collision = false, + vertical = false, + texture = "mcl_particles_totem" .. i .. ".png^[colorize:#" .. particle_colors[c], + glow = 10, + }) + end end -- Big totem overlay From eccba76732bff067bf677bee46acfc51e1298234 Mon Sep 17 00:00:00 2001 From: NO11 Date: Mon, 25 Oct 2021 20:25:34 +0000 Subject: [PATCH 11/14] Use math.floor instead of math.round --- mods/ITEMS/mcl_totems/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_totems/init.lua b/mods/ITEMS/mcl_totems/init.lua index aa188855fc..b11e68df77 100644 --- a/mods/ITEMS/mcl_totems/init.lua +++ b/mods/ITEMS/mcl_totems/init.lua @@ -37,7 +37,7 @@ mcl_damage.register_modifier(function(obj, damage, reason) for i = 1, 4 do for c = 1, #particle_colors do minetest.add_particlespawner({ - amount = math.round(100/(4 * #particle_colors)), + amount = math.floor(100 / (4 * #particle_colors)), time = 1, minpos = vector.offset(ppos, 0, -1, 0), maxpos = vector.offset(ppos, 0, 1, 0), From 19689dd857c047fb857489ed4385b4c5440400c6 Mon Sep 17 00:00:00 2001 From: NO11 Date: Tue, 26 Oct 2021 16:50:10 +0000 Subject: [PATCH 12/14] Use enchanted golden apple for thing banner --- mods/ITEMS/mcl_banners/patterncraft.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_banners/patterncraft.lua b/mods/ITEMS/mcl_banners/patterncraft.lua index 79778a6657..767235b1e2 100644 --- a/mods/ITEMS/mcl_banners/patterncraft.lua +++ b/mods/ITEMS/mcl_banners/patterncraft.lua @@ -119,8 +119,7 @@ local patterns = { name = N("@1 Thing Charge"), type = "shapeless", - -- TODO: Replace with enchanted golden apple - { e, "mcl_core:apple_gold", d }, + { e, "mcl_core:apple_gold_enchanted", d }, }, ["rhombus"] = { name = N("@1 Lozenge"), From 5b37f5600504608e3cd0dbffc1c43c15a6b6c14d Mon Sep 17 00:00:00 2001 From: NO11 Date: Thu, 28 Oct 2021 09:43:14 +0000 Subject: [PATCH 13/14] Remove small gray border of buttons in creative inventory pages --- mods/HUD/mcl_inventory/creative.lua | 1339 +++++++++++++-------------- 1 file changed, 669 insertions(+), 670 deletions(-) diff --git a/mods/HUD/mcl_inventory/creative.lua b/mods/HUD/mcl_inventory/creative.lua index ff9cccf9e1..2be0be4bc1 100644 --- a/mods/HUD/mcl_inventory/creative.lua +++ b/mods/HUD/mcl_inventory/creative.lua @@ -1,670 +1,669 @@ -local S = minetest.get_translator(minetest.get_current_modname()) -local F = minetest.formspec_escape - --- Prepare player info table -local players = {} - --- Containing all the items for each Creative Mode tab -local inventory_lists = {} - ---local mod_player = minetest.get_modpath("mcl_player") - --- Create tables -local builtin_filter_ids = {"blocks","deco","redstone","rail","food","tools","combat","mobs","brew","matr","misc","all"} -for _, f in pairs(builtin_filter_ids) do - inventory_lists[f] = {} -end - -local function replace_enchanted_books(tbl) - for k, item in ipairs(tbl) do - if item:find("mcl_enchanting:book_enchanted") == 1 then - local _, enchantment, level = item:match("(%a+) ([_%w]+) (%d+)") - level = level and tonumber(level) - if enchantment and level then - tbl[k] = mcl_enchanting.enchant(ItemStack("mcl_enchanting:book_enchanted"), enchantment, level) - end - end - end -end - ---[[ Populate all the item tables. We only do this once. Note this code must be -executed after loading all the other mods in order to work. ]] -minetest.register_on_mods_loaded(function() - for name,def in pairs(minetest.registered_items) do - if (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0) and def.description and def.description ~= "" then - local function is_redstone(def) - return def.mesecons or def.groups.mesecon or def.groups.mesecon_conductor_craftable or def.groups.mesecon_effecor_off - end - local function is_tool(def) - return def.groups.tool or (def.tool_capabilities and def.tool_capabilities.damage_groups == nil) - end - local function is_weapon_or_armor(def) - return def.groups.weapon or def.groups.weapon_ranged or def.groups.ammo or def.groups.combat_item or ((def.groups.armor_head or def.groups.armor_torso or def.groups.armor_legs or def.groups.armor_feet or def.groups.horse_armor) and def.groups.non_combat_armor ~= 1) - end - -- Is set to true if it was added in any category besides misc - local nonmisc = false - if def.groups.building_block then - table.insert(inventory_lists["blocks"], name) - nonmisc = true - end - if def.groups.deco_block then - table.insert(inventory_lists["deco"], name) - nonmisc = true - end - if is_redstone(def) then - table.insert(inventory_lists["redstone"], name) - nonmisc = true - end - if def.groups.transport then - table.insert(inventory_lists["rail"], name) - nonmisc = true - end - if (def.groups.food and not def.groups.brewitem) or def.groups.eatable then - table.insert(inventory_lists["food"], name) - nonmisc = true - end - if is_tool(def) then - table.insert(inventory_lists["tools"], name) - nonmisc = true - end - if is_weapon_or_armor(def) then - table.insert(inventory_lists["combat"], name) - nonmisc = true - end - if def.groups.spawn_egg == 1 then - table.insert(inventory_lists["mobs"], name) - nonmisc = true - end - if def.groups.brewitem then - table.insert(inventory_lists["brew"], name) - nonmisc = true - end - if def.groups.craftitem then - table.insert(inventory_lists["matr"], name) - nonmisc = true - end - -- Misc. category is for everything which is not in any other category - if not nonmisc then - table.insert(inventory_lists["misc"], name) - end - - table.insert(inventory_lists["all"], name) - end - end - - for ench, def in pairs(mcl_enchanting.enchantments) do - local str = "mcl_enchanting:book_enchanted " .. ench .. " " .. def.max_level - if def.inv_tool_tab then - table.insert(inventory_lists["tools"], str) - end - if def.inv_combat_tab then - table.insert(inventory_lists["combat"], str) - end - table.insert(inventory_lists["all"], str) - end - - for _, to_sort in pairs(inventory_lists) do - table.sort(to_sort) - replace_enchanted_books(to_sort) - end -end) - -local function filter_item(name, description, lang, filter) - local desc - if not lang then - desc = string.lower(description) - else - desc = string.lower(minetest.get_translated_string(lang, description)) - end - return string.find(name, filter) or string.find(desc, filter) -end - -local function set_inv_search(filter, player) - local playername = player:get_player_name() - local inv = minetest.get_inventory({type="detached", name="creative_"..playername}) - local creative_list = {} - local lang = minetest.get_player_information(playername).lang_code - for name,def in pairs(minetest.registered_items) do - if (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0) and def.description and def.description ~= "" then - if filter_item(string.lower(def.name), def.description, lang, filter) then - table.insert(creative_list, name) - end - end - end - for ench, def in pairs(mcl_enchanting.enchantments) do - for i = 1, def.max_level do - local stack = mcl_enchanting.enchant(ItemStack("mcl_enchanting:book_enchanted"), ench, i) - if filter_item("mcl_enchanting:book_enchanted", minetest.strip_colors(stack:get_description()), lang, filter) then - table.insert(creative_list, "mcl_enchanting:book_enchanted " .. ench .. " " .. i) - end - end - end - table.sort(creative_list) - replace_enchanted_books(creative_list) - - inv:set_size("main", #creative_list) - inv:set_list("main", creative_list) -end - -local function set_inv_page(page, player) - local playername = player:get_player_name() - local inv = minetest.get_inventory({type="detached", name="creative_"..playername}) - inv:set_size("main", 0) - local creative_list = {} - if inventory_lists[page] then -- Standard filter - creative_list = inventory_lists[page] - end - inv:set_size("main", #creative_list) - inv:set_list("main", creative_list) -end - -local function init(player) - local playername = player:get_player_name() - minetest.create_detached_inventory("creative_"..playername, { - allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) - if minetest.is_creative_enabled(playername) then - return count - else - return 0 - end - end, - allow_put = function(inv, listname, index, stack, player) - return 0 - end, - allow_take = function(inv, listname, index, stack, player) - if minetest.is_creative_enabled(player:get_player_name()) then - return -1 - else - return 0 - end - end, - }, playername) - set_inv_page("all", player) -end - --- Create the trash field -local trash = minetest.create_detached_inventory("trash", { - allow_put = function(inv, listname, index, stack, player) - if minetest.is_creative_enabled(player:get_player_name()) then - return stack:get_count() - else - return 0 - end - end, - on_put = function(inv, listname, index, stack, player) - inv:set_stack(listname, index, "") - end, -}) -trash:set_size("main", 1) - -local noffset = {} -- numeric tab offset -local offset = {} -- string offset: -local boffset = {} -- -local hoch = {} -local filtername = {} ---local bg = {} - -local noffset_x_start = -0.24 -local noffset_x = noffset_x_start -local noffset_y = -0.25 -local function next_noffset(id, right) - if right then - noffset[id] = { 8.94, noffset_y } - else - noffset[id] = { noffset_x, noffset_y } - noffset_x = noffset_x + 1.25 - end -end - --- Upper row -next_noffset("blocks") -next_noffset("deco") -next_noffset("redstone") -next_noffset("rail") -next_noffset("brew") -next_noffset("misc") -next_noffset("nix", true) - -noffset_x = noffset_x_start -noffset_y = 8.12 - --- Lower row -next_noffset("food") -next_noffset("tools") -next_noffset("combat") -next_noffset("mobs") -next_noffset("matr") -next_noffset("inv", true) - -for k,v in pairs(noffset) do - offset[k] = tostring(v[1]) .. "," .. tostring(v[2]) - boffset[k] = tostring(v[1]+0.19) .. "," .. tostring(v[2]+0.25) -end - -hoch["blocks"] = "" -hoch["deco"] = "" -hoch["redstone"] = "" -hoch["rail"] = "" -hoch["brew"] = "" -hoch["misc"] = "" -hoch["nix"] = "" -hoch["default"] = "" -hoch["food"] = "_down" -hoch["tools"] = "_down" -hoch["combat"] = "_down" -hoch["mobs"] = "_down" -hoch["matr"] = "_down" -hoch["inv"] = "_down" - -filtername["blocks"] = S("Building Blocks") -filtername["deco"] = S("Decoration Blocks") -filtername["redstone"] = S("Redstone") -filtername["rail"] = S("Transportation") -filtername["misc"] = S("Miscellaneous") -filtername["nix"] = S("Search Items") -filtername["food"] = S("Foodstuffs") -filtername["tools"] = S("Tools") -filtername["combat"] = S("Combat") -filtername["mobs"] = S("Mobs") -filtername["brew"] = S("Brewing") -filtername["matr"] = S("Materials") -filtername["inv"] = S("Survival Inventory") - ---local dark_bg = "crafting_creative_bg_dark.png" - ---[[local function reset_menu_item_bg() - bg["blocks"] = dark_bg - bg["deco"] = dark_bg - bg["redstone"] = dark_bg - bg["rail"] = dark_bg - bg["misc"] = dark_bg - bg["nix"] = dark_bg - bg["food"] = dark_bg - bg["tools"] = dark_bg - bg["combat"] = dark_bg - bg["mobs"] = dark_bg - bg["brew"] = dark_bg - bg["matr"] = dark_bg - bg["inv"] = dark_bg - bg["default"] = dark_bg -end]] - - -function mcl_inventory.set_creative_formspec(player, start_i, pagenum, inv_size, show, page, filter) - --reset_menu_item_bg() - pagenum = math.floor(pagenum) or 1 - - local playername = player:get_player_name() - - if not inv_size then - if page == "nix" then - local inv = minetest.get_inventory({type="detached", name="creative_"..playername}) - inv_size = inv:get_size("main") - elseif page and page ~= "inv" then - inv_size = #(inventory_lists[page]) - else - inv_size = 0 - end - end - local pagemax = math.max(1, math.floor((inv_size-1) / (9*5) + 1)) - local name = "nix" - local main_list - local listrings = "listring[detached:creative_"..playername..";main]".. - "listring[current_player;main]".. - "listring[detached:trash;main]" - - if page then - name = page - if players[playername] then - players[playername].page = page - end - end - --bg[name] = "crafting_creative_bg.png" - - local inv_bg = "crafting_inventory_creative.png" - if name == "inv" then - inv_bg = "crafting_inventory_creative_survival.png" - - -- Show armor and player image - local player_preview - if minetest.settings:get_bool("3d_player_preview", true) then - player_preview = mcl_player.get_player_formspec_model(player, 3.9, 1.4, 1.2333, 2.4666, "") - else - player_preview = "image[3.9,1.4;1.2333,2.4666;"..mcl_player.player_get_preview(player).."]" - end - - -- Background images for armor slots (hide if occupied) - local armor_slot_imgs = "" - local inv = player:get_inventory() - if inv:get_stack("armor", 2):is_empty() then - armor_slot_imgs = armor_slot_imgs .. "image[2.5,1.3;1,1;mcl_inventory_empty_armor_slot_helmet.png]" - end - if inv:get_stack("armor", 3):is_empty() then - armor_slot_imgs = armor_slot_imgs .. "image[2.5,2.75;1,1;mcl_inventory_empty_armor_slot_chestplate.png]" - end - if inv:get_stack("armor", 4):is_empty() then - armor_slot_imgs = armor_slot_imgs .. "image[5.5,1.3;1,1;mcl_inventory_empty_armor_slot_leggings.png]" - end - if inv:get_stack("armor", 5):is_empty() then - armor_slot_imgs = armor_slot_imgs .. "image[5.5,2.75;1,1;mcl_inventory_empty_armor_slot_boots.png]" - end - - -- Survival inventory slots - main_list = "list[current_player;main;0,3.75;9,3;9]".. - mcl_formspec.get_itemslot_bg(0,3.75,9,3).. - -- armor - "list[current_player;armor;2.5,1.3;1,1;1]".. - "list[current_player;armor;2.5,2.75;1,1;2]".. - "list[current_player;armor;5.5,1.3;1,1;3]".. - "list[current_player;armor;5.5,2.75;1,1;4]".. - mcl_formspec.get_itemslot_bg(2.5,1.3,1,1).. - mcl_formspec.get_itemslot_bg(2.5,2.75,1,1).. - mcl_formspec.get_itemslot_bg(5.5,1.3,1,1).. - mcl_formspec.get_itemslot_bg(5.5,2.75,1,1).. - armor_slot_imgs.. - -- player preview - player_preview.. - -- crafting guide button - "image_button[9,1;1,1;craftguide_book.png;__mcl_craftguide;]".. - "tooltip[__mcl_craftguide;"..F(S("Recipe book")).."]".. - -- help button - "image_button[9,2;1,1;doc_button_icon_lores.png;__mcl_doc;]".. - "tooltip[__mcl_doc;"..F(S("Help")).."]".. - -- skins button - "image_button[9,3;1,1;mcl_skins_button.png;__mcl_skins;]".. - "tooltip[__mcl_skins;"..F(S("Select player skin")).."]".. - -- achievements button - "image_button[9,4;1,1;mcl_achievements_button.png;__mcl_achievements;]".. - --"style_type[image_button;border=;bgimg=;bgimg_pressed=]".. - "tooltip[__mcl_achievements;"..F(S("Achievements")).."]" - - -- For shortcuts - listrings = listrings .. - "listring[detached:"..playername.."_armor;armor]".. - "listring[current_player;main]" - else - -- Creative inventory slots - main_list = "list[detached:creative_"..playername..";main;0,1.75;9,5;"..tostring(start_i).."]".. - mcl_formspec.get_itemslot_bg(0,1.75,9,5).. - -- Page buttons - "label[9.0,5.5;"..F(S("@1/@2", pagenum, pagemax)).."]".. - "image_button[9.0,6.0;0.7,0.7;crafting_creative_prev.png;creative_prev;]".. - "image_button[9.5,6.0;0.7,0.7;crafting_creative_next.png;creative_next;]" - end - - local tab_icon = { - blocks = "mcl_core:brick_block", - deco = "mcl_flowers:peony", - redstone = "mesecons:redstone", - rail = "mcl_minecarts:golden_rail", - misc = "mcl_buckets:bucket_lava", - nix = "mcl_compass:compass", - food = "mcl_core:apple", - tools = "mcl_core:axe_iron", - combat = "mcl_core:sword_gold", - mobs = "mobs_mc:cow", - brew = "mcl_potions:dragon_breath", - matr = "mcl_core:stick", - inv = "mcl_chests:chest", - } - local function tab(current_tab, this_tab) - local bg_img - if current_tab == this_tab then - bg_img = "crafting_creative_active"..hoch[this_tab]..".png" - else - bg_img = "crafting_creative_inactive"..hoch[this_tab]..".png" - end - return - "style["..this_tab..";border=false;bgimg=;bgimg_pressed=]".. - "item_image_button[" .. boffset[this_tab] ..";1,1;"..tab_icon[this_tab]..";"..this_tab..";]".. - "image[" .. offset[this_tab] .. ";1.5,1.44;" .. bg_img .. "]" .. - "image[" .. boffset[this_tab] .. ";1,1;crafting_creative_marker.png]" - end - local caption = "" - if name ~= "inv" and filtername[name] then - caption = "label[0,1.2;"..F(minetest.colorize("#313131", filtername[name])).."]" - end - - local formspec = "size[10,9.3]".. - "no_prepend[]".. - mcl_vars.gui_nonbg..mcl_vars.gui_bg_color.. - "background[-0.19,-0.25;10.5,9.87;"..inv_bg.."]".. - "label[-5,-5;"..name.."]".. - tab(name, "blocks") .. - "tooltip[blocks;"..F(filtername["blocks"]).."]".. - tab(name, "deco") .. - "tooltip[deco;"..F(filtername["deco"]).."]".. - tab(name, "redstone") .. - "tooltip[redstone;"..F(filtername["redstone"]).."]".. - tab(name, "rail") .. - "tooltip[rail;"..F(filtername["rail"]).."]".. - tab(name, "misc") .. - "tooltip[misc;"..F(filtername["misc"]).."]".. - tab(name, "nix") .. - "tooltip[nix;"..F(filtername["nix"]).."]".. - caption.. - "list[current_player;main;0,7;9,1;]".. - mcl_formspec.get_itemslot_bg(0,7,9,1).. - main_list.. - tab(name, "food") .. - "tooltip[food;"..F(filtername["food"]).."]".. - tab(name, "tools") .. - "tooltip[tools;"..F(filtername["tools"]).."]".. - tab(name, "combat") .. - "tooltip[combat;"..F(filtername["combat"]).."]".. - tab(name, "mobs") .. - "tooltip[mobs;"..F(filtername["mobs"]).."]".. - tab(name, "brew") .. - "tooltip[brew;"..F(filtername["brew"]).."]".. - tab(name, "matr") .. - "tooltip[matr;"..F(filtername["matr"]).."]".. - tab(name, "inv") .. - "tooltip[inv;"..F(filtername["inv"]).."]".. - "list[detached:trash;main;9,7;1,1;]".. - mcl_formspec.get_itemslot_bg(9,7,1,1).. - "image[9,7;1,1;crafting_creative_trash.png]".. - listrings - - if name == "nix" then - if filter == nil then - filter = "" - end - formspec = formspec .. "field[5.3,1.34;4,0.75;search;;"..minetest.formspec_escape(filter).."]" - formspec = formspec .. "field_close_on_enter[search;false]" - end - if pagenum then formspec = formspec .. "p"..tostring(pagenum) end - player:set_inventory_formspec(formspec) -end - -minetest.register_on_player_receive_fields(function(player, formname, fields) - local page = nil - - if not minetest.is_creative_enabled(player:get_player_name()) then - return - end - if formname ~= "" or fields.quit == "true" then - -- No-op if formspec closed or not player inventory (formname == "") - return - end - - local name = player:get_player_name() - - if fields.blocks then - if players[name].page == "blocks" then return end - set_inv_page("blocks",player) - page = "blocks" - elseif fields.deco then - if players[name].page == "deco" then return end - set_inv_page("deco",player) - page = "deco" - elseif fields.redstone then - if players[name].page == "redstone" then return end - set_inv_page("redstone",player) - page = "redstone" - elseif fields.rail then - if players[name].page == "rail" then return end - set_inv_page("rail",player) - page = "rail" - elseif fields.misc then - if players[name].page == "misc" then return end - set_inv_page("misc",player) - page = "misc" - elseif fields.nix then - set_inv_page("all",player) - page = "nix" - elseif fields.food then - if players[name].page == "food" then return end - set_inv_page("food",player) - page = "food" - elseif fields.tools then - if players[name].page == "tools" then return end - set_inv_page("tools",player) - page = "tools" - elseif fields.combat then - if players[name].page == "combat" then return end - set_inv_page("combat",player) - page = "combat" - elseif fields.mobs then - if players[name].page == "mobs" then return end - set_inv_page("mobs",player) - page = "mobs" - elseif fields.brew then - if players[name].page == "brew" then return end - set_inv_page("brew",player) - page = "brew" - elseif fields.matr then - if players[name].page == "matr" then return end - set_inv_page("matr",player) - page = "matr" - elseif fields.inv then - if players[name].page == "inv" then return end - page = "inv" - elseif fields.search == "" and not fields.creative_next and not fields.creative_prev then - set_inv_page("all", player) - page = "nix" - elseif fields.search and not fields.creative_next and not fields.creative_prev then - set_inv_search(string.lower(fields.search),player) - page = "nix" - end - - if page then - players[name].page = page - end - if players[name].page then - page = players[name].page - end - - -- Figure out current scroll bar from formspec - --local formspec = player:get_inventory_formspec() - - local start_i = players[name].start_i - - if fields.creative_prev then - start_i = start_i - 9*5 - elseif fields.creative_next then - start_i = start_i + 9*5 - else - -- Reset scroll bar if not scrolled - start_i = 0 - end - if start_i < 0 then - start_i = start_i + 9*5 - end - - local inv_size - if page == "nix" then - local inv = minetest.get_inventory({type="detached", name="creative_"..name}) - inv_size = inv:get_size("main") - elseif page and page ~= "inv" then - inv_size = #(inventory_lists[page]) - else - inv_size = 0 - end - - if start_i >= inv_size then - start_i = start_i - 9*5 - end - if start_i < 0 or start_i >= inv_size then - start_i = 0 - end - players[name].start_i = start_i - - local filter = "" - if not fields.nix and fields.search and fields.search ~= "" then - filter = fields.search - players[name].filter = filter - end - - mcl_inventory.set_creative_formspec(player, start_i, start_i / (9*5) + 1, inv_size, false, page, filter) -end) - - -if minetest.is_creative_enabled("") then - minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack) - -- Place infinite nodes, except for shulker boxes - local group = minetest.get_item_group(itemstack:get_name(), "shulker_box") - return group == 0 or group == nil - end) - - function minetest.handle_node_drops(pos, drops, digger) - if not digger or not digger:is_player() then - for _,item in ipairs(drops) do - minetest.add_item(pos, item) - end - end - local inv = digger:get_inventory() - if inv then - for _,item in ipairs(drops) do - if not inv:contains_item("main", item, true) then - inv:add_item("main", item) - end - end - end - end - - mcl_inventory.update_inventory_formspec = function(player) - local page - - local name = player:get_player_name() - - if players[name].page then - page = players[name].page - else - page = "nix" - end - - -- Figure out current scroll bar from formspec - --local formspec = player:get_inventory_formspec() - local start_i = players[name].start_i - - local inv_size - if page == "nix" then - local inv = minetest.get_inventory({type="detached", name="creative_"..name}) - inv_size = inv:get_size("main") - elseif page and page ~= "inv" then - inv_size = #(inventory_lists[page]) - else - inv_size = 0 - end - - local filter = players[name].filter - if filter == nil then - filter = "" - end - - mcl_inventory.set_creative_formspec(player, start_i, start_i / (9*5) + 1, inv_size, false, page, filter) - end -end - -minetest.register_on_joinplayer(function(player) - -- Initialize variables and inventory - local name = player:get_player_name() - if not players[name] then - players[name] = {} - players[name].page = "nix" - players[name].filter = "" - players[name].start_i = 0 - end - init(player) - mcl_inventory.set_creative_formspec(player, 0, 1, nil, false, "nix", "") -end) +local S = minetest.get_translator(minetest.get_current_modname()) +local F = minetest.formspec_escape + +-- Prepare player info table +local players = {} + +-- Containing all the items for each Creative Mode tab +local inventory_lists = {} + +--local mod_player = minetest.get_modpath("mcl_player") + +-- Create tables +local builtin_filter_ids = {"blocks","deco","redstone","rail","food","tools","combat","mobs","brew","matr","misc","all"} +for _, f in pairs(builtin_filter_ids) do + inventory_lists[f] = {} +end + +local function replace_enchanted_books(tbl) + for k, item in ipairs(tbl) do + if item:find("mcl_enchanting:book_enchanted") == 1 then + local _, enchantment, level = item:match("(%a+) ([_%w]+) (%d+)") + level = level and tonumber(level) + if enchantment and level then + tbl[k] = mcl_enchanting.enchant(ItemStack("mcl_enchanting:book_enchanted"), enchantment, level) + end + end + end +end + +--[[ Populate all the item tables. We only do this once. Note this code must be +executed after loading all the other mods in order to work. ]] +minetest.register_on_mods_loaded(function() + for name,def in pairs(minetest.registered_items) do + if (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0) and def.description and def.description ~= "" then + local function is_redstone(def) + return def.mesecons or def.groups.mesecon or def.groups.mesecon_conductor_craftable or def.groups.mesecon_effecor_off + end + local function is_tool(def) + return def.groups.tool or (def.tool_capabilities and def.tool_capabilities.damage_groups == nil) + end + local function is_weapon_or_armor(def) + return def.groups.weapon or def.groups.weapon_ranged or def.groups.ammo or def.groups.combat_item or ((def.groups.armor_head or def.groups.armor_torso or def.groups.armor_legs or def.groups.armor_feet or def.groups.horse_armor) and def.groups.non_combat_armor ~= 1) + end + -- Is set to true if it was added in any category besides misc + local nonmisc = false + if def.groups.building_block then + table.insert(inventory_lists["blocks"], name) + nonmisc = true + end + if def.groups.deco_block then + table.insert(inventory_lists["deco"], name) + nonmisc = true + end + if is_redstone(def) then + table.insert(inventory_lists["redstone"], name) + nonmisc = true + end + if def.groups.transport then + table.insert(inventory_lists["rail"], name) + nonmisc = true + end + if (def.groups.food and not def.groups.brewitem) or def.groups.eatable then + table.insert(inventory_lists["food"], name) + nonmisc = true + end + if is_tool(def) then + table.insert(inventory_lists["tools"], name) + nonmisc = true + end + if is_weapon_or_armor(def) then + table.insert(inventory_lists["combat"], name) + nonmisc = true + end + if def.groups.spawn_egg == 1 then + table.insert(inventory_lists["mobs"], name) + nonmisc = true + end + if def.groups.brewitem then + table.insert(inventory_lists["brew"], name) + nonmisc = true + end + if def.groups.craftitem then + table.insert(inventory_lists["matr"], name) + nonmisc = true + end + -- Misc. category is for everything which is not in any other category + if not nonmisc then + table.insert(inventory_lists["misc"], name) + end + + table.insert(inventory_lists["all"], name) + end + end + + for ench, def in pairs(mcl_enchanting.enchantments) do + local str = "mcl_enchanting:book_enchanted " .. ench .. " " .. def.max_level + if def.inv_tool_tab then + table.insert(inventory_lists["tools"], str) + end + if def.inv_combat_tab then + table.insert(inventory_lists["combat"], str) + end + table.insert(inventory_lists["all"], str) + end + + for _, to_sort in pairs(inventory_lists) do + table.sort(to_sort) + replace_enchanted_books(to_sort) + end +end) + +local function filter_item(name, description, lang, filter) + local desc + if not lang then + desc = string.lower(description) + else + desc = string.lower(minetest.get_translated_string(lang, description)) + end + return string.find(name, filter) or string.find(desc, filter) +end + +local function set_inv_search(filter, player) + local playername = player:get_player_name() + local inv = minetest.get_inventory({type="detached", name="creative_"..playername}) + local creative_list = {} + local lang = minetest.get_player_information(playername).lang_code + for name,def in pairs(minetest.registered_items) do + if (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0) and def.description and def.description ~= "" then + if filter_item(string.lower(def.name), def.description, lang, filter) then + table.insert(creative_list, name) + end + end + end + for ench, def in pairs(mcl_enchanting.enchantments) do + for i = 1, def.max_level do + local stack = mcl_enchanting.enchant(ItemStack("mcl_enchanting:book_enchanted"), ench, i) + if filter_item("mcl_enchanting:book_enchanted", minetest.strip_colors(stack:get_description()), lang, filter) then + table.insert(creative_list, "mcl_enchanting:book_enchanted " .. ench .. " " .. i) + end + end + end + table.sort(creative_list) + replace_enchanted_books(creative_list) + + inv:set_size("main", #creative_list) + inv:set_list("main", creative_list) +end + +local function set_inv_page(page, player) + local playername = player:get_player_name() + local inv = minetest.get_inventory({type="detached", name="creative_"..playername}) + inv:set_size("main", 0) + local creative_list = {} + if inventory_lists[page] then -- Standard filter + creative_list = inventory_lists[page] + end + inv:set_size("main", #creative_list) + inv:set_list("main", creative_list) +end + +local function init(player) + local playername = player:get_player_name() + minetest.create_detached_inventory("creative_"..playername, { + allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) + if minetest.is_creative_enabled(playername) then + return count + else + return 0 + end + end, + allow_put = function(inv, listname, index, stack, player) + return 0 + end, + allow_take = function(inv, listname, index, stack, player) + if minetest.is_creative_enabled(player:get_player_name()) then + return -1 + else + return 0 + end + end, + }, playername) + set_inv_page("all", player) +end + +-- Create the trash field +local trash = minetest.create_detached_inventory("trash", { + allow_put = function(inv, listname, index, stack, player) + if minetest.is_creative_enabled(player:get_player_name()) then + return stack:get_count() + else + return 0 + end + end, + on_put = function(inv, listname, index, stack, player) + inv:set_stack(listname, index, "") + end, +}) +trash:set_size("main", 1) + +local noffset = {} -- numeric tab offset +local offset = {} -- string offset: +local boffset = {} -- +local hoch = {} +local filtername = {} +--local bg = {} + +local noffset_x_start = -0.24 +local noffset_x = noffset_x_start +local noffset_y = -0.25 +local function next_noffset(id, right) + if right then + noffset[id] = { 8.94, noffset_y } + else + noffset[id] = { noffset_x, noffset_y } + noffset_x = noffset_x + 1.25 + end +end + +-- Upper row +next_noffset("blocks") +next_noffset("deco") +next_noffset("redstone") +next_noffset("rail") +next_noffset("brew") +next_noffset("misc") +next_noffset("nix", true) + +noffset_x = noffset_x_start +noffset_y = 8.12 + +-- Lower row +next_noffset("food") +next_noffset("tools") +next_noffset("combat") +next_noffset("mobs") +next_noffset("matr") +next_noffset("inv", true) + +for k,v in pairs(noffset) do + offset[k] = tostring(v[1]) .. "," .. tostring(v[2]) + boffset[k] = tostring(v[1]+0.19) .. "," .. tostring(v[2]+0.25) +end + +hoch["blocks"] = "" +hoch["deco"] = "" +hoch["redstone"] = "" +hoch["rail"] = "" +hoch["brew"] = "" +hoch["misc"] = "" +hoch["nix"] = "" +hoch["default"] = "" +hoch["food"] = "_down" +hoch["tools"] = "_down" +hoch["combat"] = "_down" +hoch["mobs"] = "_down" +hoch["matr"] = "_down" +hoch["inv"] = "_down" + +filtername["blocks"] = S("Building Blocks") +filtername["deco"] = S("Decoration Blocks") +filtername["redstone"] = S("Redstone") +filtername["rail"] = S("Transportation") +filtername["misc"] = S("Miscellaneous") +filtername["nix"] = S("Search Items") +filtername["food"] = S("Foodstuffs") +filtername["tools"] = S("Tools") +filtername["combat"] = S("Combat") +filtername["mobs"] = S("Mobs") +filtername["brew"] = S("Brewing") +filtername["matr"] = S("Materials") +filtername["inv"] = S("Survival Inventory") + +--local dark_bg = "crafting_creative_bg_dark.png" + +--[[local function reset_menu_item_bg() + bg["blocks"] = dark_bg + bg["deco"] = dark_bg + bg["redstone"] = dark_bg + bg["rail"] = dark_bg + bg["misc"] = dark_bg + bg["nix"] = dark_bg + bg["food"] = dark_bg + bg["tools"] = dark_bg + bg["combat"] = dark_bg + bg["mobs"] = dark_bg + bg["brew"] = dark_bg + bg["matr"] = dark_bg + bg["inv"] = dark_bg + bg["default"] = dark_bg +end]] + + +function mcl_inventory.set_creative_formspec(player, start_i, pagenum, inv_size, show, page, filter) + --reset_menu_item_bg() + pagenum = math.floor(pagenum) or 1 + + local playername = player:get_player_name() + + if not inv_size then + if page == "nix" then + local inv = minetest.get_inventory({type="detached", name="creative_"..playername}) + inv_size = inv:get_size("main") + elseif page and page ~= "inv" then + inv_size = #(inventory_lists[page]) + else + inv_size = 0 + end + end + local pagemax = math.max(1, math.floor((inv_size-1) / (9*5) + 1)) + local name = "nix" + local main_list + local listrings = "listring[detached:creative_"..playername..";main]".. + "listring[current_player;main]".. + "listring[detached:trash;main]" + + if page then + name = page + if players[playername] then + players[playername].page = page + end + end + --bg[name] = "crafting_creative_bg.png" + + local inv_bg = "crafting_inventory_creative.png" + if name == "inv" then + inv_bg = "crafting_inventory_creative_survival.png" + + -- Show armor and player image + local player_preview + if minetest.settings:get_bool("3d_player_preview", true) then + player_preview = mcl_player.get_player_formspec_model(player, 3.9, 1.4, 1.2333, 2.4666, "") + else + player_preview = "image[3.9,1.4;1.2333,2.4666;"..mcl_player.player_get_preview(player).."]" + end + + -- Background images for armor slots (hide if occupied) + local armor_slot_imgs = "" + local inv = player:get_inventory() + if inv:get_stack("armor", 2):is_empty() then + armor_slot_imgs = armor_slot_imgs .. "image[2.5,1.3;1,1;mcl_inventory_empty_armor_slot_helmet.png]" + end + if inv:get_stack("armor", 3):is_empty() then + armor_slot_imgs = armor_slot_imgs .. "image[2.5,2.75;1,1;mcl_inventory_empty_armor_slot_chestplate.png]" + end + if inv:get_stack("armor", 4):is_empty() then + armor_slot_imgs = armor_slot_imgs .. "image[5.5,1.3;1,1;mcl_inventory_empty_armor_slot_leggings.png]" + end + if inv:get_stack("armor", 5):is_empty() then + armor_slot_imgs = armor_slot_imgs .. "image[5.5,2.75;1,1;mcl_inventory_empty_armor_slot_boots.png]" + end + + -- Survival inventory slots + main_list = "list[current_player;main;0,3.75;9,3;9]".. + mcl_formspec.get_itemslot_bg(0,3.75,9,3).. + -- armor + "list[current_player;armor;2.5,1.3;1,1;1]".. + "list[current_player;armor;2.5,2.75;1,1;2]".. + "list[current_player;armor;5.5,1.3;1,1;3]".. + "list[current_player;armor;5.5,2.75;1,1;4]".. + mcl_formspec.get_itemslot_bg(2.5,1.3,1,1).. + mcl_formspec.get_itemslot_bg(2.5,2.75,1,1).. + mcl_formspec.get_itemslot_bg(5.5,1.3,1,1).. + mcl_formspec.get_itemslot_bg(5.5,2.75,1,1).. + armor_slot_imgs.. + -- player preview + player_preview.. + -- crafting guide button + "image_button[9,1;1,1;craftguide_book.png;__mcl_craftguide;]".. + "tooltip[__mcl_craftguide;"..F(S("Recipe book")).."]".. + -- help button + "image_button[9,2;1,1;doc_button_icon_lores.png;__mcl_doc;]".. + "tooltip[__mcl_doc;"..F(S("Help")).."]".. + -- skins button + "image_button[9,3;1,1;mcl_skins_button.png;__mcl_skins;]".. + "tooltip[__mcl_skins;"..F(S("Select player skin")).."]".. + -- achievements button + "image_button[9,4;1,1;mcl_achievements_button.png;__mcl_achievements;]".. + --"style_type[image_button;border=;bgimg=;bgimg_pressed=]".. + "tooltip[__mcl_achievements;"..F(S("Achievements")).."]" + + -- For shortcuts + listrings = listrings .. + "listring[detached:"..playername.."_armor;armor]".. + "listring[current_player;main]" + else + -- Creative inventory slots + main_list = "list[detached:creative_"..playername..";main;0,1.75;9,5;"..tostring(start_i).."]".. + mcl_formspec.get_itemslot_bg(0,1.75,9,5).. + -- Page buttons + "label[9.0,5.5;"..F(S("@1/@2", pagenum, pagemax)).."]".. + "image_button[9.0,6.0;0.7,0.7;crafting_creative_prev.png;creative_prev;]".. + "image_button[9.5,6.0;0.7,0.7;crafting_creative_next.png;creative_next;]" + end + + local tab_icon = { + blocks = "mcl_core:brick_block", + deco = "mcl_flowers:peony", + redstone = "mesecons:redstone", + rail = "mcl_minecarts:golden_rail", + misc = "mcl_buckets:bucket_lava", + nix = "mcl_compass:compass", + food = "mcl_core:apple", + tools = "mcl_core:axe_iron", + combat = "mcl_core:sword_gold", + mobs = "mobs_mc:cow", + brew = "mcl_potions:dragon_breath", + matr = "mcl_core:stick", + inv = "mcl_chests:chest", + } + local function tab(current_tab, this_tab) + local bg_img + if current_tab == this_tab then + bg_img = "crafting_creative_active"..hoch[this_tab]..".png" + else + bg_img = "crafting_creative_inactive"..hoch[this_tab]..".png" + end + return + "style["..this_tab..";border=false;bgimg=;bgimg_pressed=]".. + "item_image_button[" .. boffset[this_tab] ..";1,1;"..tab_icon[this_tab]..";"..this_tab..";]".. + "image[" .. offset[this_tab] .. ";1.5,1.44;" .. bg_img .. "]" + end + local caption = "" + if name ~= "inv" and filtername[name] then + caption = "label[0,1.2;"..F(minetest.colorize("#313131", filtername[name])).."]" + end + + local formspec = "size[10,9.3]".. + "no_prepend[]".. + mcl_vars.gui_nonbg..mcl_vars.gui_bg_color.. + "background[-0.19,-0.25;10.5,9.87;"..inv_bg.."]".. + "label[-5,-5;"..name.."]".. + tab(name, "blocks") .. + "tooltip[blocks;"..F(filtername["blocks"]).."]".. + tab(name, "deco") .. + "tooltip[deco;"..F(filtername["deco"]).."]".. + tab(name, "redstone") .. + "tooltip[redstone;"..F(filtername["redstone"]).."]".. + tab(name, "rail") .. + "tooltip[rail;"..F(filtername["rail"]).."]".. + tab(name, "misc") .. + "tooltip[misc;"..F(filtername["misc"]).."]".. + tab(name, "nix") .. + "tooltip[nix;"..F(filtername["nix"]).."]".. + caption.. + "list[current_player;main;0,7;9,1;]".. + mcl_formspec.get_itemslot_bg(0,7,9,1).. + main_list.. + tab(name, "food") .. + "tooltip[food;"..F(filtername["food"]).."]".. + tab(name, "tools") .. + "tooltip[tools;"..F(filtername["tools"]).."]".. + tab(name, "combat") .. + "tooltip[combat;"..F(filtername["combat"]).."]".. + tab(name, "mobs") .. + "tooltip[mobs;"..F(filtername["mobs"]).."]".. + tab(name, "brew") .. + "tooltip[brew;"..F(filtername["brew"]).."]".. + tab(name, "matr") .. + "tooltip[matr;"..F(filtername["matr"]).."]".. + tab(name, "inv") .. + "tooltip[inv;"..F(filtername["inv"]).."]".. + "list[detached:trash;main;9,7;1,1;]".. + mcl_formspec.get_itemslot_bg(9,7,1,1).. + "image[9,7;1,1;crafting_creative_trash.png]".. + listrings + + if name == "nix" then + if filter == nil then + filter = "" + end + formspec = formspec .. "field[5.3,1.34;4,0.75;search;;"..minetest.formspec_escape(filter).."]" + formspec = formspec .. "field_close_on_enter[search;false]" + end + if pagenum then formspec = formspec .. "p"..tostring(pagenum) end + player:set_inventory_formspec(formspec) +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + local page = nil + + if not minetest.is_creative_enabled(player:get_player_name()) then + return + end + if formname ~= "" or fields.quit == "true" then + -- No-op if formspec closed or not player inventory (formname == "") + return + end + + local name = player:get_player_name() + + if fields.blocks then + if players[name].page == "blocks" then return end + set_inv_page("blocks",player) + page = "blocks" + elseif fields.deco then + if players[name].page == "deco" then return end + set_inv_page("deco",player) + page = "deco" + elseif fields.redstone then + if players[name].page == "redstone" then return end + set_inv_page("redstone",player) + page = "redstone" + elseif fields.rail then + if players[name].page == "rail" then return end + set_inv_page("rail",player) + page = "rail" + elseif fields.misc then + if players[name].page == "misc" then return end + set_inv_page("misc",player) + page = "misc" + elseif fields.nix then + set_inv_page("all",player) + page = "nix" + elseif fields.food then + if players[name].page == "food" then return end + set_inv_page("food",player) + page = "food" + elseif fields.tools then + if players[name].page == "tools" then return end + set_inv_page("tools",player) + page = "tools" + elseif fields.combat then + if players[name].page == "combat" then return end + set_inv_page("combat",player) + page = "combat" + elseif fields.mobs then + if players[name].page == "mobs" then return end + set_inv_page("mobs",player) + page = "mobs" + elseif fields.brew then + if players[name].page == "brew" then return end + set_inv_page("brew",player) + page = "brew" + elseif fields.matr then + if players[name].page == "matr" then return end + set_inv_page("matr",player) + page = "matr" + elseif fields.inv then + if players[name].page == "inv" then return end + page = "inv" + elseif fields.search == "" and not fields.creative_next and not fields.creative_prev then + set_inv_page("all", player) + page = "nix" + elseif fields.search and not fields.creative_next and not fields.creative_prev then + set_inv_search(string.lower(fields.search),player) + page = "nix" + end + + if page then + players[name].page = page + end + if players[name].page then + page = players[name].page + end + + -- Figure out current scroll bar from formspec + --local formspec = player:get_inventory_formspec() + + local start_i = players[name].start_i + + if fields.creative_prev then + start_i = start_i - 9*5 + elseif fields.creative_next then + start_i = start_i + 9*5 + else + -- Reset scroll bar if not scrolled + start_i = 0 + end + if start_i < 0 then + start_i = start_i + 9*5 + end + + local inv_size + if page == "nix" then + local inv = minetest.get_inventory({type="detached", name="creative_"..name}) + inv_size = inv:get_size("main") + elseif page and page ~= "inv" then + inv_size = #(inventory_lists[page]) + else + inv_size = 0 + end + + if start_i >= inv_size then + start_i = start_i - 9*5 + end + if start_i < 0 or start_i >= inv_size then + start_i = 0 + end + players[name].start_i = start_i + + local filter = "" + if not fields.nix and fields.search and fields.search ~= "" then + filter = fields.search + players[name].filter = filter + end + + mcl_inventory.set_creative_formspec(player, start_i, start_i / (9*5) + 1, inv_size, false, page, filter) +end) + + +if minetest.is_creative_enabled("") then + minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack) + -- Place infinite nodes, except for shulker boxes + local group = minetest.get_item_group(itemstack:get_name(), "shulker_box") + return group == 0 or group == nil + end) + + function minetest.handle_node_drops(pos, drops, digger) + if not digger or not digger:is_player() then + for _,item in ipairs(drops) do + minetest.add_item(pos, item) + end + end + local inv = digger:get_inventory() + if inv then + for _,item in ipairs(drops) do + if not inv:contains_item("main", item, true) then + inv:add_item("main", item) + end + end + end + end + + mcl_inventory.update_inventory_formspec = function(player) + local page + + local name = player:get_player_name() + + if players[name].page then + page = players[name].page + else + page = "nix" + end + + -- Figure out current scroll bar from formspec + --local formspec = player:get_inventory_formspec() + local start_i = players[name].start_i + + local inv_size + if page == "nix" then + local inv = minetest.get_inventory({type="detached", name="creative_"..name}) + inv_size = inv:get_size("main") + elseif page and page ~= "inv" then + inv_size = #(inventory_lists[page]) + else + inv_size = 0 + end + + local filter = players[name].filter + if filter == nil then + filter = "" + end + + mcl_inventory.set_creative_formspec(player, start_i, start_i / (9*5) + 1, inv_size, false, page, filter) + end +end + +minetest.register_on_joinplayer(function(player) + -- Initialize variables and inventory + local name = player:get_player_name() + if not players[name] then + players[name] = {} + players[name].page = "nix" + players[name].filter = "" + players[name].start_i = 0 + end + init(player) + mcl_inventory.set_creative_formspec(player, 0, 1, nil, false, "nix", "") +end) From 2607d40f1fcb4680f324aea4ad733fbe48a0fbfa Mon Sep 17 00:00:00 2001 From: Nils Dagsson Moskopp Date: Sat, 17 Jul 2021 07:23:20 +0200 Subject: [PATCH 14/14] Add script to show packets count from debug logs Mineclonia has inherited mods from MineClone 2 that send a lot of network packets. This behaviour wastes bandwith and is most likely a major reason for the unusually high amount of lag that MineClone2 and Mineclonia have. Many network packets that are sent by Mineclonia are entirely useless. Analyzing minetest log files to figure out what kind of packets are sent and how often is a first step in getting rid of useless traffic. --- tools/analyze-packet-spam | 60 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100755 tools/analyze-packet-spam diff --git a/tools/analyze-packet-spam b/tools/analyze-packet-spam new file mode 100755 index 0000000000..310616fd9a --- /dev/null +++ b/tools/analyze-packet-spam @@ -0,0 +1,60 @@ +#!/bin/sh -eu +# analyze-packet-spam – show minetest client packet count per second +# Copyright © 2021 Nils Dagsson Moskopp (erlehmann) + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. + +# Dieses Programm hat das Ziel, die Medienkompetenz der Leser zu +# steigern. Gelegentlich packe ich sogar einen handfesten Buffer +# Overflow oder eine Format String Vulnerability zwischen die anderen +# Codezeilen und schreibe das auch nicht dran. + +# This script takes a minetest log with at least INFO log level and +# outputs the MINETEST network protocol packet count per second. + +# To collect such a log file of minetest running for 10 minutes, run: +# timeout 600 minetest --info >log.txt 2>&1 >/dev/null + +# To get packet counts from that file, run: +# ./analyze-packet-spam "${TEMPFILE}" + +TIMESTAMP_START=$( <"${TEMPFILE}" head -n1 |cut -d' ' -f1 ) +TIMESTAMP_END=$( <"${TEMPFILE}" tail -n1 |cut -d' ' -f1 ) +DURATION=$(( 30 + ${TIMESTAMP_END} - ${TIMESTAMP_START} )) + +PACKET_NAME_SEEN='' +<"${TEMPFILE}" tac \ + |while read _ PACKET_NAME PACKET_COUNT; do + case "${PACKET_NAME_SEEN}" in + *"${PACKET_NAME}"*) + ;; + *) + PACKET_COUNT_PER_SECOND=$( + printf '1k %s %s /p' "${PACKET_COUNT}" "${DURATION}" \ + |dc + ) + printf '%s\t%s\n' "${PACKET_COUNT_PER_SECOND}" "${PACKET_NAME}" + PACKET_NAME_SEEN="${PACKET_NAME_SEEN} ${PACKET_NAME}" + ;; + esac + done + +unlink "${TEMPFILE}"