diff --git a/mods/CORE/mcl_mapgen/init.lua b/mods/CORE/mcl_mapgen/init.lua index 4aca65f54..fc0a98c6b 100644 --- a/mods/CORE/mcl_mapgen/init.lua +++ b/mods/CORE/mcl_mapgen/init.lua @@ -325,7 +325,7 @@ minetest.register_on_generated(function(minp, maxp, chunkseed) -- mcl_mapgen.register_mapgen_lvm(function(vm_context), order_number) -- -- -- for _, v in pairs(queue_chunks_lvm) do - vm_context = v.f(vm_context) + v.f(vm_context) end -- -- -- mcl_mapgen.register_mapgen(function(minp, maxp, chunkseed, vm_context), order_number) -- diff --git a/mods/CORE/mcl_worlds/init.lua b/mods/CORE/mcl_worlds/init.lua index eb366013e..d31913599 100644 --- a/mods/CORE/mcl_worlds/init.lua +++ b/mods/CORE/mcl_worlds/init.lua @@ -152,3 +152,23 @@ minetest.register_globalstep(function(dtime) dimtimer = 0 end end) + +function mcl_worlds.get_cloud_parameters() + if mcl_mapgen.name == "valleys" then + return { + height = 384, + speed = {x=-2, z=0}, + thickness=5, + color="#FFF0FEF", + ambient = "#201060", + } + else + -- MC-style clouds: Layer 127, thickness 4, fly to the “West” + return { + height = mcl_worlds.layer_to_y(127), + speed = {x=-2, z=0}, + thickness = 4, + color = "#FFF0FEF", + } + end +end diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index 564c59d0f..4447c1587 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -402,6 +402,7 @@ function mobs:register_mob(name, def) ignited_by_sunlight = def.ignited_by_sunlight or false, eye_height = def.eye_height or 1.5, defuse_reach = def.defuse_reach or 4, + spawn = def.spawn, -- End of MCL2 extensions on_spawn = def.on_spawn, diff --git a/mods/ENTITIES/mcl_mobs/api/spawning.lua b/mods/ENTITIES/mcl_mobs/api/spawning.lua index 424989426..7fb6983f4 100644 --- a/mods/ENTITIES/mcl_mobs/api/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/api/spawning.lua @@ -267,6 +267,8 @@ function mobs:spawn_setup(def) local day_toggle = def.day_toggle local on_spawn = def.on_spawn local check_position = def.check_position + local group_size_min = def.group_size_min or 1 + local group_size_max = def.group_size_max or 1 -- chance/spawn number override in minetest.conf for registered mob local numbers = minetest.settings:get(name) @@ -300,10 +302,23 @@ function mobs:spawn_setup(def) day_toggle = day_toggle, check_position = check_position, on_spawn = on_spawn, + group_size_min = group_size_min, + group_size_max = group_size_max, } summary_chance = summary_chance + chance end +function mobs.spawn_mob(name, pos) + local def = minetest.registered_entities[name] + if not def then return end + if def.spawn then + return def.spawn(pos) + end + return minetest.add_entity(pos, name) +end + +local spawn_mob = mobs.spawn_mob + function mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_light, max_light, interval, chance, aoc, min_height, max_height, day_toggle, on_spawn) -- Do mobs spawn at all? @@ -341,6 +356,8 @@ function mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_ligh spawn_dictionary[key]["min_height"] = min_height spawn_dictionary[key]["max_height"] = max_height spawn_dictionary[key]["day_toggle"] = day_toggle + spawn_dictionary[key]["group_size_min"] = 1 + spawn_dictionary[key]["group_size_max"] = 3 summary_chance = summary_chance + chance end @@ -442,9 +459,9 @@ if mobs_spawn then and (mob_def.check_position and mob_def.check_position(spawning_position) or true) then --everything is correct, spawn mob - local object = minetest.add_entity(spawning_position, mob_def.name) + local object = spawn_mob(mob_def.name, spawning_position) if object then - return mob_def.on_spawn and mob_def.on_spawn(object, pos) + return mob_def.on_spawn and mob_def.on_spawn(object, spawning_position) end end current_summary_chance = current_summary_chance - mob_chance diff --git a/mods/ENTITIES/mobs_mc/rabbit.lua b/mods/ENTITIES/mobs_mc/rabbit.lua index 51235a3f9..e63c0d594 100644 --- a/mods/ENTITIES/mobs_mc/rabbit.lua +++ b/mods/ENTITIES/mobs_mc/rabbit.lua @@ -2,118 +2,27 @@ local S = minetest.get_translator(minetest.get_current_modname()) -local rabbit = { - description = S("Rabbit"), - type = "animal", - spawn_class = "passive", - passive = true, - reach = 1, - rotate = 270, - hp_min = 3, - hp_max = 3, - xp_min = 1, - xp_max = 3, - collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.49, 0.2}, +local mob_name = "mobs_mc:rabbit" - visual = "mesh", - mesh = "mobs_mc_rabbit.b3d", - textures = { +local textures = { {"mobs_mc_rabbit_brown.png"}, {"mobs_mc_rabbit_gold.png"}, {"mobs_mc_rabbit_white.png"}, {"mobs_mc_rabbit_white_splotched.png"}, {"mobs_mc_rabbit_salt.png"}, {"mobs_mc_rabbit_black.png"}, - }, - visual_size = {x=1.5, y=1.5}, - sounds = { - random = "mobs_mc_rabbit_random", - damage = "mobs_mc_rabbit_hurt", - death = "mobs_mc_rabbit_death", - attack = "mobs_mc_rabbit_attack", - eat = "mobs_mc_animal_eat_generic", - distance = 16, - }, - makes_footstep_sound = false, - walk_velocity = 1, - run_velocity = 3.7, - follow_velocity = 1.1, - floats = 1, - runaway = true, - jump = true, - drops = { - {name = mobs_mc.items.rabbit_raw, chance = 1, min = 0, max = 1, looting = "common",}, - {name = mobs_mc.items.rabbit_hide, chance = 1, min = 0, max = 1, looting = "common",}, - {name = mobs_mc.items.rabbit_foot, chance = 10, min = 0, max = 1, looting = "rare", looting_factor = 0.03,}, - }, - fear_height = 4, - animation = { - speed_normal = 25, speed_run = 50, - stand_start = 0, stand_end = 0, - walk_start = 0, walk_end = 20, - run_start = 0, run_end = 20, - }, - -- Follow (yellow) dangelions, carrots and golden carrots - follow = mobs_mc.follow.rabbit, - view_range = 8, - -- Eat carrots and reduce their growth stage by 1 - replace_rate = 10, - replace_what = mobs_mc.replace.rabbit, - on_rightclick = function(self, clicker) - -- Feed, tame protect or capture - if mobs:feed_tame(self, clicker, 1, true, true) then return end - end, - do_custom = function(self) - -- Easter egg: Change texture if rabbit is named “Toast” - if self.nametag == "Toast" and not self._has_toast_texture then - self._original_rabbit_texture = self.base_texture - self.base_texture = { "mobs_mc_rabbit_toast.png" } - self.object:set_properties({ textures = self.base_texture }) - self._has_toast_texture = true - elseif self.nametag ~= "Toast" and self._has_toast_texture then - self.base_texture = self._original_rabbit_texture - self.object:set_properties({ textures = self.base_texture }) - self._has_toast_texture = false - end - end, } -mobs:register_mob("mobs_mc:rabbit", rabbit) +local sounds = { + random = "mobs_mc_rabbit_random", + damage = "mobs_mc_rabbit_hurt", + death = "mobs_mc_rabbit_death", + attack = "mobs_mc_rabbit_attack", + eat = "mobs_mc_animal_eat_generic", + distance = 16, +} --- The killer bunny (Only with spawn egg) -local killer_bunny = table.copy(rabbit) -killer_bunny.description = S("Killer Bunny") -killer_bunny.type = "monster" -killer_bunny.spawn_class = "hostile" -killer_bunny.attack_type = "dogfight" -killer_bunny.specific_attack = { "player", "mobs_mc:wolf", "mobs_mc:dog" } -killer_bunny.damage = 8 -killer_bunny.passive = false --- 8 armor points -killer_bunny.armor = 50 -killer_bunny.textures = { "mobs_mc_rabbit_caerbannog.png" } -killer_bunny.view_range = 16 -killer_bunny.replace_rate = nil -killer_bunny.replace_what = nil -killer_bunny.on_rightclick = nil -killer_bunny.run_velocity = 6 -killer_bunny.do_custom = function(self) - if not self._killer_bunny_nametag_set then - self.nametag = S("The Killer Bunny") - self._killer_bunny_nametag_set = true - end -end - -mobs:register_mob("mobs_mc:killer_bunny", killer_bunny) - --- Mob spawning rules. --- Different skins depending on spawn location <- we'll get to this when the spawning algorithm is fleshed out - -mobs:spawn_specific( -"mobs_mc:rabbit", -"overworld", -"ground", -{ +local biome_list = { "FlowerForest_beach", "Forest_beach", "StoneBeach", @@ -161,73 +70,149 @@ mobs:spawn_specific( "MesaBryce", "JungleEdge", "SavannaM", -}, -9, -minetest.LIGHT_MAX+1, -30, -15000, -8, -mobs_mc.spawn_height.overworld_min, -mobs_mc.spawn_height.overworld_max) - ---[[ -local spawn = { - name = "mobs_mc:rabbit", - neighbors = {"air"}, - chance = 15000, - active_object_count = 10, - min_light = 0, - max_light = minetest.LIGHT_MAX+1, - min_height = mobs_mc.spawn_height.overworld_min, - max_height = mobs_mc.spawn_height.overworld_max, } -local spawn_desert = table.copy(spawn) -spawn_desert.nodes = mobs_mc.spawn.desert -spawn_desert.on_spawn = function(self, pos) - local texture = "mobs_mc_rabbit_gold.png" - self.base_texture = { "mobs_mc_rabbit_gold.png" } - self.object:set_properties({textures = self.base_texture}) -end -mobs:spawn(spawn_desert) - -local spawn_snow = table.copy(spawn) -spawn_snow.nodes = mobs_mc.spawn.snow -spawn_snow.on_spawn = function(self, pos) +local function spawn_rabbit(pos) + local biome_data = minetest.get_biome_data(pos) + local biome_name = biome_data and minetest.get_biome_name(biome_data.biome) or "" + local mob = minetest.add_entity(pos, mob_name) + if not mob then return end + local self = mob:get_luaentity() local texture - local r = math.random(1, 100) - -- 80% white fur - if r <= 80 then - texture = "mobs_mc_rabbit_white.png" - -- 20% black and white fur + if biome_name:find("Desert") then + texture = "mobs_mc_rabbit_gold.png" else - texture = "mobs_mc_rabbit_white_splotched.png" + local r = math.random(1, 100) + if biome_name:find("Ice") or biome_name:find("snow") or biome_name:find("Cold") then + -- 80% white fur + if r <= 80 then + texture = "mobs_mc_rabbit_white.png" + -- 20% black and white fur + else + texture = "mobs_mc_rabbit_white_splotched.png" + end + else + -- 50% brown fur + if r <= 50 then + texture = "mobs_mc_rabbit_brown.png" + -- 40% salt fur + elseif r <= 90 then + texture = "mobs_mc_rabbit_salt.png" + -- 10% black fur + else + texture = "mobs_mc_rabbit_black.png" + end + end end - self.base_texture = { texture } - self.object:set_properties({textures = self.base_texture}) + self.base_texture = {texture} + self.object:set_properties({textures = {texture}}) end -mobs:spawn(spawn_snow) -local spawn_grass = table.copy(spawn) -spawn_grass.nodes = mobs_mc.spawn.grassland -spawn_grass.on_spawn = function(self, pos) - local texture - local r = math.random(1, 100) - -- 50% brown fur - if r <= 50 then - texture = "mobs_mc_rabbit_brown.png" - -- 40% salt fur - elseif r <= 90 then - texture = "mobs_mc_rabbit_salt.png" - -- 10% black fur - else - texture = "mobs_mc_rabbit_black.png" +local function do_custom_rabbit(self) + -- Easter egg: Change texture if rabbit is named “Toast” + if self.nametag == "Toast" and not self._has_toast_texture then + self._original_rabbit_texture = self.base_texture + self.base_texture = { "mobs_mc_rabbit_toast.png" } + self.object:set_properties({ textures = self.base_texture }) + self._has_toast_texture = true + elseif self.nametag ~= "Toast" and self._has_toast_texture then + self.base_texture = self._original_rabbit_texture + self.object:set_properties({ textures = self.base_texture }) + self._has_toast_texture = false end - self.base_texture = { texture } - self.object:set_properties({textures = self.base_texture}) end -mobs:spawn(spawn_grass) -]]-- + +local rabbit = { + description = S("Rabbit"), + type = "animal", + spawn_class = "passive", + passive = true, + reach = 1, + rotate = 270, + hp_min = 3, + hp_max = 3, + xp_min = 1, + xp_max = 3, + collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.49, 0.2}, + visual = "mesh", + mesh = "mobs_mc_rabbit.b3d", + textures = textures, + visual_size = {x=1.5, y=1.5}, + sounds = sounds, + makes_footstep_sound = false, + walk_velocity = 1, + run_velocity = 3.7, + follow_velocity = 1.1, + floats = 1, + runaway = true, + jump = true, + drops = { + {name = mobs_mc.items.rabbit_raw, chance = 1, min = 0, max = 1, looting = "common",}, + {name = mobs_mc.items.rabbit_hide, chance = 1, min = 0, max = 1, looting = "common",}, + {name = mobs_mc.items.rabbit_foot, chance = 10, min = 0, max = 1, looting = "rare", looting_factor = 0.03,}, + }, + fear_height = 4, + animation = { + speed_normal = 25, speed_run = 50, + stand_start = 0, stand_end = 0, + walk_start = 0, walk_end = 20, + run_start = 0, run_end = 20, + }, + -- Follow (yellow) dangelions, carrots and golden carrots + follow = mobs_mc.follow.rabbit, + view_range = 8, + -- Eat carrots and reduce their growth stage by 1 + replace_rate = 10, + replace_what = mobs_mc.replace.rabbit, + on_rightclick = function(self, clicker) + -- Feed, tame protect or capture + if mobs:feed_tame(self, clicker, 1, true, true) then return end + end, + do_custom = do_custom_rabbit, + spawn = spawn_rabbit +} + +mobs:register_mob(mob_name, rabbit) + +-- The killer bunny (Only with spawn egg) +local killer_bunny = table.copy(rabbit) +killer_bunny.description = S("Killer Bunny") +killer_bunny.type = "monster" +killer_bunny.spawn_class = "hostile" +killer_bunny.attack_type = "dogfight" +killer_bunny.specific_attack = { "player", "mobs_mc:wolf", "mobs_mc:dog" } +killer_bunny.damage = 8 +killer_bunny.passive = false +-- 8 armor points +killer_bunny.armor = 50 +killer_bunny.textures = { "mobs_mc_rabbit_caerbannog.png" } +killer_bunny.view_range = 16 +killer_bunny.replace_rate = nil +killer_bunny.replace_what = nil +killer_bunny.on_rightclick = nil +killer_bunny.run_velocity = 6 +killer_bunny.do_custom = function(self) + if not self._killer_bunny_nametag_set then + self.nametag = S("The Killer Bunny") + self._killer_bunny_nametag_set = true + end +end + +mobs:register_mob("mobs_mc:killer_bunny", killer_bunny) + +-- Mob spawning rules. +-- Different skins depending on spawn location <- we customized spawn function + +mobs:spawn_setup({ + name = mob_name, + min_light = 9, + chance = 1000, + aoc = 8, + biomes = biome_list, + group_size_max = 1, + baby_min = 1, + baby_max = 2, +}) -- Spawn egg mobs:register_egg("mobs_mc:rabbit", S("Rabbit"), "mobs_mc_spawn_icon_rabbit.png", 0) diff --git a/mods/ENVIRONMENT/mcl_weather/skycolor.lua b/mods/ENVIRONMENT/mcl_weather/skycolor.lua index 6b89c33be..93e92defc 100644 --- a/mods/ENVIRONMENT/mcl_weather/skycolor.lua +++ b/mods/ENVIRONMENT/mcl_weather/skycolor.lua @@ -241,7 +241,7 @@ local function initsky(player) end -- MC-style clouds: Layer 127, thickness 4, fly to the “West” - player:set_clouds({height=mcl_worlds.layer_to_y(127), speed={x=-2, z=0}, thickness=4, color="#FFF0FEF"}) + player:set_clouds(mcl_worlds:get_cloud_parameters() or {height=mcl_worlds.layer_to_y(127), speed={x=-2, z=0}, thickness=4, color="#FFF0FEF"}) end minetest.register_on_joinplayer(initsky) diff --git a/mods/HUD/mcl_info/init.lua b/mods/HUD/mcl_info/init.lua index 02af53fbc..9cf95b43a 100644 --- a/mods/HUD/mcl_info/init.lua +++ b/mods/HUD/mcl_info/init.lua @@ -89,7 +89,7 @@ minetest.register_chatcommand("debug",{ minetest.chat_send_player(name, S("Error! Possible values are integer numbers from @1 to @2", 0, 3)) return end - if dbg == default_dbg then + if dbg == default_debug then player_dbg[name] = nil else player_dbg[name] = dbg diff --git a/mods/ITEMS/mcl_cauldrons/init.lua b/mods/ITEMS/mcl_cauldrons/init.lua index 55866f5cc..4b6fcd318 100644 --- a/mods/ITEMS/mcl_cauldrons/init.lua +++ b/mods/ITEMS/mcl_cauldrons/init.lua @@ -128,8 +128,9 @@ minetest.register_craft({ minetest.register_abm({ label = "cauldrons", nodenames = {"group:cauldron_filled"}, - interval = 0.5, + interval = 1, chance = 1, + -- TODO: Move to playerinfo/playerplus/mob api action = function(pos, node) for _, obj in pairs(minetest.get_objects_inside_radius(pos, 0.4)) do if mcl_burning.is_burning(obj) then diff --git a/mods/ITEMS/mcl_end/textures/mcl_end_crystal_beam.png b/mods/ITEMS/mcl_end/textures/mcl_end_crystal_beam.png index 94eac193a..42b05a17f 100644 Binary files a/mods/ITEMS/mcl_end/textures/mcl_end_crystal_beam.png and b/mods/ITEMS/mcl_end/textures/mcl_end_crystal_beam.png differ diff --git a/mods/ITEMS/mcl_mushroom/init.lua b/mods/ITEMS/mcl_mushroom/init.lua index d6b6b97ba..719fbd186 100644 --- a/mods/ITEMS/mcl_mushroom/init.lua +++ b/mods/ITEMS/mcl_mushroom/init.lua @@ -227,7 +227,7 @@ minetest.register_abm({ minetest.register_abm({ label = "mcl_mushroom:warped_checknode", nodenames = {"mcl_mushroom:warped_checknode"}, - interval = 0.1, + interval = 1, chance = 1, action = function(pos) local nodepos = minetest.get_node({x = pos.x, y = pos.y + 1, z = pos.z}) @@ -384,7 +384,7 @@ minetest.register_abm({ minetest.register_abm({ label = "mcl_mushroom:crimson_checknode", nodenames = {"mcl_mushroom:crimson_checknode"}, - interval = 0.1, + interval = 1, chance = 1, action = function(pos) local nodepos = minetest.get_node({x = pos.x, y = pos.y + 1, z = pos.z}) diff --git a/mods/ITEMS/mcl_portals/portal_end.lua b/mods/ITEMS/mcl_portals/portal_end.lua index 803aca74c..3e4f5ba12 100644 --- a/mods/ITEMS/mcl_portals/portal_end.lua +++ b/mods/ITEMS/mcl_portals/portal_end.lua @@ -244,8 +244,9 @@ end minetest.register_abm({ label = "End portal teleportation", nodenames = {"mcl_portals:portal_end"}, - interval = 0.1, + interval = 1, chance = 1, + -- TODO: Move to playerinfo/playerplus/mob api action = mcl_portals.end_portal_teleport, }) diff --git a/mods/ITEMS/mcl_portals/portal_gateway.lua b/mods/ITEMS/mcl_portals/portal_gateway.lua index 505935105..4d79dce53 100644 --- a/mods/ITEMS/mcl_portals/portal_gateway.lua +++ b/mods/ITEMS/mcl_portals/portal_gateway.lua @@ -106,9 +106,10 @@ local function teleport(pos, obj) end minetest.register_abm({ + -- TODO: Move to playerinfo/playerplus/mob api label = "End gateway portal teleportation", nodenames = {"mcl_portals:portal_gateway"}, - interval = 0.1, + interval = 1, chance = 1, action = function(pos) if preparing[minetest.pos_to_string(pos)] then return end diff --git a/mods/ITEMS/mcl_portals/portal_nether.lua b/mods/ITEMS/mcl_portals/portal_nether.lua index 7390bbb2f..a8fdc51b2 100644 --- a/mods/ITEMS/mcl_portals/portal_nether.lua +++ b/mods/ITEMS/mcl_portals/portal_nether.lua @@ -729,8 +729,8 @@ mcl_structures.register_structure({name = "nether_portal", place_function = mcl_ minetest.register_abm({ label = "Nether portal teleportation and particles", nodenames = {PORTAL}, - interval = 0.8, - chance = 3, + interval = 1, + chance = 2, action = function(pos, node) -- Don't use call stack! local upper_node_name = get_node({x = pos.x, y = pos.y + 1, z = pos.z}).name @@ -811,6 +811,7 @@ minetest.register_abm({ }) end end + -- TODO: Move to playerinfo/playerplus/mob api for _, obj in pairs(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 diff --git a/mods/MAPGEN/mcl_biomes/init.lua b/mods/MAPGEN/mcl_biomes/init.lua index 56a3cfe11..8ad8700f0 100644 --- a/mods/MAPGEN/mcl_biomes/init.lua +++ b/mods/MAPGEN/mcl_biomes/init.lua @@ -22,6 +22,10 @@ local OCEAN_MIN = -15 local DEEP_OCEAN_MAX = OCEAN_MIN - 1 local DEEP_OCEAN_MIN = -31 +local minetest_get_perlin = minetest.get_perlin +local math_floor = math.floor +local math_abs = math.abs + --[[ Special biome field: _mcl_biome_type: Rough categorization of biomes: One of "snowy", "cold", "medium" and "hot" Based off ]] @@ -3922,6 +3926,16 @@ local function register_decorations() end -- Decorations in non-Overworld dimensions + +local chorus_noise_params = { + offset = -0.012, + scale = 0.024, + spread = {x = 100, y = 100, z = 100}, + seed = 257, + octaves = 3, + persistence = 0.6, +} + local function register_dimension_decorations() --[[ NETHER ]] -- TODO: Nether @@ -3935,14 +3949,7 @@ local function register_dimension_decorations() place_on = {"mcl_end:end_stone", "air"}, flags = "all_floors", sidelen = 16, - noise_params = { - offset = -0.012, - scale = 0.024, - spread = {x = 100, y = 100, z = 100}, - seed = 257, - octaves = 3, - persist = 0.6 - }, + noise_params = chorus_noise_params, y_min = mcl_mapgen.end_.min, y_max = mcl_mapgen.end_.max, decoration = "mcl_end:chorus_flower", @@ -3962,6 +3969,8 @@ end -- Detect mapgen to select functions -- +local chorus_perlin_noise + if not mcl_mapgen.singlenode then if not superflat then if not mcl_mapgen.v6 then @@ -3994,8 +4003,10 @@ if not mcl_mapgen.singlenode then vm_context.gennotify = vm_context.gennotify or minetest.get_mapgen_object("gennotify") local gennotify = vm_context.gennotify for _, pos in pairs(gennotify["decoration#"..deco_id_chorus_plant] or {}) do + chorus_perlin_noise = chorus_perlin_noise or minetest_get_perlin(chorus_noise_params) local realpos = { x = pos.x, y = pos.y + 1, z = pos.z } - local pr = PseudoRandom(vm_context.blockseed) + local noise = chorus_perlin_noise:get_3d(realpos) + local pr = PseudoRandom(math_floor(math_abs(noise * 32767)) % 32768) minetest.after(1, mcl_end.grow_chorus_plant, realpos, false, pr) end return vm_context @@ -4003,4 +4014,3 @@ if not mcl_mapgen.singlenode then end end - diff --git a/mods/MISC/mcl_commands/summon.lua b/mods/MISC/mcl_commands/summon.lua index 69da0a66c..2a2792f5f 100644 --- a/mods/MISC/mcl_commands/summon.lua +++ b/mods/MISC/mcl_commands/summon.lua @@ -3,13 +3,41 @@ local S = minetest.get_translator(minetest.get_current_modname()) local orig_func = minetest.registered_chatcommands["spawnentity"].func local cmd = table.copy(minetest.registered_chatcommands["spawnentity"]) cmd.func = function(name, param) - local ent = minetest.registered_entities[param] - if minetest.settings:get_bool("only_peaceful_mobs", false) and ent and ent._cmi_is_mob and ent.type == "monster" then - return false, S("Only peaceful mobs allowed!") - else - local bool, msg = orig_func(name, param) - return bool, msg + local params = param:split(" ") + if not params[1] or params[3] then + return false, S("Usage: /spawnentity [,,]") end + local entity_name = params[1] + local pos = params[2] + local entity_def = minetest.registered_entities[entity_name] + if not entity_def then + entity_name = "mobs_mc:" .. entity_name + entity_def = minetest.registered_entities[entity_name] + if not entity_def then + return false, S("Error: Unknown entity name") + end + end + if entity_def._cmi_is_mob then + if minetest.settings:get_bool("only_peaceful_mobs", false) and entity_def.type == "monster" then + return false, S("Only peaceful mobs allowed!") + end + mobs.spawn_mob( + entity_name, + pos + and minetest.string_to_pos(pos) + or vector.add( + minetest.get_player_by_name(name):get_pos(), + { + x = math.random()-0.5, + y = math.random(), + z = math.random()-0.5 + } + ) + ) + return true, S("Mob @1 spawned", entity_name) + end + local bool, msg = orig_func(name, param) + return bool, msg end minetest.unregister_chatcommand("spawnentity") minetest.register_chatcommand("summon", cmd) \ No newline at end of file diff --git a/mods/PLAYER/mcl_antispam/init.lua b/mods/PLAYER/mcl_antispam/init.lua new file mode 100644 index 000000000..11431d5ba --- /dev/null +++ b/mods/PLAYER/mcl_antispam/init.lua @@ -0,0 +1,112 @@ +local ban_spammers = true +local kick_spammers = true +local revoke_shout_for_spammers = true +local limit_messages = 10 +local limit_message_length = 200 +local block_special_chars = true +local enable_antispam = ban_spammers or kick_spammers or revoke_shout_for_spammers + +local function update_settings() + ban_spammers = minetest.settings:get_bool("ban_spammers", true) + kick_spammers = minetest.settings:get_bool("kick_spammers", true) + revoke_shout_for_spammers = minetest.settings:get_bool("revoke_shout_for_spammers", true) + limit_messages = tonumber(minetest.settings:get("limit_messages") or 10) + limit_message_length = tonumber(minetest.settings:get("limit_message_length") or 200) + block_special_chars = minetest.settings:get_bool("block_special_chars", true) + enable_antispam = ban_spammers or kick_spammers or revoke_shout_for_spammers + minetest.after(7, update_settings) +end +update_settings() + +local last_messages = {} +local exceeders = {} +local special_users = {} + +local function ban(name) + if revoke_shout_for_spammers then + local privs = minetest.get_player_privs(name) + if privs then + privs.shout = nil + minetest.set_player_privs(name, privs) + end + end + if ban_spammers then + minetest.ban_player(name) + elseif kick_spammers then + minetest.kick_player(name) + end +end + +local last_char = string.char(127) + +local function on_chat_message(name, message) + if not enable_antispam then return end + local length = message:len() + if last_messages.job then + last_messages.job:cancel() + last_messages.job = nil + end + if last_messages.name and last_messages.name == name then + last_messages.count = last_messages.count + 1 + last_messages.summary_length = last_messages.summary_length + length + if last_messages.count >= limit_messages then + ban(name) + end + else + last_messages.name = name + last_messages.count = 1 + last_messages.summary_length = length + end + last_messages.job = minetest.after(30, function() + last_messages.name = nil + last_messages.job = nil + end) + if limit_message_length > 0 and message:len() > limit_message_length then + if exceeders[name] then + exceeders[name] = exceeders[name] + 1 + if exceeders[name] > limit_messages then + ban(name) + end + else + exceeders[name] = 1 + end + message = message:sub(1, limit_message_length) .. ">8 >8 >8" + minetest.chat_send_all("<" .. name .. "> " .. message) + return true + else + if exceeders[name] then + exceeders[name] = nil + end + end + if block_special_chars then + local sc = false + local msg = "" + for i = 1, #message do + local c = message:sub(i,i) + if c >= " " and c <= last_char then + msg = msg .. c + else + sc = true + end + end + if sc then + if special_users[name] then + special_users[name] = special_users[name] + 1 + if special_users[name] > limit_messages then + ban(name) + end + else + special_users[name] = 1 + end + message = msg + minetest.chat_send_all("<" .. name .. "> " .. message) + return true + else + if special_users[name] then + special_users[name] = nil + end + end + end +end + +minetest.register_on_chat_message(on_chat_message) diff --git a/mods/PLAYER/mcl_antispam/mod.conf b/mods/PLAYER/mcl_antispam/mod.conf new file mode 100644 index 000000000..ef259eab0 --- /dev/null +++ b/mods/PLAYER/mcl_antispam/mod.conf @@ -0,0 +1,2 @@ +name = mcl_antispam +author = kay27 diff --git a/settingtypes.txt b/settingtypes.txt index fd3f6114a..0587438da 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -169,6 +169,20 @@ kick_cheaters (Kick Cheaters) bool false # Cheat kicking threshold kick_threshold (Cheat Kicking Threshold) int 10 +[Antispam] +# Maximum player messages in a sequence +limit_messages (Maximum player messages in a sequence) int 10 +# Maximum message length +limit_message_length (Maximum message length) int 200 +# Block special characters +block_special_chars (Block special characters) bool true +# Ban spammers +ban_spammers (Ban spammers) bool true +# Kick spammers +kick_spammers (Kick spammers) bool true +# Revoke shout priv for spammers +revoke_shout_for_spammers (Revoke shout priv for spammers) bool true + [Debugging] # If enabled, this will show the itemstring of an item in the description. mcl_item_id_debug (Item ID Debug) bool false diff --git a/tools/create_texture__mcl_end_crystal_beam.py b/tools/create_texture__mcl_end_crystal_beam.py new file mode 100644 index 000000000..ab2166714 --- /dev/null +++ b/tools/create_texture__mcl_end_crystal_beam.py @@ -0,0 +1,28 @@ +import png +from random import randrange + +w, h = 16, 256; + +s = [[int(0) for c in range(w)] for c in range(h)] + +def drawpixel(x, y, t): + if (x >= 0) and (x < w) and (y >= 0) and (y < h): + s[y][x] = t + +# R, G, B, Alpha (0xFF = opaque): +palette=[ + (0x00,0x00,0x00,0x00), + (0xFF,0xFF,0x70,0xCC), + (0xFF,0x80,0xDF,0xCC), + (0x80,0xFF,0xDF,0xCC) +] + +for x in range(w): + for y in range(h): + n = randrange(4) + if n == 1: + drawpixel(x, y, randrange(3) + 1) + +w = png.Writer(len(s[0]), len(s), palette=palette, bitdepth=2) +f = open('mcl_end_crystal_beam.png', 'wb') +w.write(f, s)