-- Standard effect monoids, to provide canonicity. local function mult(x, y) return x * y end local function mult_fold(elems) local tot = 1 for _, v in pairs(elems) do tot = tot * v end return tot end local function v_mult(v1, v2) local res = {} for k, v in pairs(v1) do res[k] = v * v2[k] end return res end local function v_mult_fold(identity) return function(elems) local tot = identity for _, v in pairs(elems) do tot = v_mult(tot, v) end return tot end end local monoid = player_monoids.make_monoid -- Speed monoid. Effect values are speed multipliers. Must be nonnegative -- numbers. player_monoids.speed = monoid({ combine = mult, fold = mult_fold, identity = 1, apply = function(multiplier, player) local ov = player:get_physics_override() ov.speed = multiplier player:set_physics_override(ov) end, }) -- Jump monoid. Effect values are jump multipliers. Must be nonnegative -- numbers. player_monoids.jump = monoid({ combine = mult, fold = mult_fold, identity = 1, apply = function(multiplier, player) local ov = player:get_physics_override() ov.jump = multiplier player:set_physics_override(ov) end, }) -- Gravity monoid. Effect values are gravity multipliers. player_monoids.gravity = monoid({ combine = mult, fold = mult_fold, identity = 1, apply = function(multiplier, player) local ov = player:get_physics_override() ov.gravity = multiplier player:set_physics_override(ov) end, }) -- Fly ability monoid. The values are booleans, which are combined by or. A true -- value indicates having the ability to fly. player_monoids.fly = monoid({ combine = function(p, q) return p or q end, fold = function(elems) for _, v in pairs(elems) do if v then return true end end return false end, identity = false, apply = function(can_fly, player) local p_name = player:get_player_name() local privs = minetest.get_player_privs(p_name) if can_fly then privs.fly = true else privs.fly = nil end minetest.set_player_privs(p_name, privs) end, }) -- Noclip ability monoid. Works the same as fly monoid. player_monoids.noclip = monoid({ combine = function(p, q) return p or q end, fold = function(elems) for _, v in pairs(elems) do if v then return true end end return false end, identity = false, apply = function(can_noclip, player) local p_name = player:get_player_name() local privs = minetest.get_player_privs(p_name) if can_noclip then privs.noclip = true else privs.noclip = nil end minetest.set_player_privs(p_name, privs) end, }) local def_col_scale = { x=0.3, y=1, z=0.3 } -- Collisionbox scaling factor. Values are a vector of x, y, z multipliers. player_monoids.collisionbox = monoid({ combine = v_mult, fold = v_mult_fold({x=1, y=1, z=1}), identity = {x=1, y=1, z=1}, apply = function(multiplier, player) local v = vector.multiply(def_col_scale, multiplier) player:set_properties({ collisionbox = { -v.x, -v.y, -v.z, v.z, v.y, v.z } }) end, }) player_monoids.visual_size = monoid({ combine = v_mult, fold = v_mult_fold({x=1, y=1}), identity = {x=1, y=1}, apply = function(multiplier, player) player:set_properties({ visual_size = multiplier }) end, })