diff --git a/minetest.conf b/minetest.conf index e122db7b3..223587f4d 100644 --- a/minetest.conf +++ b/minetest.conf @@ -1,5 +1,8 @@ # This is a game specific minetest.conf file, do not edit +# If any of these settings are set in your minetest.conf file in ~/.minetest (Linux) or in the root directory of the game (Run in place/Windows) +# They will override these settings + # Basic game rules time_speed = 72 @@ -33,7 +36,7 @@ mgvalleys_spflags = noaltitude_chill,noaltitude_dry,nohumid_rivers,vary_river_de keepInventory = false # Performance settings -# dedicated_server_step = 0.001 +dedicated_server_step = 0.05 #tick rate # abm_interval = 0.25 # max_objects_per_block = 4096 # max_packets_per_iteration = 10096 diff --git a/mods/CORE/controls/API.md b/mods/CORE/controls/API.md new file mode 100644 index 000000000..8d9df6ca5 --- /dev/null +++ b/mods/CORE/controls/API.md @@ -0,0 +1,23 @@ +# controls + +## controls.players +Table containing player controls at runtime. +WARNING: Never use this table in writing + +## controls.register_on_press(func) +Register a function that will be executed with (player, keyname) every time a player press a key. + +## controls.registered_on_press +Table containing functions registered with controls.register_on_press(). + +## controls.register_on_release(func) +Register a function that will be executed with (player, keyname, clock_from_last_press) every time a player release a key. + +## controls.registered_on_release +Table containing functions registered with controls.register_on_release(). + +## controls.register_on_hold(func) +Register a function that will be executed with (player, keyname, clock_from_start_hold) every time a player hold a key. + +## controls.registered_on_hold +Table containing functions registered with controls.register_on_hold(). \ No newline at end of file diff --git a/mods/CORE/flowlib/API.md b/mods/CORE/flowlib/API.md new file mode 100644 index 000000000..20e85036b --- /dev/null +++ b/mods/CORE/flowlib/API.md @@ -0,0 +1,45 @@ +# flowlib +Simple flow functions. + +## flowlib.is_touching(realpos, nodepos, radius) +Return true if a sphere of at collide with node at . +* realpos: position +* nodepos: position +* radius: number + +## flowlib.is_water(pos) +Return true if node at is water, false overwise. +* pos: position + +## flowlib.node_is_water(node) +Return true if is water, false overwise. +* node: node + +## flowlib.is_lava(pos) +Return true if node at is lava, false overwise. +* pos: position + +## flowlib.node_is_lava(node) +Return true if is lava, false overwise. +* node: node + +## flowlib.is_liquid(pos) +Return true if node at is liquid, false overwise. +* pos: position + +## flowlib.node_is_liquid(node) +Return true if is liquid, false overwise. +* node: node + +## flowlib.quick_flow(pos, node) +Return direction where the water is flowing (to be use to push mobs, items...). +* pos: position +* node: node + +## flowlib.move_centre(pos, realpos, node, radius) +Return the pos of the nearest not water block near from in a sphere of at . +WARNING: This function is never used in mcl2, use at your own risk. The informations described here may be wrong. +* pos: position +* realpos: position, position of the entity +* node: node +* radius: number \ No newline at end of file diff --git a/mods/CORE/mcl_autogroup/API.md b/mods/CORE/mcl_autogroup/API.md new file mode 100644 index 000000000..79b9770b5 --- /dev/null +++ b/mods/CORE/mcl_autogroup/API.md @@ -0,0 +1,27 @@ +# mcl_autogroup +This mod emulate digging times from mc. + +## mcl_autogroup.can_harvest(nodename, toolname) +Return true if can be dig with . +* nodename: string, valid nodename +* toolname: (optional) string, valid toolname + +## mcl_autogroup.get_groupcaps(toolname, efficiency) +This function is used to calculate diggroups for tools. +WARNING: This function can only be called after mod initialization. +* toolname: string, name of the tool being enchanted (like "mcl_tools:diamond_pickaxe") +* efficiency: (optional) integer, the efficiency level the tool is enchanted with (default 0) + +## mcl_autogroup.get_wear(toolname, diggroup) +Return the max wear of with +WARNING: This function can only be called after mod initialization. +* toolname: string, name of the tool used +* diggroup: string, the name of the diggroup the tool is used on + +## mcl_autogroup.register_diggroup(group, def) +* group: string, name of the group to register as a digging group +* def: (optional) table, table with information about the diggroup (defaults to {} if unspecified) + * level: (optional) string, if specified it is an array containing the names of the different digging levels the digging group supports + +## mcl_autogroup.registered_diggroups +List of registered diggroups, indexed by name. \ No newline at end of file diff --git a/mods/CORE/mcl_colors/API.md b/mods/CORE/mcl_colors/API.md new file mode 100644 index 000000000..71cad335b --- /dev/null +++ b/mods/CORE/mcl_colors/API.md @@ -0,0 +1,8 @@ +# mcl_colors +Mod providing global table containing legacity minecraft colors to be used in mods. + +## mcl_colors.* +Colors by upper name, in hex value. + +## mcl_colors.background.* +Background colors by upper name, in hex value. diff --git a/mods/CORE/mcl_explosions/API.md b/mods/CORE/mcl_explosions/API.md new file mode 100644 index 000000000..cb0e9252d --- /dev/null +++ b/mods/CORE/mcl_explosions/API.md @@ -0,0 +1,15 @@ +# mcl_explosions +This mod provide helper functions to create explosions. + +## mcl_explosions.explode(pos, strength, info, puncher) +* pos: position, initial position of the explosion +* strenght: number, radius of the explosion +* info: table, explosion informations: + * drop_chance: number, if specified becomes the drop chance of all nodes in the explosion (default: 1.0 / strength) + * max_blast_resistance: int, if specified the explosion will treat all non-indestructible nodes as having a blast resistance of no more than this value + * sound: bool, if true, the explosion will play a sound (default: true) + * particles: bool, if true, the explosion will create particles (default: true) + * fire: bool, if true, 1/3 nodes become fire (default: false) + * griefing: bool, if true, the explosion will destroy nodes (default: true) + * grief_protected: bool, if true, the explosion will also destroy nodes which have been protected (default: false) +* puncher: (optional) entity, will be used as source for damage done by the explosion \ No newline at end of file diff --git a/mods/CORE/mcl_worlds/API.md b/mods/CORE/mcl_worlds/API.md new file mode 100644 index 000000000..a5509431c --- /dev/null +++ b/mods/CORE/mcl_worlds/API.md @@ -0,0 +1,80 @@ +# mcl_worlds +This mod provides utility functions about positions and dimensions. + +## mcl_worlds.is_in_void(pos) +This function returns: + +* true, true: if pos is in deep void (deadly) +* true, false: if the pos is in void (non deadly) +* false, false: owerwise + +Params: + +* pos: position + +## mcl_worlds.y_to_layer(y) +This function is used to calculate the minetest y layer and dimension of the given minecraft layer. +Mainly used for ore generation. +Takes an Y coordinate as input and returns: + +* The corresponding Minecraft layer (can be nil if void) +* The corresponding Minecraft dimension ("overworld", "nether" or "end") or "void" if is in the void +If the Y coordinate is not located in any dimension, it will return: nil, "void" + +Params: + +* y: int + +## mcl_worlds.pos_to_dimension(pos) +This function return the Minecraft dimension of ("overworld", "nether" or "end") or "void" if is in the void. + +* pos: position + +## mcl_worlds.layer_to_y(layer, mc_dimension) +Takes a Minecraft layer and a “dimension” name and returns the corresponding Y coordinate for MineClone 2. +mc_dimension can be "overworld", "nether", "end" (default: "overworld"). + +* layer: int +* mc_dimension: string + +## mcl_worlds.has_weather(pos) +Returns true if can have weather, false owerwise. +Weather can be only in the overworld. + +* pos: position + +## mcl_worlds.has_dust(pos) +Returns true if can have nether dust, false owerwise. +Nether dust can be only in the nether. + +* pos: position + +## mcl_worlds.compass_works(pos) +Returns true if compasses are working at , false owerwise. +In mc, you cant use compass in the nether and the end. + +* pos: position + +## mcl_worlds.compass_works(pos) +Returns true if clock are working at , false owerwise. +In mc, you cant use clock in the nether and the end. + +* pos: position + +## mcl_worlds.register_on_dimension_change(function(player, dimension)) +Register a callback function func(player, dimension). +It will be called whenever a player changes between dimensions. +The void counts as dimension. + +* player: player, the player who changed the dimension +* dimension: position, The new dimension of the player ("overworld", "nether", "end", "void"). + + +## mcl_worlds.registered_on_dimension_change +Table containing all function registered with mcl_worlds.register_on_dimension_change() + +## mcl_worlds.dimension_change(player, dimension) +Notify this mod of a dimmension change of to + +* player: player, player who changed the dimension +* dimension: string, new dimension ("overworld", "nether", "end", "void") \ No newline at end of file diff --git a/mods/ENTITIES/mcl_boats/init.lua b/mods/ENTITIES/mcl_boats/init.lua index efb6c073e..38e73565b 100644 --- a/mods/ENTITIES/mcl_boats/init.lua +++ b/mods/ENTITIES/mcl_boats/init.lua @@ -1,6 +1,6 @@ local S = minetest.get_translator("mcl_boats") -local boat_visual_size = {x = 3, y = 3, z = 3} +local boat_visual_size = {x = 1, y = 1, z = 1} local paddling_speed = 22 local boat_y_offset = 0.35 local boat_y_offset_ground = boat_y_offset + 0.6 diff --git a/mods/ENTITIES/mcl_boats/models/mcl_boats_boat.b3d b/mods/ENTITIES/mcl_boats/models/mcl_boats_boat.b3d index e53bc4129..6c9c31469 100644 Binary files a/mods/ENTITIES/mcl_boats/models/mcl_boats_boat.b3d and b/mods/ENTITIES/mcl_boats/models/mcl_boats_boat.b3d differ diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index 95b90e546..b65585a15 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -1,14 +1,36 @@ +--these are lua locals, used for higher performance +local minetest,math,vector,ipairs = minetest,math,vector,ipairs + +--this is used for the player pool in the sound buffer +local pool = {} + +local tick = false + +minetest.register_on_joinplayer(function(player) + local name + name = player:get_player_name() + pool[name] = 0 +end) + +minetest.register_on_leaveplayer(function(player) + local name + name = player:get_player_name() + pool[name] = nil +end) + + local has_awards = minetest.get_modpath("awards") -mcl_item_entity = {} +local mcl_item_entity = {} --basic settings local item_drop_settings = {} --settings table +item_drop_settings.dug_buffer = 0.65 -- the warm up period before a dug item can be collected item_drop_settings.age = 1.0 --how old a dropped item (_insta_collect==false) has to be before collecting item_drop_settings.radius_magnet = 2.0 --radius of item magnet. MUST BE LARGER THAN radius_collect! item_drop_settings.xp_radius_magnet = 7.25 --radius of xp magnet. MUST BE LARGER THAN radius_collect! item_drop_settings.radius_collect = 0.2 --radius of collection -item_drop_settings.player_collect_height = 1.0 --added to their pos y value +item_drop_settings.player_collect_height = 0.8 --added to their pos y value item_drop_settings.collection_safety = false --do this to prevent items from flying away on laggy servers item_drop_settings.random_item_velocity = true --this sets random item velocity if velocity is 0 item_drop_settings.drop_single_item = false --if true, the drop control drops 1 item instead of the entire stack, and sneak+drop drops the stack @@ -74,103 +96,71 @@ local disable_physics = function(object, luaentity, ignore_check, reset_movement end end + minetest.register_globalstep(function(dtime) + + tick = not tick + for _,player in pairs(minetest.get_connected_players()) do if player:get_hp() > 0 or not minetest.settings:get_bool("enable_damage") then + + + local name = player:get_player_name() + local pos = player:get_pos() + + if tick == true and pool[name] > 0 then + minetest.sound_play("item_drop_pickup", { + pos = pos, + gain = 0.7, + max_hear_distance = 16, + pitch = math.random(70,110)/100 + }) + if pool[name] > 6 then + pool[name] = 6 + else + pool[name] = pool[name] - 1 + end + end + + + local inv = player:get_inventory() local checkpos = {x=pos.x,y=pos.y + item_drop_settings.player_collect_height,z=pos.z} --magnet and collection for _,object in pairs(minetest.get_objects_inside_radius(checkpos, item_drop_settings.xp_radius_magnet)) do if not object:is_player() and vector.distance(checkpos, object:get_pos()) < item_drop_settings.radius_magnet and object:get_luaentity() and object:get_luaentity().name == "__builtin:item" and object:get_luaentity()._magnet_timer and (object:get_luaentity()._insta_collect or (object:get_luaentity().age > item_drop_settings.age)) then - object:get_luaentity()._magnet_timer = object:get_luaentity()._magnet_timer + dtime - local collected = false + if object:get_luaentity()._magnet_timer >= 0 and object:get_luaentity()._magnet_timer < item_drop_settings.magnet_time and inv and inv:room_for_item("main", ItemStack(object:get_luaentity().itemstring)) then -- Collection - if vector.distance(checkpos, object:get_pos()) <= item_drop_settings.radius_collect and not object:get_luaentity()._removed then + if not object:get_luaentity()._removed then -- Ignore if itemstring is not set yet if object:get_luaentity().itemstring ~= "" then inv:add_item("main", ItemStack(object:get_luaentity().itemstring)) - minetest.sound_play("item_drop_pickup", { - pos = pos, - max_hear_distance = 16, - gain = 1.0, - }, true) - check_pickup_achievements(object, player) + check_pickup_achievements(object, player) -- Destroy entity -- This just prevents this section to be run again because object:remove() doesn't remove the item immediately. + object:get_luaentity().target = checkpos object:get_luaentity()._removed = true - object:remove() - collected = true + + object:set_velocity({x=0,y=0,z=0}) + object:set_acceleration({x=0,y=0,z=0}) + + object:move_to(checkpos) + + pool[name] = pool[name] + 1 + + minetest.after(0.25, function() + --safety check + if object and object:get_luaentity() then + object:remove() + end + end) end - - -- Magnet - else - - object:get_luaentity()._magnet_active = true - object:get_luaentity()._collector_timer = 0 - - -- Move object to player - disable_physics(object, object:get_luaentity()) - - local opos = object:get_pos() - local vec = vector.subtract(checkpos, opos) - vec = vector.add(opos, vector.divide(vec, 2)) - object:move_to(vec) - - - --fix eternally falling items - minetest.after(0, function(object) - local lua = object:get_luaentity() - if lua then - object:set_acceleration({x=0, y=0, z=0}) - end - end, object) - - - --this is a safety to prevent items flying away on laggy servers - if item_drop_settings.collection_safety == true then - if object:get_luaentity().init ~= true then - object:get_luaentity().init = true - minetest.after(1, function(args) - local playername = args[1] - local player = minetest.get_player_by_name(playername) - local object = args[2] - local lua = object:get_luaentity() - if player == nil or not player:is_player() or object == nil or lua == nil or lua.itemstring == nil then - return - end - if inv:room_for_item("main", ItemStack(object:get_luaentity().itemstring)) then - inv:add_item("main", ItemStack(object:get_luaentity().itemstring)) - if not object:get_luaentity()._removed then - minetest.sound_play("item_drop_pickup", { - pos = pos, - max_hear_distance = 16, - gain = 1.0, - }, true) - end - check_pickup_achievements(object, player) - object:get_luaentity()._removed = true - object:remove() - else - enable_physics(object, object:get_luaentity()) - end - end, {player:get_player_name(), object}) - end - end - end - end - - if not collected then - if object:get_luaentity()._magnet_timer > 1 then - object:get_luaentity()._magnet_timer = -item_drop_settings.magnet_time - object:get_luaentity()._magnet_active = false - elseif object:get_luaentity()._magnet_timer < 0 then - object:get_luaentity()._magnet_timer = object:get_luaentity()._magnet_timer + dtime end end @@ -230,12 +220,13 @@ local function get_fortune_drops(fortune_drops, fortune_level) return drop or {} end +local doTileDrops = minetest.settings:get_bool("mcl_doTileDrops", true) + function minetest.handle_node_drops(pos, drops, digger) -- NOTE: This function override allows digger to be nil. -- This means there is no digger. This is a special case which allows this function to be called -- by hand. Creative Mode is intentionally ignored in this case. - local doTileDrops = minetest.settings:get_bool("mcl_doTileDrops", true) if (digger and digger:is_player() and minetest.is_creative_enabled(digger:get_player_name())) or doTileDrops == false then return end @@ -335,6 +326,10 @@ function minetest.handle_node_drops(pos, drops, digger) z = -z end obj:set_velocity({x=1/x, y=obj:get_velocity().y, z=1/z}) + + obj:get_luaentity().age = item_drop_settings.dug_buffer + + obj:get_luaentity()._insta_collect = false end end end @@ -401,6 +396,9 @@ minetest.register_entity(":__builtin:item", { -- Number of seconds this item entity has existed so far age = 0, + -- How old it has become in the collection animation + collection_age = 0, + set_item = function(self, itemstring) self.itemstring = itemstring if self.itemstring == "" then @@ -566,6 +564,11 @@ minetest.register_entity(":__builtin:item", { on_step = function(self, dtime) if self._removed then + self.object:set_properties({ + physical = false + }) + self.object:set_velocity({x=0,y=0,z=0}) + self.object:set_acceleration({x=0,y=0,z=0}) return end self.age = self.age + dtime diff --git a/mods/ENTITIES/mcl_item_entity/sounds/Attributes.txt b/mods/ENTITIES/mcl_item_entity/sounds/Attributes.txt new file mode 100644 index 000000000..781759352 --- /dev/null +++ b/mods/ENTITIES/mcl_item_entity/sounds/Attributes.txt @@ -0,0 +1 @@ + Item_Drop_Pickup - https://freesound.org/people/benniknop/sounds/317848/ (License: CC0) diff --git a/mods/ENTITIES/mcl_item_entity/sounds/item_drop_pickup.1.ogg b/mods/ENTITIES/mcl_item_entity/sounds/item_drop_pickup.1.ogg deleted file mode 100644 index 8010ff0a2..000000000 Binary files a/mods/ENTITIES/mcl_item_entity/sounds/item_drop_pickup.1.ogg and /dev/null differ diff --git a/mods/ENTITIES/mcl_item_entity/sounds/item_drop_pickup.2.ogg b/mods/ENTITIES/mcl_item_entity/sounds/item_drop_pickup.2.ogg deleted file mode 100644 index a5087ab7d..000000000 Binary files a/mods/ENTITIES/mcl_item_entity/sounds/item_drop_pickup.2.ogg and /dev/null differ diff --git a/mods/ENTITIES/mcl_item_entity/sounds/item_drop_pickup.3.ogg b/mods/ENTITIES/mcl_item_entity/sounds/item_drop_pickup.3.ogg deleted file mode 100644 index f234a482c..000000000 Binary files a/mods/ENTITIES/mcl_item_entity/sounds/item_drop_pickup.3.ogg and /dev/null differ diff --git a/mods/ENTITIES/mcl_item_entity/sounds/item_drop_pickup.4.ogg b/mods/ENTITIES/mcl_item_entity/sounds/item_drop_pickup.4.ogg deleted file mode 100644 index 6436f2678..000000000 Binary files a/mods/ENTITIES/mcl_item_entity/sounds/item_drop_pickup.4.ogg and /dev/null differ diff --git a/mods/ENTITIES/mcl_item_entity/sounds/item_drop_pickup.ogg b/mods/ENTITIES/mcl_item_entity/sounds/item_drop_pickup.ogg new file mode 100644 index 000000000..e7f5df094 Binary files /dev/null and b/mods/ENTITIES/mcl_item_entity/sounds/item_drop_pickup.ogg differ diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index f1df87e8b..0a038ba13 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -735,7 +735,9 @@ local item_drop = function(self, cooked, looting_level) end -- add item if it exists - obj = minetest.add_item(pos, ItemStack(item .. " " .. num)) + for x = 1, num do + obj = minetest.add_item(pos, ItemStack(item .. " " .. 1)) + end if obj and obj:get_luaentity() then @@ -2817,6 +2819,10 @@ local do_states = function(self, dtime) local arrow, ent local v = 1 if not self.shoot_arrow then + self.firing = true + minetest.after(1, function() + self.firing = false + end) arrow = minetest.add_entity(p, self.arrow) ent = arrow:get_luaentity() if ent.velocity then @@ -4221,6 +4227,11 @@ function mobs:register_arrow(name, def) switch = 0, owner_id = def.owner_id, rotate = def.rotate, + on_punch = function(self) + local vel = self.object:get_velocity() + self.object:set_velocity({x=vel.x * -1, y=vel.y * -1, z=vel.z * -1}) + end, + collisionbox = def.collisionbox or {0, 0, 0, 0, 0, 0}, automatic_face_movement_dir = def.rotate and (def.rotate - (pi / 180)) or false, @@ -4283,7 +4294,7 @@ function mobs:register_arrow(name, def) if self.hit_player or self.hit_mob or self.hit_object then - for _,player in pairs(minetest.get_objects_inside_radius(pos, 1.0)) do + for _,player in pairs(minetest.get_objects_inside_radius(pos, 1.5)) do if self.hit_player and player:is_player() then diff --git a/mods/ENTITIES/mobs_mc/enderman.lua b/mods/ENTITIES/mobs_mc/enderman.lua index efc789344..22599dd9e 100644 --- a/mods/ENTITIES/mobs_mc/enderman.lua +++ b/mods/ENTITIES/mobs_mc/enderman.lua @@ -534,9 +534,11 @@ mobs:register_mob("mobs_mc:enderman", { --if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then -- self:teleport(nil) --else + if pr:next(1, 8) == 8 then --FIXME: real mc rate self:teleport(hitter) - self.attack=hitter - self.state="attack" + end + self.attack=hitter + self.state="attack" --end end end, diff --git a/mods/ENTITIES/mobs_mc/ghast.lua b/mods/ENTITIES/mobs_mc/ghast.lua index 679a28c13..7aed9395e 100644 --- a/mods/ENTITIES/mobs_mc/ghast.lua +++ b/mods/ENTITIES/mobs_mc/ghast.lua @@ -63,6 +63,15 @@ mobs:register_mob("mobs_mc:ghast", { makes_footstep_sound = false, instant_death = true, fire_resistant = true, + do_custom = function(self) + if self.firing == true then + self.base_texture = {"mobs_mc_ghast_firing.png"} + self.object:set_properties({textures=self.base_texture}) + else + self.base_texture = {"mobs_mc_ghast.png"} + self.object:set_properties({textures=self.base_texture}) + end + end, }) @@ -74,6 +83,7 @@ mobs:register_arrow("mobs_mc:fireball", { visual_size = {x = 1, y = 1}, textures = {"mcl_fire_fire_charge.png"}, velocity = 15, + collisionbox = {-.5, -.5, -.5, .5, .5, .5}, hit_player = function(self, player) if rawget(_G, "armor") and armor.last_damage_types then diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_ghast_firing.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_ghast_firing.png new file mode 100644 index 000000000..3e5b41c32 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_ghast_firing.png differ diff --git a/mods/HUD/hudbars/default_settings.lua b/mods/HUD/hudbars/default_settings.lua index 0bd267d0e..ce43cc8be 100644 --- a/mods/HUD/hudbars/default_settings.lua +++ b/mods/HUD/hudbars/default_settings.lua @@ -20,9 +20,9 @@ if hb.settings.bar_type == "progress_bar" then hb.settings.start_offset_right.x = hb.load_setting("hudbars_start_offset_right_x", "number", 15) hb.settings.start_offset_right.y = hb.load_setting("hudbars_start_offset_right_y", "number", -86) else - hb.settings.start_offset_left.x = hb.load_setting("hudbars_start_statbar_offset_left_x", "number", -265) + hb.settings.start_offset_left.x = hb.load_setting("hudbars_start_statbar_offset_left_x", "number", -258) hb.settings.start_offset_left.y = hb.load_setting("hudbars_start_statbar_offset_left_y", "number", -90) - hb.settings.start_offset_right.x = hb.load_setting("hudbars_start_statbar_offset_right_x", "number", 25) + hb.settings.start_offset_right.x = hb.load_setting("hudbars_start_statbar_offset_right_x", "number", 16) hb.settings.start_offset_right.y = hb.load_setting("hudbars_start_statbar_offset_right_y", "number", -90) end -- Modified in MCL2! diff --git a/mods/ITEMS/REDSTONE/mesecons_mvps/init.lua b/mods/ITEMS/REDSTONE/mesecons_mvps/init.lua index 669edbcbb..8cd5ae872 100644 --- a/mods/ITEMS/REDSTONE/mesecons_mvps/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_mvps/init.lua @@ -74,6 +74,7 @@ function mesecon.is_mvps_unsticky(node, pulldir, stack, stackid) end -- Functions to be called on mvps movement +-- See also the callback function mesecon.register_on_mvps_move(callback) mesecon.on_mvps_move[#mesecon.on_mvps_move+1] = callback end @@ -405,17 +406,20 @@ mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_brown") mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_light_blue") mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_pink") +-- Includes node heat when moving them mesecon.register_on_mvps_move(mesecon.move_hot_nodes) --- Check for falling after moving node mesecon.register_on_mvps_move(function(moved_nodes) for i = 1, #moved_nodes do local moved_node = moved_nodes[i] + -- Check for falling after moving node mesecon.on_placenode(moved_node.pos, moved_node.node) minetest.after(0, function() minetest.check_for_falling(moved_node.oldpos) minetest.check_for_falling(moved_node.pos) end) + + -- Callback for on_mvps_move stored in nodedef local node_def = minetest.registered_nodes[moved_node.node.name] if node_def and node_def.mesecon and node_def.mesecon.on_mvps_move then node_def.mesecon.on_mvps_move(moved_node.pos, moved_node.node, diff --git a/mods/ITEMS/mcl_armor/armor.lua b/mods/ITEMS/mcl_armor/armor.lua index a879f7240..05a020016 100644 --- a/mods/ITEMS/mcl_armor/armor.lua +++ b/mods/ITEMS/mcl_armor/armor.lua @@ -367,6 +367,7 @@ mcl_player.player_register_model("mcl_armor_character.b3d", { run_walk = {x=440, y=459}, run_walk_mine = {x=461, y=480}, sit_mount = {x=484, y=484}, + die = {x=498, y=498}, }, }) diff --git a/mods/ITEMS/mcl_armor/models/mcl_armor_character.b3d b/mods/ITEMS/mcl_armor/models/mcl_armor_character.b3d index c6a1274c5..a658f753c 100644 Binary files a/mods/ITEMS/mcl_armor/models/mcl_armor_character.b3d and b/mods/ITEMS/mcl_armor/models/mcl_armor_character.b3d differ diff --git a/mods/ITEMS/mcl_armor/models/mcl_armor_character.blend b/mods/ITEMS/mcl_armor/models/mcl_armor_character.blend index 88db35cf5..12869b59d 100644 Binary files a/mods/ITEMS/mcl_armor/models/mcl_armor_character.blend and b/mods/ITEMS/mcl_armor/models/mcl_armor_character.blend differ diff --git a/mods/ITEMS/mcl_armor/models/mcl_armor_character_female.b3d b/mods/ITEMS/mcl_armor/models/mcl_armor_character_female.b3d index cd2fca988..44494d1ec 100644 Binary files a/mods/ITEMS/mcl_armor/models/mcl_armor_character_female.b3d and b/mods/ITEMS/mcl_armor/models/mcl_armor_character_female.b3d differ diff --git a/mods/ITEMS/mcl_armor/models/mcl_armor_character_female.blend b/mods/ITEMS/mcl_armor/models/mcl_armor_character_female.blend index 098417b42..c854a49e5 100644 Binary files a/mods/ITEMS/mcl_armor/models/mcl_armor_character_female.blend and b/mods/ITEMS/mcl_armor/models/mcl_armor_character_female.blend differ diff --git a/mods/ITEMS/mcl_bows/models/mcl_bows_arrow.obj b/mods/ITEMS/mcl_bows/models/mcl_bows_arrow.obj index 8530efa78..bee2c0f4b 100644 --- a/mods/ITEMS/mcl_bows/models/mcl_bows_arrow.obj +++ b/mods/ITEMS/mcl_bows/models/mcl_bows_arrow.obj @@ -1,56 +1,56 @@ -# Blender v2.91.0 OBJ File: '' +# Blender v2.92.0 OBJ File: '' # www.blender.org mtllib mcl_bows_arrow.mtl o Plane -v -3.782006 -1.443249 0.000500 -v -3.782006 1.444249 0.000500 -v 3.782006 1.444249 0.000500 -v 3.782006 -1.443249 0.000500 -v 3.331104 1.069925 1.085017 -v 3.331104 -1.100076 1.085017 -v 3.331104 1.069925 -1.064830 -v 3.331104 -1.100076 -1.064829 -v 3.782006 0.001000 1.443749 -v 3.782006 0.001000 -1.443750 -v -3.782006 0.001000 -1.443749 -v -3.782006 0.001000 1.443750 -v 3.782006 0.000000 -1.443750 -v 3.782006 0.000000 1.443749 -v -3.782006 0.000000 1.443750 -v -3.782006 0.000000 -1.443749 v 3.782006 1.444249 -0.000500 v 3.782006 -1.443249 -0.000500 v -3.782006 -1.443249 -0.000500 v -3.782006 1.444249 -0.000500 -vt 0.000000 0.300000 -vt 0.000000 0.700000 -vt 1.000000 0.700000 -vt 1.000000 0.300000 -vt -0.007553 -0.000373 -vt 0.296712 -0.000373 -vt 0.296712 0.298611 -vt -0.007553 0.298611 -vt 0.000000 0.300000 -vt 1.000000 0.300000 -vt 1.000000 0.700000 -vt 0.000000 0.700000 -vt 0.000000 0.300000 -vt 1.000000 0.300000 -vt 1.000000 0.700000 -vt 0.000000 0.700000 -vt 0.000000 0.300000 -vt 0.000000 0.700000 -vt 1.000000 0.700000 -vt 1.000000 0.300000 -vn -0.0000 -0.0000 -1.0000 -vn 1.0000 -0.0000 0.0000 +v 3.331104 -1.100076 -1.064829 +v 3.331104 1.069925 -1.064830 +v 3.331104 1.069925 1.085017 +v 3.331104 -1.100076 1.085017 +v 3.782006 0.001000 -1.443750 +v -3.782006 0.001000 -1.443749 +v -3.782006 0.001000 1.443750 +v 3.782006 0.001000 1.443749 +v 3.782006 1.444249 0.000500 +v -3.782006 1.444249 0.000500 +v -3.782006 -1.443249 0.000500 +v 3.782006 -1.443249 0.000500 +v 3.782006 0.000000 -1.443750 +v 3.782006 -0.000000 1.443749 +v -3.782006 -0.000000 1.443750 +v -3.782006 0.000000 -1.443749 +vt -0.000893 0.835148 +vt -0.000893 1.008567 +vt 0.486244 1.008567 +vt 0.486244 0.835148 +vt 0.159016 0.682983 +vt 0.159016 0.849928 +vt -0.005031 0.849928 +vt -0.005031 0.682983 +vt -0.000893 0.835148 +vt 0.486244 0.835148 +vt 0.486244 1.008567 +vt -0.000893 1.008567 +vt -0.000893 0.835148 +vt 0.486244 0.835148 +vt 0.486244 1.008567 +vt -0.000893 1.008567 +vt -0.000893 0.835148 +vt -0.000893 1.008567 +vt 0.486244 1.008567 +vt 0.486244 0.835148 +vn 0.0000 0.0000 -1.0000 +vn 1.0000 0.0000 0.0000 vn 0.0000 1.0000 0.0000 -vn 0.0000 0.0000 1.0000 -vn 0.0000 -1.0000 0.0000 +vn 0.0000 -0.0000 1.0000 +vn -0.0000 -1.0000 -0.0000 usemtl Material.002 -s off -f 17/1/1 18/2/1 19/3/1 20/4/1 -f 8/5/2 7/6/2 5/7/2 6/8/2 -f 10/9/3 11/10/3 12/11/3 9/12/3 -f 3/13/4 2/14/4 1/15/4 4/16/4 -f 13/17/5 14/18/5 15/19/5 16/20/5 +s 1 +f 1/1/1 2/2/1 3/3/1 4/4/1 +f 5/5/2 6/6/2 7/7/2 8/8/2 +f 9/9/3 10/10/3 11/11/3 12/12/3 +f 13/13/4 14/14/4 15/15/4 16/16/4 +f 17/17/5 18/18/5 19/19/5 20/20/5 diff --git a/mods/ITEMS/mcl_bows/textures/mcl_bows_arrow.png b/mods/ITEMS/mcl_bows/textures/mcl_bows_arrow.png index 244405288..f7bd92a9c 100644 Binary files a/mods/ITEMS/mcl_bows/textures/mcl_bows_arrow.png and b/mods/ITEMS/mcl_bows/textures/mcl_bows_arrow.png differ diff --git a/mods/ITEMS/mcl_core/nodes_liquid.lua b/mods/ITEMS/mcl_core/nodes_liquid.lua index 0479c7f72..4696a629a 100644 --- a/mods/ITEMS/mcl_core/nodes_liquid.lua +++ b/mods/ITEMS/mcl_core/nodes_liquid.lua @@ -7,10 +7,10 @@ local WATER_ALPHA = 179 local WATER_VISC = 1 local LAVA_VISC = 7 local LIGHT_LAVA = minetest.LIGHT_MAX -local USE_TEXTURE_ALPHA +local USE_TEXTURE_ALPHA = true + if minetest.features.use_texture_alpha_string_modes then USE_TEXTURE_ALPHA = "blend" - WATER_ALPHA = nil end local lava_death_messages = { @@ -40,7 +40,6 @@ minetest.register_node("mcl_core:water_flowing", { }, sounds = mcl_sounds.node_sound_water_defaults(), is_ground_content = false, - alpha = WATER_ALPHA, use_texture_alpha = USE_TEXTURE_ALPHA, paramtype = "light", paramtype2 = "flowingliquid", @@ -86,7 +85,6 @@ S("• When water is directly below lava, the water turns into stone."), }, sounds = mcl_sounds.node_sound_water_defaults(), is_ground_content = false, - alpha = WATER_ALPHA, use_texture_alpha = USE_TEXTURE_ALPHA, paramtype = "light", walkable = false, diff --git a/mods/ITEMS/mcl_end/end_crystal.lua b/mods/ITEMS/mcl_end/end_crystal.lua index b6b9fdd6a..d089c3cdf 100644 --- a/mods/ITEMS/mcl_end/end_crystal.lua +++ b/mods/ITEMS/mcl_end/end_crystal.lua @@ -70,7 +70,7 @@ minetest.register_entity("mcl_end:crystal", { collisionbox = {-1, 0.5, -1, 1, 2.5, 1}, mesh = "mcl_end_crystal.b3d", textures = {"mcl_end_crystal.png"}, - collide_with_objects = true, + collide_with_objects = false, }, on_punch = crystal_explode, on_activate = set_crystal_animation, diff --git a/mods/ITEMS/mcl_fishing/init.lua b/mods/ITEMS/mcl_fishing/init.lua index 228d490ea..2bd0ed515 100644 --- a/mods/ITEMS/mcl_fishing/init.lua +++ b/mods/ITEMS/mcl_fishing/init.lua @@ -303,8 +303,8 @@ local flying_bobber_ENTITY={ collisionbox = {0,0,0,0,0,0}, pointable = false, - get_staticdata = get_staticdata, - on_activate = on_activate, + get_staticdata = mcl_throwing.get_staticdata, + on_activate = mcl_throwing.on_activate, _lastpos={}, _thrower = nil, diff --git a/mods/ITEMS/mcl_ocean/init.lua b/mods/ITEMS/mcl_ocean/init.lua index 2a103b8d0..f723a1f3f 100644 --- a/mods/ITEMS/mcl_ocean/init.lua +++ b/mods/ITEMS/mcl_ocean/init.lua @@ -1,3 +1,5 @@ +mcl_ocean = {} + -- Prismarine (includes sea lantern) dofile(minetest.get_modpath(minetest.get_current_modname()).."/prismarine.lua") diff --git a/mods/ITEMS/mcl_ocean/kelp.lua b/mods/ITEMS/mcl_ocean/kelp.lua index 3c6e32422..3aefe85f8 100644 --- a/mods/ITEMS/mcl_ocean/kelp.lua +++ b/mods/ITEMS/mcl_ocean/kelp.lua @@ -1,71 +1,494 @@ +-- TODO: whenever it becomes possible to fully implement kelp without the +-- plantlike_rooted limitation, please update accordingly. +-- +-- TODO: In MC, you can't actually destroy kelp by bucket'ing water in the middle. +-- However, because of the plantlike_rooted hack, we'll just allow it for now. + local S = minetest.get_translator("mcl_ocean") local mod_doc = minetest.get_modpath("doc") ~= nil --- List of supported surfaces for seagrass and kelp -local surfaces = { - { "dirt", "mcl_core:dirt" }, - { "sand", "mcl_core:sand", 1 }, - { "redsand", "mcl_core:redsand", 1 }, - { "gravel", "mcl_core:gravel", 1 }, -} +-------------------------------------------------------------------------------- +-- local-ify runtime functions +-------------------------------------------------------------------------------- +-- objects +local mt_registered_items = minetest.registered_items +local mt_registered_nodes = minetest.registered_nodes -local function get_kelp_top(pos, node) - local size = math.ceil(node.param2 / 16) - local pos_water = table.copy(pos) - pos_water.y = pos_water.y + size - return pos_water, minetest.get_node(pos_water) +-- functions +local mt_log = minetest.log +local mt_add_item = minetest.add_item +local mt_get_item_group = minetest.get_item_group +local mt_get_node = minetest.get_node +local mt_get_node_level = minetest.get_node_level +local mt_get_node_max_level = minetest.get_node_max_level +local mt_get_node_or_nil = minetest.get_node_or_nil +local mt_get_node_timer = minetest.get_node_timer +local mt_get_meta = minetest.get_meta +local mt_hash_node_position = minetest.hash_node_position +local mt_set_node = minetest.set_node +local mt_swap_node = minetest.swap_node +local mt_pos_to_string = minetest.pos_to_string +local mt_is_protected = minetest.is_protected +local mt_record_protection_violation = minetest.record_protection_violation + +local mt_is_creative_enabled = minetest.is_creative_enabled +local mt_sound_play = minetest.sound_play + +local math_min = math.min +local math_max = math.max +local math_ceil = math.ceil +local math_floor = math.floor +local math_random = math.random +local string_format = string.format +local table_copy = table.copy +local table_insert = table.insert + +-- DEBUG: functions +-- local log = minetest.log +-- local chatlog = minetest.chat_send_all + +-------------------------------------------------------------------------------- +-- Kelp API +-------------------------------------------------------------------------------- + +local kelp = {} +mcl_ocean.kelp = kelp + +-- Kelp minimum and maximum age. Once reached the maximum, kelp no longer grows. +kelp.MIN_AGE = 0 +kelp.MAX_AGE = 25 + +-- Tick interval (in seconds) for updating kelp. +kelp.TICK = 0.2 + +-- Tick interval (in seconds) to store kelp meta. +kelp.META_TICK = 2 + +-- Max age queue length +kelp.MAX_AGE_QUEUE = 20 + +-- The average amount of growth for kelp in a day is 2.16 (https://youtu.be/5Bp4lAjAk3I) +-- Normally, a day lasts 20 minutes, meaning kelp.next_grow() is executed +-- 1200 / TICK times. Per tick probability = (216/100) / (1200/TICK) +-- NOTE: currently, we can't exactly use the same type of randomness MC does, because +-- it has multiple complicated sets of PRNGs. +-- NOTE: Small loss of precision, should be 10 to preserve it. +-- kelp.ROLL_GROWTH_PRECISION = 10 +-- kelp.ROLL_GROWTH_NUMERATOR = 216 * kelp.TICK * kelp.ROLL_GROWTH_PRECISION +-- kelp.ROLL_GROWTH_DENOMINATOR = 100 * 1200 * kelp.ROLL_GROWTH_PRECISION +kelp.ROLL_GROWTH_PRECISION = 1 +kelp.ROLL_GROWTH_NUMERATOR = 216 * kelp.TICK +kelp.ROLL_GROWTH_DENOMINATOR = 100 * 1200 + +-- Sounds used to dig and place kelp. +kelp.leaf_sounds = mcl_sounds.node_sound_leaves_defaults() + +-- Pool storing nodetimers +kelp.timers_pool = {} + +-- Pool storing age, indexed by pos_hash. +kelp.age_pool = {} + +-- Queue(List) of hashed positions to save their ages. +-- Invalid ones may still persist in this queue. +kelp.age_queue = {} +-- Stores only valid positions of each hashed postiions. +kelp.age_queue_pos = {} + + +-- is age in the growable range? +function kelp.is_age_growable(age) + return age >= 0 and age < kelp.MAX_AGE end -local function get_submerged(node_water) - local def_water = minetest.registered_nodes[node_water.name] - -- Submerged in water? - if minetest.get_item_group(node_water.name, "water") then - if def_water.liquidtype == "source" then - return "source" - elseif def_water.liquidtype == "flowing" then - return "flowing" - end + +-- Is this water? +-- Returns the liquidtype, if indeed water. +function kelp.is_submerged(node) + if mt_get_item_group(node.name, "water") ~= 0 then + -- Expected only "source" and "flowing" from water liquids + return mt_registered_nodes[node.name].liquidtype end return false end -local function grow_param2_step(param2, snap_into_grid) - local old_param2 = param2 - param2 = param2 + 16 - if param2 > 240 then - param2 = 240 + +-- Is the water downward flowing? +-- (kelp can grow/be placed inside downward flowing water) +function kelp.is_downward_flowing(pos, node, pos_above, node_above, __is_above__) + -- Function params: (pos[, node]) or (node, pos_above) or (node, node_above) + local node = node or mt_get_node(pos) + + local result = (math_floor(node.param2 / 8) % 2) == 1 + if not (result or __is_above__) then + -- If not, also check node above. + -- (this is needed due a weird quirk in the definition of "downwards flowing" + -- liquids in Minetest) + local pos_above = pos_above or {x=pos.x,y=pos.y+1,z=pos.z} + local node_above = node_above or mt_get_node(pos_above) + result = kelp.is_submerged(node_above) + or kelp.is_downward_flowing(nil, node_above, nil, nil, true) end - if snap_into_grid and (param2 % 16 ~= 0) then - param2 = param2 - (param2 % 16) - end - return param2, param2 ~= old_param2 + return result end -local function kelp_check_place(pos_above, node_above, def_above) - if minetest.get_item_group(node_above.name, "water") == 0 then + +-- Will node fall at that position? +-- This only checks if a node would fall, meaning that node need not be at pos. +function kelp.is_falling(pos, node, is_falling, pos_bottom, node_bottom, def_bottom) + -- Optional params: is_falling, pos_bottom, node_bottom, def_bottom + + -- NOTE: Modified from check_single_for_falling in builtin. + -- Please update accordingly. + local nodename = node.name + + if is_falling == false or + is_falling == nil and mt_get_item_group(nodename, "falling_node") == 0 then return false end - local can_place = false - if (def_above.liquidtype == "source") then - can_place = true - elseif (def_above.liquidtype == "flowing") then - -- Check if bit 3 (downwards flowing) is set - can_place = (math.floor(node_above.param2 / 8) % 2) == 1 - if not can_place then - -- If not, also check node above (this is needed due a weird quirk in the definition of - -- "downwards flowing" liquids in Minetest) - local node_above_above = minetest.get_node({x=pos_above.x,y=pos_above.y+1,z=pos_above.z}) - local naa_def = minetest.registered_nodes[node_above_above.name] - can_place = naa_def.liquidtype == "source" - if not can_place then - can_place = (naa_def.liquidtype == "flowing") and ((math.floor(node_above_above.param2 / 8) % 2) == 1) - end - end + + local pos_bottom = pos_bottom or {x = pos.x, y = pos.y - 1, z = pos.z} + -- get_node_or_nil: Only fall if node below is loaded + local node_bottom = node_bottom or mt_get_node_or_nil(pos_bottom) + local nodename_bottom = node_bottom.name + local def_bottom = def_bottom or node_bottom and mt_registered_nodes[nodename_bottom] + if not def_bottom then + return false end - return can_place + + local same = nodename == nodename_bottom + -- Let leveled nodes fall if it can merge with the bottom node + if same and def_bottom.paramtype2 == "leveled" and + mt_get_node_level(pos_bottom) < + mt_get_node_max_level(pos_bottom) then + return true + end + + -- Otherwise only if the bottom node is considered "fall through" + if not same and + (not def_bottom.walkable or def_bottom.buildable_to) and + (mt_get_item_group(nodename, "float") == 0 or + def_bottom.liquidtype == "none") then + return true + end + + return false end -local function kelp_on_place(itemstack, placer, pointed_thing) + +-- Roll whether to grow kelp or not. +function kelp.roll_growth(numerator, denominator) + -- Optional params: numerator, denominator + return math_random(denominator or kelp.ROLL_GROWTH_DENOMINATOR) <= (numerator or kelp.ROLL_GROWTH_NUMERATOR) +end + + +-- Roll initial age for kelp. +function kelp.roll_init_age(min, max) + -- Optional params + return math_random(min or kelp.MIN_AGE, (max or kelp.MAX_AGE)-1) +end + + +-- Converts param2 to kelp height. +function kelp.get_height(param2) + return math_floor(param2 / 16) +end + + +-- Obtain pos and node of the tip of kelp. +function kelp.get_tip(pos, param2) + -- Optional params: param2 + local height = kelp.get_height(param2 or mt_get_node(pos).param2) + local pos_tip = {x=pos.x, y=pos.y, z=pos.z} + pos_tip.y = pos_tip.y + height + 1 + return pos_tip, mt_get_node(pos_tip), height +end + + +-- Obtain position of the first kelp unsubmerged. +function kelp.find_unsubmerged(pos, node, height) + -- Optional params: node, height + local node = node or mt_get_node(pos) + local height = height or kelp.get_height(node.param2) + + local walk_pos = {x=pos.x, z=pos.z} + local y = pos.y + for i=1,height do + walk_pos.y = y + i + local walk_node = mt_get_node(walk_pos) + if not kelp.is_submerged(walk_node) then + return walk_pos, walk_node, height, i + end + end + return nil, nil, height, height +end + + +-- Obtain next param2. +function kelp.next_param2(param2) + return param2+16 - param2 % 16 +end + + +-- Stores age from kelp.age_queue* into their respective meta +function kelp.store_meta() + local count = 0 + for _ in pairs(kelp.age_queue_pos) do + count = count + 1 + end + -- chatlog(string_format("Storing age metadata: %d in queue", #kelp.age_queue)) + -- chatlog(string_format("Storing age metadata: %d valid in queue", count)) + for i=1,#kelp.age_queue do + local pos_hash = kelp.age_queue[i] + local pos = kelp.age_queue_pos[pos_hash] + -- queued hashes may no longer point to a valid pos, e.g. kelp is destroyed. + if pos then + mt_get_meta(pos):set_int("mcl_ocean:kelp_age", kelp.age_pool[pos_hash]) + end + end + kelp.age_queue = {} + kelp.age_queue_pos = {} +end + + +-- Store and queue a kelp's age to be saved into meta later. +function kelp.store_age(age, pos, pos_hash) + -- Watched params: pos + -- Optional params: pos_hash + local pos_hash = pos_hash or mt_hash_node_position(pos) + + kelp.age_pool[pos_hash] = age + if not kelp.age_queue_pos[pos_hash] then + table_insert(kelp.age_queue, pos_hash) + kelp.age_queue_pos[pos_hash] = pos + return true, pos_hash + end + + return false, pos_hash +end + + +-- Initialise a kelp's age. +function kelp.init_age(pos, age, pos_hash, meta) + -- Watched params: pos + -- Optional params: age, pos_hash, meta + local pos_hash = pos_hash or mt_hash_node_position(pos) + local meta = meta or mt_get_meta(pos) + + local age = age + if age then + kelp.store_age(age, pos, pos_hash) + elseif not meta:contains("mcl_ocean:kelp_age") then + age = kelp.roll_init_age() + kelp.store_age(age, pos, pos_hash) + else + age = meta:get_int("mcl_ocean:kelp_age") + if not kelp.age_pool[pos_hash] then + kelp.age_pool[pos_hash] = age + end + end + + return age, pos_hash, meta +end + + +-- Initialise kelp nodetimer. +function kelp.init_timer(pos, pos_hash) + -- Optional params: pos_hash + local pos_hash = pos_hash or mt_hash_node_position(pos) + + local timer = kelp.timers_pool[pos_hash] + if not timer then + timer = mt_get_node_timer(pos) + kelp.timers_pool[pos_hash] = timer + end + if not timer:is_started() then + timer:start(kelp.TICK) + end + + return pos_hash +end + + +-- Apply next kelp height. +function kelp.next_height(pos, node, pos_tip, node_tip, submerged, downward_flowing) + -- Modified params: node + -- Optional params: node, set_node, pos_tip, node_tip, submerged, downward_flowing + local node = node or mt_get_node(pos) + local pos_tip = pos_tip + local node_tip = node_tip or (pos_tip and mt_get_node(pos_tip)) + if not pos_tip then + pos_tip,node_tip = kelp.get_tip(pos) + end + local downward_flowing = downward_flowing or + (submerged or kelp.is_submerged(node_tip) + and kelp.is_downward_flowing(pos_tip, node_tip)) + + -- Liquid source: Grow normally. + node.param2 = kelp.next_param2(node.param2) + mt_swap_node(pos, node) + + -- Flowing liquid: Grow 1 step, but also turn the tip node into a liquid source. + if downward_flowing then + local alt_liq = mt_registered_nodes[node_tip.name].liquid_alternative_source + if alt_liq then + mt_set_node(pos_tip, {name=alt_liq}) + end + end + + return node, pos_tip, node_tip, submerged, downward_flowing +end + + +-- Grow next kelp. +function kelp.next_grow(age, pos, node, pos_hash, pos_tip, node_tip, submerged, downward_flowing) + -- Watched params: pos + -- Modified params: node + -- Optional params: node, pos_hash, pos_tip, node_tip, submerged, downward_flowing + local node = node or mt_get_node(pos) + local pos_hash = pos_hash or mt_hash_node_position(pos) + local pos_tip = pos_tip + local node_tip = node_tip or (pos_tip and mt_get_node(pos_tip)) + if not pos_tip then + pos_tip,node_tip = kelp.get_tip(pos) + end + + -- New kelp must also be submerged in water. + local downward_flowing = downward_flowing or kelp.is_downward_flowing(pos_tip, node_tip) + if not (submerged or kelp.is_submerged(node_tip)) then + return + end + + kelp.next_height(pos, node, pos_tip, node_tip, submerged, downward_flowing) + + return kelp.store_age(age, pos, pos_hash), node, pos_hash, pos_tip, node_tip, submerged, downward_flowing +end + + +-- Drops the items for detached kelps. +function kelp.detach_drop(pos, param2) + -- Optional params: param2 + local height = kelp.get_height(param2 or mt_get_node(pos).param2) + local y = pos.y + local walk_pos = {x=pos.x, z=pos.z} + for i=1,height do + walk_pos.y = y+i + mt_add_item(walk_pos, "mcl_ocean:kelp") + end + return true +end + + +-- Detach the kelp at dig_pos, and drop their items. +-- Synonymous to digging the kelp. +-- NOTE: this is intended for whenever kelp truly becomes segmented plants +-- instead of rooted to the floor. Don't try to remove dig_pos. +function kelp.detach_dig(dig_pos, pos, node, drop) + -- Optional params: drop + + local param2 = node.param2 + -- pos.y points to the surface, offset needed to point to the first kelp. + local new_height = dig_pos.y - (pos.y+1) + + -- Digs the entire kelp. + if new_height <= 0 then + if drop then + kelp.detach_drop(dig_pos, param2) + end + mt_set_node(pos, { + name=mt_registered_nodes[node.name].node_dig_prediction, + param=node.param, + param2=0 }) + + -- Digs the kelp beginning at a height. + else + if drop then + kelp.detach_drop(dig_pos, param2 - new_height) + end + mt_swap_node(pos, {name=node.name, param=node.param, param2=16*new_height}) + end +end + + +-------------------------------------------------------------------------------- +-- Kelp callback functions +-------------------------------------------------------------------------------- + +function kelp.surface_on_dig(pos, node, digger) + kelp.detach_dig(pos, pos, node, true) +end + + +function kelp.surface_after_dig_node(pos, node) + return mt_set_node(pos, {name=registred_nodes[node.name].node_dig_prediction}) +end + + +function kelp.surface_on_timer(pos) + local node = mt_get_node(pos) + local pos_hash + + -- Update detahed kelps + local dig_pos = kelp.find_unsubmerged(pos, node) + if dig_pos then + pos_hash = mt_hash_node_position(pos) + mt_sound_play(mt_registered_nodes[node.name].sounds.dug, { gain = 0.5, pos = dig_pos }, true) + kelp.detach_dig(dig_pos, pos, node, true) + kelp.store_age(kelp.roll_init_age(), pos, pos_hash) + end + + -- Grow kelp on chance + if kelp.roll_growth() then + pos_hash = pos_hash or mt_hash_node_position(pos) + local age = kelp.age_pool[pos_hash] + if kelp.is_age_growable(age) then + kelp.next_grow(age+1, pos, node, pos_hash) + end + end + + return true +end + +function kelp.surface_on_construct(pos) + local pos_hash = mt_hash_node_position(pos) + kelp.init_age(pos, nil, pos_hash) + kelp.init_timer(pos, pos_hash) +end + + +function kelp.surface_on_destruct(pos) + local node = mt_get_node(pos) + local pos_hash = mt_hash_node_position(pos) + + -- on_falling callback. Activated by pistons for falling nodes too. + if kelp.is_falling(pos, node) then + kelp.detach_drop(pos, node.param2) + end + + -- Removes position from queue + kelp.age_queue_pos[pos_hash] = nil +end + + + +function kelp.surface_on_mvps_move(pos, node, oldpos, nodemeta) + -- Pistons moving falling nodes will have already activated on_falling callback. + kelp.detach_dig(pos, pos, node, mt_get_item_group(node.name, "falling_node") ~= 1) +end + + +-- NOTE: Old ABM implementation. +-- local function surface_unsubmerged_abm(pos, node) +-- local dig_pos = find_unsubmerged(pos, node) +-- if dig_pos then +-- detach_dig(dig_pos, pos, node, true) +-- end +-- return true +-- end + + +function kelp.kelp_on_place(itemstack, placer, pointed_thing) if pointed_thing.type ~= "node" or not placer then return itemstack end @@ -73,183 +496,251 @@ local function kelp_on_place(itemstack, placer, pointed_thing) local player_name = placer:get_player_name() local pos_under = pointed_thing.under local pos_above = pointed_thing.above - local node_under = minetest.get_node(pos_under) - local node_above = minetest.get_node(pos_above) - local def_under = minetest.registered_nodes[node_under.name] - local def_above = minetest.registered_nodes[node_above.name] + local node_under = mt_get_node(pos_under) + local nu_name = node_under.name + local def_under = mt_registered_nodes[nu_name] + -- Allow rightclick to override place. if def_under and def_under.on_rightclick and not placer:get_player_control().sneak then return def_under.on_rightclick(pos_under, node_under, placer, itemstack, pointed_thing) or itemstack end - if minetest.is_protected(pos_under, player_name) or - minetest.is_protected(pos_above, player_name) then - minetest.log("action", player_name + -- Protection + if mt_is_protected(pos_under, player_name) or + mt_is_protected(pos_above, player_name) then + mt_log("action", player_name .. " tried to place " .. itemstack:get_name() .. " at protected position " - .. minetest.pos_to_string(pos_under)) - minetest.record_protection_violation(pos_under, player_name) + .. mt_pos_to_string(pos_under)) + mt_record_protection_violation(pos_under, player_name) return itemstack end - local grow_kelp = false - -- Select a kelp node when placed on surface node - if node_under.name == "mcl_core:dirt" then - node_under.name = "mcl_ocean:kelp_dirt" - elseif node_under.name == "mcl_core:sand" then - node_under.name = "mcl_ocean:kelp_sand" - elseif node_under.name == "mcl_core:redsand" then - node_under.name = "mcl_ocean:kelp_redsand" - elseif node_under.name == "mcl_core:gravel" then - node_under.name = "mcl_ocean:kelp_gravel" - elseif minetest.get_item_group(node_under.name, "kelp") == 1 then - -- Place kelp on kelp = grow kelp by 1 node length - node_under.param2, grow_kelp = grow_param2_step(node_under.param2) - if not grow_kelp then - return itemstack - end - else + + local pos_tip, node_tip, def_tip, new_kelp + -- Kelp must also be placed on the top/tip side of the surface/kelp + if pos_under.y >= pos_above.y then return itemstack end - local submerged = false - if grow_kelp then - -- Kelp placed on kelp ... - -- Kelp can be placed on top of another kelp to make it grow - if pos_under.y >= pos_above.y or pos_under.x ~= pos_above.x or pos_under.z ~= pos_above.z then - -- Placed on side or below node, abort - return itemstack - end - -- New kelp top must also be submerged in water - local top_pos, top_node = get_kelp_top(pos_under, node_under) - local top_def = minetest.registered_nodes[top_node.name] - submerged = kelp_check_place(top_pos, top_node, top_def) - if not submerged then - -- Not submerged in water, abort - return itemstack - end + + -- When placed on kelp. + if mt_get_item_group(nu_name, "kelp") == 1 then + pos_tip,node_tip = kelp.get_tip(pos_under, node_under.param2) + def_tip = mt_registered_nodes[node_tip.name] + + -- When placed on surface. else - -- New kelp placed ... - if pos_under.y >= pos_above.y then - -- Placed on side or below node, abort + new_kelp = false + for _,surface in pairs(kelp.surfaces) do + if nu_name == surface.nodename then + node_under.name = "mcl_ocean:kelp_" ..surface.name + node_under.param2 = 0 + new_kelp = true + break + end + end + -- Surface must support kelp + if not new_kelp then return itemstack end - -- Kelp can be placed inside a water source or water flowing downwards on top of a surface node - local can_place = kelp_check_place(pos_above, node_above, def_above) - if not can_place then - return itemstack - end - node_under.param2 = minetest.registered_items[node_under.name].place_param2 or 16 + + pos_tip = pos_above + node_tip = mt_get_node(pos_above) + def_tip = mt_registered_nodes[node_tip.name] end - -- Place or grow kelp - local def_node = minetest.registered_items[node_under.name] + + -- New kelp must also be submerged in water. + local downward_flowing = kelp.is_downward_flowing(pos_tip, node_tip) + local submerged = kelp.is_submerged(node_tip) + if not submerged then + return itemstack + end + + -- Play sound, place surface/kelp and take away an item + local def_node = mt_registered_items[nu_name] if def_node.sounds then - minetest.sound_play(def_node.sounds.place, { gain = 0.5, pos = pos_under }, true) + mt_sound_play(def_node.sounds.place, { gain = 0.5, pos = pos_under }, true) end - minetest.set_node(pos_under, node_under) - if not minetest.is_creative_enabled(player_name) then + kelp.next_height(pos_under, node_under, pos_tip, node_tip, def_tip, submerged, downward_flowing) + if not mt_is_creative_enabled(player_name) then itemstack:take_item() end + -- Initialize age and timer when it's a new kelp + local pos_hash = mt_hash_node_position(pos_under) + if new_kelp then + kelp.init_age(pos_under, nil, pos_hash) + kelp.init_timer(pos_under, pos_hash) + else + kelp.store_age(kelp.roll_init_age(), pos_under, pos_hash) + end + return itemstack end -local get_kelp_height = function(param2) - return math.floor(param2 / 16) + +function kelp.lbm_register_nodetimer(pos, node) + local pos_hash = mt_hash_node_position(pos) + kelp.init_age(pos, nil, pos_hash) + kelp.init_timer(pos, pos_hash) end + +local gstep_time = 0 +function kelp.globalstep(dtime) + if #kelp.age_queue > kelp.MAX_AGE_QUEUE then + kelp.store_meta() + end + + gstep_time = gstep_time + dtime + if gstep_time < kelp.META_TICK then + return + end + gstep_time = 0 + + if #kelp.age_queue > 0 then + kelp.store_meta() + end +end + + +function kelp.on_shutdown() + if #kelp.age_queue > 0 then + kelp.store_meta() + end +end + +-------------------------------------------------------------------------------- +-- Kelp registration API +-------------------------------------------------------------------------------- + +-- List of supported surfaces for seagrass and kelp. +kelp.surfaces = { + { name="dirt", nodename="mcl_core:dirt", }, + { name="sand", nodename="mcl_core:sand", }, + { name="redsand", nodename="mcl_core:redsand", }, + { name="gravel", nodename="mcl_core:gravel", }, +} +kelp.registered_surfaces = {} + +-- Commented properties are the ones obtained using register_kelp_surface. +-- If you define your own properties, it overrides the default ones. +kelp.surface_deftemplate = { + drawtype = "plantlike_rooted", + paramtype = "light", + paramtype2 = "leveled", + place_param2 = 16, + --tiles = def.tiles, + special_tiles = { + { + image = "mcl_ocean_kelp_plant.png", + animation = {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}, + tileable_vertical = true, + } + }, + --inventory_image = "("..def.tiles[1]..")^mcl_ocean_kelp_item.png", + wield_image = "mcl_ocean_kelp_item.png", + selection_box = { + type = "fixed", + fixed = { + { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 }, + { -0.5, 0.5, -0.5, 0.5, 1.5, 0.5 }, + }, + }, + -- groups.falling_node = is_falling, + groups = { dig_immediate = 3, deco_block = 1, plant = 1, kelp = 1, }, + --sounds = sounds, + --node_dig_prediction = nodename, + on_construct = kelp.surface_on_construct, + on_destruct = kelp.surface_on_destruct, + on_dig = kelp.surface_on_dig, + after_dig_node = kelp.surface_after_dig_node, + on_timer = kelp.surface_on_timer, + mesecon = { on_mvps_move = kelp.surface_on_mvps_move, }, + drop = "", -- drops are handled in on_dig + --_mcl_falling_node_alternative = is_falling and nodename or nil, + _mcl_hardness = 0, + _mcl_blast_resistance = 0, +} + +-- Commented properties are the ones obtained using register_kelp_surface. +kelp.surface_docs = { + -- entry_id_orig = nodename, + _doc_items_entry_name = S("Kelp"), + _doc_items_longdesc = S("Kelp grows inside water on top of dirt, sand or gravel."), + --_doc_items_create_entry = doc_create, + _doc_items_image = "mcl_ocean_kelp_item.png", +} + +-- Creates new surfaces. +-- NOTE: surface_deftemplate will be modified in-place. +function kelp.register_kelp_surface(surface, surface_deftemplate, surface_docs) + local name = surface.name + local nodename = surface.nodename + local def = mt_registered_nodes[nodename] + local def_tiles = def.tiles + + local surfacename = "mcl_ocean:kelp_"..name + local surface_deftemplate = surface_deftemplate or kelp.surface_deftemplate -- Optional param + + local doc_create = surface.doc_create or false + local surface_docs = surface_docs or kelp.surface_docs -- Optional param + + if doc_create then + surface_deftemplate._doc_items_entry_name = surface_docs._doc_items_entry_name + surface_deftemplate._doc_items_longdesc = surface_docs._doc_items_longdesc + surface_deftemplate._doc_items_create_entry = true + surface_deftemplate._doc_items_image = surface_docs._doc_items_image + -- Sets the first surface as the docs' entry ID + if not surface_docs.entry_id_orig then + surface_docs.entry_id_orig = nodename + end + elseif mod_doc then + doc.add_entry_alias("nodes", surface_docs.entry_id_orig, "nodes", surfacename) + end + + local sounds = table_copy(def.sounds) + sounds.dig = kelp.leaf_sounds.dig + sounds.dug = kelp.leaf_sounds.dug + sounds.place = kelp.leaf_sounds.place + + surface_deftemplate.tiles = surface_deftemplate.tiles or def_tiles + surface_deftemplate.inventory_image = surface_deftemplate.inventory_image or "("..def_tiles[1]..")^mcl_ocean_kelp_item.png" + surface_deftemplate.sounds = surface_deftemplate.sound or sounds + local falling_node = mt_get_item_group(nodename, "falling_node") + surface_deftemplate.node_dig_prediction = surface_deftemplate.node_dig_prediction or nodename + surface_deftemplate.groups.falling_node = surface_deftemplate.groups.falling_node or falling_node + surface_deftemplate._mcl_falling_node_alternative = surface_deftemplate._mcl_falling_node_alternative or (falling_node and nodename or nil) + + minetest.register_node(surfacename, surface_deftemplate) +end + +-- Kelp surfaces nodes --------------------------------------------------------- + +-- Dirt must be registered first, for the docs +kelp.register_kelp_surface(kelp.surfaces[1], table_copy(kelp.surface_deftemplate), kelp.surface_docs) +for i=2, #kelp.surfaces do + kelp.register_kelp_surface(kelp.surfaces[i], table_copy(kelp.surface_deftemplate), kelp.surface_docs) +end + +-- Kelp item ------------------------------------------------------------------- + minetest.register_craftitem("mcl_ocean:kelp", { description = S("Kelp"), _tt_help = S("Grows in water on dirt, sand, gravel"), _doc_items_create_entry = false, inventory_image = "mcl_ocean_kelp_item.png", wield_image = "mcl_ocean_kelp_item.png", - on_place = kelp_on_place, + on_place = kelp.kelp_on_place, groups = { deco_block = 1 }, }) --- Kelp nodes: kelp on a surface node - -for s=1, #surfaces do - local def = minetest.registered_nodes[surfaces[s][2]] - local alt - if surfaces[s][3] == 1 then - alt = surfaces[s][2] - end - local sounds = table.copy(def.sounds) - local leaf_sounds = mcl_sounds.node_sound_leaves_defaults() - sounds.dig = leaf_sounds.dig - sounds.dug = leaf_sounds.dug - sounds.place = leaf_sounds.place - local tt_help, doc_longdesc, doc_img, desc - if surfaces[s][1] == "dirt" then - doc_longdesc = S("Kelp grows inside water on top of dirt, sand or gravel.") - desc = S("Kelp") - doc_create = true - doc_img = "mcl_ocean_kelp_item.png" - else - doc_create = false - end - minetest.register_node("mcl_ocean:kelp_"..surfaces[s][1], { - _doc_items_entry_name = desc, - _doc_items_longdesc = doc_longdesc, - _doc_items_create_entry = doc_create, - _doc_items_image = doc_img, - drawtype = "plantlike_rooted", - paramtype = "light", - paramtype2 = "leveled", - place_param2 = 16, - tiles = def.tiles, - special_tiles = { - { - image = "mcl_ocean_kelp_plant.png", - animation = {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}, - tileable_vertical = true, - } - }, - inventory_image = "("..def.tiles[1]..")^mcl_ocean_kelp_item.png", - wield_image = "mcl_ocean_kelp_item.png", - selection_box = { - type = "fixed", - fixed = { - { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 }, - { -0.5, 0.5, -0.5, 0.5, 1.5, 0.5 }, - }, - }, - groups = { dig_immediate = 3, deco_block = 1, plant = 1, kelp = 1, falling_node = surfaces[s][3] }, - sounds = sounds, - node_dig_prediction = surfaces[s][2], - after_dig_node = function(pos) - minetest.set_node(pos, {name=surfaces[s][2]}) - end, - on_dig = function(pos, node, digger) - -- Drop kelp as item; item count depends on height - local dname = "" - if digger then - dname = digger:get_player_name() - end - local creative = minetest.is_creative_enabled(dname) - if not creative then - minetest.add_item({x=pos.x, y=pos.y+1, z=pos.z}, "mcl_ocean:kelp "..get_kelp_height(node.param2)) - end - minetest.node_dig(pos, node, digger) - end, - drop = "", -- drops are handled in on_dig - _mcl_falling_node_alternative = alt, - _mcl_hardness = 0, - _mcl_blast_resistance = 0, - }) - - if mod_doc and surfaces[s][1] ~= "dirt" then - doc.add_entry_alias("nodes", "mcl_ocean:kelp_dirt", "nodes", "mcl_ocean:kelp_"..surfaces[s][1]) - end -end - if mod_doc then - doc.add_entry_alias("nodes", "mcl_ocean:kelp_dirt", "craftitems", "mcl_ocean:kelp") + doc.add_entry_alias("nodes", kelp.surface_docs.entry_id_orig, "craftitems", "mcl_ocean:kelp") end --- Dried kelp stuff +-- Dried kelp ------------------------------------------------------------------ -- TODO: This is supposed to be eaten very fast minetest.register_craftitem("mcl_ocean:dried_kelp", { @@ -264,13 +755,13 @@ minetest.register_craftitem("mcl_ocean:dried_kelp", { _mcl_saturation = 0.6, }) + local mod_screwdriver = minetest.get_modpath("screwdriver") ~= nil local on_rotate if mod_screwdriver then on_rotate = screwdriver.rotate_3way end - minetest.register_node("mcl_ocean:dried_kelp_block", { description = S("Dried Kelp Block"), _doc_items_longdesc = S("A decorative block that serves as a great furnace fuel."), @@ -310,32 +801,35 @@ minetest.register_craft({ burntime = 200, }) --- Grow kelp -minetest.register_abm({ - label = "Kelp growth", +-- Global registration ------------------------------------------------------------------------ + +minetest.register_lbm({ + label = "Kelp initialise", + name = "mcl_ocean:kelp_init", nodenames = { "group:kelp" }, - interval = 45, - chance = 12, - catch_up = false, - action = function(pos, node, active_object_count, active_object_count_wider) - local grown - -- Grow kelp by 1 node length if it would grow inside water - node.param2, grown = grow_param2_step(node.param2, true) - local top, top_node = get_kelp_top(pos, node) - local submerged = get_submerged(top_node) - if grown then - if submerged == "source" then - -- Liquid source: Grow normally - minetest.set_node(pos, node) - elseif submerged == "flowing" then - -- Flowing liquid: Grow 1 step, but also turn the top node into a liquid source - minetest.set_node(pos, node) - local def_liq = minetest.registered_nodes[top_node.name] - local alt_liq = def_liq and def_liq.liquid_alternative_source - if alt_liq then - minetest.set_node(top, {name=alt_liq}) - end - end - end - end, + run_at_every_load = true, -- so old kelps are also initialised + action = kelp.lbm_register_nodetimer, }) + + +minetest.register_globalstep(kelp.globalstep) +minetest.register_on_shutdown(kelp.on_shutdown) + +-- NOTE: Old ABM implementation. +-- minetest.register_abm({ +-- label = "Kelp drops", +-- nodenames = { "group:kelp" }, +-- interval = 1.0, +-- chance = 1, +-- catch_up = false, +-- action = surface_unsubmerged_abm, +-- }) +-- +-- minetest.register_abm({ +-- label = "Kelp growth", +-- nodenames = { "group:kelp" }, +-- interval = 45, +-- chance = 12, +-- catch_up = false, +-- action = grow_abm, +-- }) diff --git a/mods/ITEMS/mcl_portals/portal_end.lua b/mods/ITEMS/mcl_portals/portal_end.lua index 0bc0ce57e..ab09c5966 100644 --- a/mods/ITEMS/mcl_portals/portal_end.lua +++ b/mods/ITEMS/mcl_portals/portal_end.lua @@ -4,11 +4,6 @@ local S = minetest.get_translator("mcl_portals") local SPAWN_MIN = mcl_vars.mg_end_min+70 local SPAWN_MAX = mcl_vars.mg_end_min+98 -local PORTAL_ALPHA = 192 -if minetest.features.use_texture_alpha_string_modes then - PORTAL_ALPHA = nil -end - local mg_name = minetest.get_mapgen_setting("mg_name") local destroy_portal = function(pos) @@ -81,7 +76,6 @@ minetest.register_node("mcl_portals:portal_end", { -- This is 15 in MC. light_source = 14, post_effect_color = {a = 192, r = 0, g = 0, b = 0}, - alpha = PORTAL_ALPHA, after_destruct = destroy_portal, -- This prevents “falling through” collision_box = { diff --git a/mods/ITEMS/mcl_portals/portal_nether.lua b/mods/ITEMS/mcl_portals/portal_nether.lua index e842edf81..50a3bde39 100644 --- a/mods/ITEMS/mcl_portals/portal_nether.lua +++ b/mods/ITEMS/mcl_portals/portal_nether.lua @@ -30,7 +30,6 @@ local N_Y_MIN, N_Y_MAX = mcl_vars.mg_bedrock_nether_bottom_min, mcl_vars.mg_be local O_DY, N_DY = O_Y_MAX - O_Y_MIN + 1, N_Y_MAX - N_Y_MIN + 1 -- Alpha and particles -local ALPHA = minetest.features.use_texture_alpha_string_modes and 192 local node_particles_allowed = minetest.settings:get("mcl_node_particles") or "none" local node_particles_levels = { none=0, low=1, medium=2, high=3 } local PARTICLES = node_particles_levels[node_particles_allowed] @@ -263,7 +262,6 @@ minetest.register_node(PORTAL, { drop = "", light_source = 11, post_effect_color = {a = 180, r = 51, g = 7, b = 89}, - alpha = ALPHA, node_box = { type = "fixed", fixed = { diff --git a/mods/ITEMS/mcl_throwing/API.md b/mods/ITEMS/mcl_throwing/API.md index f2b1c7374..41a47223a 100644 --- a/mods/ITEMS/mcl_throwing/API.md +++ b/mods/ITEMS/mcl_throwing/API.md @@ -33,3 +33,9 @@ Handle creative mode, and throw params. * entity_name: the name of the entity to throw * velocity: (optional) velocity overide (can be nil) + +## mcl_throwing.get_staticdata(self) +Must be used in entity def if you want the entity to be saved after unloading mapblock. + +## mcl_throwing.on_activate(self, staticdata, dtime_s) +Must be used in entity def if you want the entity to be saved after unloading mapblock. diff --git a/mods/ITEMS/mcl_throwing/init.lua b/mods/ITEMS/mcl_throwing/init.lua index 4d6dcfe5c..09a34c12f 100644 --- a/mods/ITEMS/mcl_throwing/init.lua +++ b/mods/ITEMS/mcl_throwing/init.lua @@ -58,7 +58,7 @@ function mcl_throwing.dispense_function(stack, dispenserpos, droppos, dropnode, end -- Staticdata handling because objects may want to be reloaded -local get_staticdata = function(self) +function mcl_throwing.get_staticdata(self) local thrower -- Only save thrower if it's a player name if type(self._thrower) == "string" then @@ -71,7 +71,7 @@ local get_staticdata = function(self) return minetest.serialize(data) end -local on_activate = function(self, staticdata, dtime_s) +function mcl_throwing.on_activate(self, staticdata, dtime_s) local data = minetest.deserialize(staticdata) if data then self._lastpos = data._lastpos diff --git a/mods/ITEMS/mcl_throwing/register.lua b/mods/ITEMS/mcl_throwing/register.lua index 027ff4e93..8ef1c73bf 100644 --- a/mods/ITEMS/mcl_throwing/register.lua +++ b/mods/ITEMS/mcl_throwing/register.lua @@ -9,8 +9,8 @@ local snowball_ENTITY={ collisionbox = {0,0,0,0,0,0}, pointable = false, - get_staticdata = get_staticdata, - on_activate = on_activate, + get_staticdata = mcl_throwing.get_staticdata, + on_activate = mcl_throwing.on_activate, _thrower = nil, _lastpos={}, @@ -23,8 +23,8 @@ local egg_ENTITY={ collisionbox = {0,0,0,0,0,0}, pointable = false, - get_staticdata = get_staticdata, - on_activate = on_activate, + get_staticdata = mcl_throwing.get_staticdata, + on_activate = mcl_throwing.on_activate, _thrower = nil, _lastpos={}, @@ -38,8 +38,8 @@ local pearl_ENTITY={ collisionbox = {0,0,0,0,0,0}, pointable = false, - get_staticdata = get_staticdata, - on_activate = on_activate, + get_staticdata = mcl_throwing.get_staticdata, + on_activate = mcl_throwing.on_activate, _lastpos={}, _thrower = nil, -- Player ObjectRef of the player who threw the ender pearl diff --git a/mods/PLAYER/mcl_player/init.lua b/mods/PLAYER/mcl_player/init.lua index 9e6790ea0..210e2d19f 100644 --- a/mods/PLAYER/mcl_player/init.lua +++ b/mods/PLAYER/mcl_player/init.lua @@ -178,7 +178,7 @@ minetest.register_globalstep(function(dtime) -- Apply animations based on what the player is doing if player:get_hp() == 0 then - player_set_animation(player, "lay") + player_set_animation(player, "die") elseif walking and velocity.x > 0.35 or walking and velocity.x < -0.35 or walking and velocity.z > 0.35 or walking and velocity.z < -0.35 then if player_sneak[name] ~= controls.sneak then player_anim[name] = nil @@ -253,3 +253,28 @@ minetest.register_on_player_hpchange(function(player, hp_change, reason) end return hp_change end, true) + +minetest.register_on_respawnplayer(function(player) + local pos = player:get_pos() + minetest.add_particlespawner({ + amount = 50, + time = 0.001, + minpos = vector.add(pos, 0), + maxpos = vector.add(pos, 0), + minvel = vector.new(-5,-5,-5), + maxvel = vector.new(5,5,5), + minexptime = 1.1, + maxexptime = 1.5, + minsize = 1, + maxsize = 2, + collisiondetection = false, + vertical = false, + texture = "mcl_particles_mob_death.png^[colorize:#000000:255", + }) + + minetest.sound_play("mcl_mobs_mob_poof", { + pos = pos, + gain = 1.0, + max_hear_distance = 8, + }, true) +end) diff --git a/mods/PLAYER/mcl_skins/init.lua b/mods/PLAYER/mcl_skins/init.lua index 0ecb4a85a..5956aab7c 100644 --- a/mods/PLAYER/mcl_skins/init.lua +++ b/mods/PLAYER/mcl_skins/init.lua @@ -227,6 +227,9 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if mcl_skins.skin_count <= 6 then -- Change skin immediately if there are not many skins mcl_skins.cycle_skin(player) + if player:get_attach() ~= nil then + mcl_player.player_set_animation(player, "sit") + end else -- Show skin selection formspec otherwise mcl_skins.show_formspec(player:get_player_name()) @@ -294,4 +297,3 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end) minetest.log("action", "[mcl_skins] Mod initialized with "..mcl_skins.skin_count.." custom skin(s)") -