diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1b5098a4f..4c9bf3e38 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -52,17 +52,17 @@ Each mod must provide `mod.conf`. Each mod which add API functions should store functions inside a global table named like the mod. Public functions should not use self references but rather just access the table directly. Functions should be defined in this way: -``` +```lua function mcl_xyz.stuff(param) end ``` Insteed of this way: -``` +```lua mcl_xyz.stuff = function(param) end ``` Indentation must be unified, more likely with tabs. Time sensitive mods should make a local copy of most used API functions to improve performances. -``` +```lua local vector = vector local get_node = minetest.get_node ``` diff --git a/mods/ENTITIES/mcl_boats/init.lua b/mods/ENTITIES/mcl_boats/init.lua index 76ace7a45..311b07882 100644 --- a/mods/ENTITIES/mcl_boats/init.lua +++ b/mods/ENTITIES/mcl_boats/init.lua @@ -84,7 +84,7 @@ local function attach_object(self, obj) end end, name) obj:set_look_horizontal(yaw) - mcl_tmp_message.message(obj, S("Sneak to dismount")) + mcl_title.set(obj, "actionbar", {text=S("Sneak to dismount"), color="white", stay=60}) else obj:get_luaentity()._old_visual_size = visual_size end diff --git a/mods/ENTITIES/mcl_boats/locale/mcl_boats.fr.tr b/mods/ENTITIES/mcl_boats/locale/mcl_boats.fr.tr index 04d6d9da9..785d50146 100644 --- a/mods/ENTITIES/mcl_boats/locale/mcl_boats.fr.tr +++ b/mods/ENTITIES/mcl_boats/locale/mcl_boats.fr.tr @@ -6,6 +6,7 @@ Boats are used to travel on the surface of water.=Les bateaux sont utilisés pou Dark Oak Boat=Bateau en Chêne Noir Jungle Boat=Bateau en Acajou Oak Boat=Bateau en Chêne -Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Rightclick the boat again to leave it, punch the boat to make it drop as an item.=Faites un clic droit sur une source d'eau pour placer le bateau. Faites un clic droit sur le bateau pour y entrer. Utilisez [Gauche] et [Droite] pour diriger, [Avant] pour accélérer et [Arrière] pour ralentir ou reculer. Cliquez de nouveau avec le bouton droit sur le bateau pour le quitter, frappez le bateau pour le faire tomber en tant qu'objet. +Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Faites un clic droit sur une source d'eau pour placer le bateau. Faites un clic droit sur le bateau pour y entrer. Utilisez [Gauche] et [Droite] pour diriger, [Avant] pour accélérer et [Arrière] pour ralentir ou reculer. Utilisez [Sneak] pour le quitter, frappez le bateau pour le faire tomber en tant qu'objet. Spruce Boat=Bateau en Sapin -Water vehicle=Véhicule aquatique \ No newline at end of file +Water vehicle=Véhicule aquatique +Sneak to dismount= \ No newline at end of file diff --git a/mods/ENTITIES/mcl_boats/mod.conf b/mods/ENTITIES/mcl_boats/mod.conf index a5d6cc8cb..61463b6ec 100644 --- a/mods/ENTITIES/mcl_boats/mod.conf +++ b/mods/ENTITIES/mcl_boats/mod.conf @@ -1,7 +1,7 @@ name = mcl_boats author = PilzAdam description = Adds drivable boats. -depends = mcl_player, flowlib +depends = mcl_player, flowlib, mcl_title optional_depends = mcl_core, doc_identifier diff --git a/mods/ENTITIES/mcl_burning/api.lua b/mods/ENTITIES/mcl_burning/api.lua index 4cb19cca1..969985205 100644 --- a/mods/ENTITIES/mcl_burning/api.lua +++ b/mods/ENTITIES/mcl_burning/api.lua @@ -67,14 +67,9 @@ function mcl_burning.set_on_fire(obj, burn_time) end if not storage.burn_time or burn_time >= storage.burn_time then - if obj:is_player() and not storage.fire_hud_id then - storage.fire_hud_id = obj:hud_add({ - hud_elem_type = "image", - position = {x = 0.5, y = 0.5}, - scale = {x = -100, y = -100}, - text = "mcl_burning_entity_flame_animated.png^[opacity:180^[verticalframe:" .. mcl_burning.animation_frames .. ":" .. 1, - z_index = 1000, - }) + if obj:is_player() then + mcl_burning.channels[obj]:send_all(tostring(mcl_burning.animation_frames)) + mcl_burning.channels[obj]:send_all("start") end storage.burn_time = burn_time storage.fire_damage_timer = 0 @@ -95,7 +90,6 @@ function mcl_burning.set_on_fire(obj, burn_time) fire_entity:set_properties({visual_size = size}) fire_entity:set_attach(obj, "", offset, {x = 0, y = 0, z = 0}) local fire_luaentity = fire_entity:get_luaentity() - fire_luaentity:update_frame(obj, storage) for _, other in pairs(minetest.get_objects_inside_radius(fire_entity:get_pos(), 0)) do local other_luaentity = other:get_luaentity() @@ -111,9 +105,7 @@ function mcl_burning.extinguish(obj) if mcl_burning.is_burning(obj) then local storage = mcl_burning.get_storage(obj) if obj:is_player() then - if storage.fire_hud_id then - obj:hud_remove(storage.fire_hud_id) - end + mcl_burning.channels[obj]:send_all("stop") mcl_burning.storage[obj] = {} else storage.burn_time = nil @@ -143,4 +135,4 @@ function mcl_burning.tick(obj, dtime, storage) end end end -end \ No newline at end of file +end diff --git a/mods/ENTITIES/mcl_burning/init.lua b/mods/ENTITIES/mcl_burning/init.lua index 34b7ca2d4..313e75dca 100644 --- a/mods/ENTITIES/mcl_burning/init.lua +++ b/mods/ENTITIES/mcl_burning/init.lua @@ -7,6 +7,7 @@ local get_item_group = minetest.get_item_group mcl_burning = { storage = {}, + channels = {}, animation_frames = tonumber(minetest.settings:get("fire_animation_frames")) or 8 } @@ -54,12 +55,11 @@ minetest.register_on_joinplayer(function(player) end mcl_burning.storage[player] = storage + mcl_burning.channels[player] = minetest.mod_channel_join("mcl_burning:" .. player:get_player_name()) end) minetest.register_on_leaveplayer(function(player) - local storage = mcl_burning.storage[player] - storage.fire_hud_id = nil - player:get_meta():set_string("mcl_burning:data", minetest.serialize(storage)) + player:get_meta():set_string("mcl_burning:data", minetest.serialize(mcl_burning.storage[player])) mcl_burning.storage[player] = nil end) @@ -68,27 +68,28 @@ minetest.register_entity("mcl_burning:fire", { initial_properties = { physical = false, collisionbox = {0, 0, 0, 0, 0, 0}, - visual = "cube", + visual = "upright_sprite", + textures = { + name = "mcl_burning_entity_flame_animated.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 1.0, + }, + }, + spritediv = {x = 1, y = mcl_burning.animation_frames}, pointable = false, glow = -1, backface_culling = false, }, animation_frame = 0, animation_timer = 0, - on_step = function(self, dtime) - local parent, storage = self:sanity_check() - - if parent then - self.animation_timer = self.animation_timer + dtime - if self.animation_timer >= 0.1 then - self.animation_timer = 0 - self.animation_frame = self.animation_frame + 1 - if self.animation_frame > mcl_burning.animation_frames - 1 then - self.animation_frame = 0 - end - self:update_frame(parent, storage) - end - else + on_activate = function(self) + self.object:set_sprite({x = 0, y = 0}, mcl_burning.animation_frames, 1.0 / mcl_burning.animation_frames) + end, + on_step = function(self) + if not self:sanity_check() then self.object:remove() end end, @@ -96,23 +97,15 @@ minetest.register_entity("mcl_burning:fire", { local parent = self.object:get_attach() if not parent then - return + return false end local storage = mcl_burning.get_storage(parent) if not storage or not storage.burn_time then - return + return false end - return parent, storage - end, - update_frame = function(self, parent, storage) - local frame_overlay = "^[opacity:180^[verticalframe:" .. mcl_burning.animation_frames .. ":" .. self.animation_frame - local fire_texture = "mcl_burning_entity_flame_animated.png" .. frame_overlay - self.object:set_properties({textures = {"blank.png", "blank.png", fire_texture, fire_texture, fire_texture, fire_texture}}) - if parent:is_player() then - parent:hud_change(storage.fire_hud_id, "text", "mcl_burning_hud_flame_animated.png" .. frame_overlay) - end + return true end, }) diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index ab1ac5752..cfd141f04 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -480,7 +480,7 @@ minetest.register_entity(":__builtin:item", { end, get_staticdata = function(self) - return minetest.serialize({ + local data = minetest.serialize({ itemstring = self.itemstring, always_collect = self.always_collect, age = self.age, @@ -488,6 +488,39 @@ minetest.register_entity(":__builtin:item", { _flowing = self._flowing, _removed = self._removed, }) + -- sfan5 guessed that the biggest serializable item + -- entity would have a size of 65530 bytes. This has + -- been experimentally verified to be still too large. + -- + -- anon5 has calculated that the biggest serializable + -- item entity has a size of exactly 65487 bytes: + -- + -- 1. serializeString16 can handle max. 65535 bytes. + -- 2. The following engine metadata is always saved: + -- • 1 byte (version) + -- • 2 byte (length prefix) + -- • 14 byte “__builtin:item” + -- • 4 byte (length prefix) + -- • 2 byte (health) + -- • 3 × 4 byte = 12 byte (position) + -- • 4 byte (yaw) + -- • 1 byte (version 2) + -- • 2 × 4 byte = 8 byte (pitch and roll) + -- 3. This leaves 65487 bytes for the serialization. + if #data > 65487 then -- would crash the engine + local stack = ItemStack(self.itemstring) + stack:get_meta():from_table(nil) + self.itemstring = stack:to_string() + minetest.log( + "warning", + "Overlong item entity metadata removed: “" .. + self.itemstring .. + "” had serialized length of " .. + #data + ) + return self:get_staticdata() + end + return data end, on_activate = function(self, staticdata, dtime_s) @@ -575,7 +608,7 @@ minetest.register_entity(":__builtin:item", { return true end, - on_step = function(self, dtime) + on_step = function(self, dtime, moveresult) if self._removed then self.object:set_properties({ physical = false @@ -642,6 +675,18 @@ minetest.register_entity(":__builtin:item", { end end + -- Destroy item when it collides with a cactus + if moveresult and moveresult.collides then + for _, collision in pairs(moveresult.collisions) do + local pos = collision.node_pos + if collision.type == "node" and minetest.get_node(pos).name == "mcl_core:cactus" then + self._removed = true + self.object:remove() + return + end + end + end + -- Push item out when stuck inside solid opaque node if def and def.walkable and def.groups and def.groups.opaque == 1 then local shootdir diff --git a/mods/ENTITIES/mcl_minecarts/init.lua b/mods/ENTITIES/mcl_minecarts/init.lua index e33e120a1..4d3873cc2 100644 --- a/mods/ENTITIES/mcl_minecarts/init.lua +++ b/mods/ENTITIES/mcl_minecarts/init.lua @@ -646,7 +646,7 @@ register_minecart( if player then mcl_player.player_set_animation(player, "sit" , 30) player:set_eye_offset({x=0, y=-5.5, z=0},{x=0, y=-4, z=0}) - mcl_tmp_message.message(clicker, S("Sneak to dismount")) + mcl_title.set(clicker, "actionbar", {text=S("Sneak to dismount"), color="white", stay=60}) end end, name) end diff --git a/mods/ENTITIES/mcl_minecarts/locale/mcl_minecarts.fr.tr b/mods/ENTITIES/mcl_minecarts/locale/mcl_minecarts.fr.tr index 39cdfd013..67ed5eb1b 100644 --- a/mods/ENTITIES/mcl_minecarts/locale/mcl_minecarts.fr.tr +++ b/mods/ENTITIES/mcl_minecarts/locale/mcl_minecarts.fr.tr @@ -33,3 +33,4 @@ Activates minecarts when powered=Active les wagonnets lorsqu'il est alimenté Emits redstone power when a minecart is detected=Émet de l'énergie redstone lorsqu'un wagonnet est détecté Vehicle for fast travel on rails=Véhicule pour voyager rapidement sur rails Can be ignited by tools or powered activator rail=Peut être allumé par des outils ou un rail d'activation motorisé +Sneak to dismount= \ No newline at end of file diff --git a/mods/ENTITIES/mcl_minecarts/mod.conf b/mods/ENTITIES/mcl_minecarts/mod.conf index 9fff9175d..3b8ae5551 100644 --- a/mods/ENTITIES/mcl_minecarts/mod.conf +++ b/mods/ENTITIES/mcl_minecarts/mod.conf @@ -1,6 +1,6 @@ name = mcl_minecarts author = Krock description = Minecarts are vehicles to move players quickly on rails. -depends = mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons +depends = mcl_title, mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons optional_depends = doc_identifier, mcl_wip diff --git a/mods/ENTITIES/mobs_mc/locale/template.txt b/mods/ENTITIES/mobs_mc/locale/template.txt index 04ba9e465..7b55c1b89 100644 --- a/mods/ENTITIES/mobs_mc/locale/template.txt +++ b/mods/ENTITIES/mobs_mc/locale/template.txt @@ -28,6 +28,7 @@ Pig= Polar Bear= Rabbit= Killer Bunny= +The Killer Bunny= Sheep= Shulker= Silverfish= diff --git a/mods/ENTITIES/mobs_mc/rabbit.lua b/mods/ENTITIES/mobs_mc/rabbit.lua index 8c2675954..51235a3f9 100644 --- a/mods/ENTITIES/mobs_mc/rabbit.lua +++ b/mods/ENTITIES/mobs_mc/rabbit.lua @@ -233,4 +233,4 @@ mobs:spawn(spawn_grass) mobs:register_egg("mobs_mc:rabbit", S("Rabbit"), "mobs_mc_spawn_icon_rabbit.png", 0) -- Note: This spawn egg does not exist in Minecraft -mobs:register_egg("mobs_mc:killer_bunny", S("Killer Bunny"), "mobs_mc_spawn_icon_rabbit.png^[colorize:#FF0000:192", 0) -- TODO: Update inventory image +mobs:register_egg("mobs_mc:killer_bunny", S("Killer Bunny"), "mobs_mc_spawn_icon_rabbit_caerbannog.png", 0) diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_rabbit_caerbannog.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_rabbit_caerbannog.png new file mode 100644 index 000000000..4244a83c6 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_rabbit_caerbannog.png differ diff --git a/mods/HELP/doc/doc_items/locale/doc_items.fr.tr b/mods/HELP/doc/doc_items/locale/doc_items.fr.tr index 5d655404d..824ceeeba 100644 --- a/mods/HELP/doc/doc_items/locale/doc_items.fr.tr +++ b/mods/HELP/doc/doc_items/locale/doc_items.fr.tr @@ -2,7 +2,7 @@ Using it as fuel turns it into: @1.=L'utiliser comme combustible le transforme en : @1. @1 seconds=@1 secondes # Item count times item name -%@1×@2=%@1×@ +@1×@2=@1×@ # Itemname (25%) @1 (@2%)=@1 (@2%) # Itemname (<0.5%) diff --git a/mods/HELP/mcl_item_id/API.md b/mods/HELP/mcl_item_id/API.md new file mode 100644 index 000000000..a2f244e0c --- /dev/null +++ b/mods/HELP/mcl_item_id/API.md @@ -0,0 +1,24 @@ +# mcl_item_id +Show the item ID of an item in the description. +With this API, you can register a different name space than "mineclone" for your mod. + +## mcl_item_id.set_mod_namespace(modname, namespace) +Set a name space for all items in a mod. + +* param1: the modname +* param2: (optional) string of the desired name space, if nil, it is the name of the mod + +## mcl_item_id.get_mod_namespace(modname) +Get the name space of a mod registered with mcl_item_id.set_mod_namespace(modname, namespace). + +* param1: the modname + +### Examples: + +The name of the mod is "mod" which registered an item called "mod:itemname". + +* mcl_item_id.set_mod_namespace("mod", "mymod") will show "mymod:itemname" in the description of "mod:itemname" +* mcl_item_id.set_mod_namespace(minetest.get_current_modname()) will show "mod:itemname" in the description of "mod:itemname" +* mcl_item_id.get_mod_namespace(minetest.get_current_modname()) will return "mod" + +(If no namespace is set by a mod, mcl_item_id.get_mod_namespace(minetest.get_current_modname()) will return "mineclone") diff --git a/mods/HELP/mcl_item_id/init.lua b/mods/HELP/mcl_item_id/init.lua new file mode 100644 index 000000000..f3e6d2735 --- /dev/null +++ b/mods/HELP/mcl_item_id/init.lua @@ -0,0 +1,62 @@ +mcl_item_id = { + mod_namespaces = {}, +} + +local game = "mineclone" + +function mcl_item_id.set_mod_namespace(modname, namespace) + local namespace = namespace or modname + mcl_item_id.mod_namespaces[modname] = namespace +end + +function mcl_item_id.get_mod_namespace(modname) + local namespace = mcl_item_id.mod_namespaces[modname] + if namespace then + return namespace + else + return game + end +end + +local same_id = { + enchanting = { "table" }, + experience = { "bottle" }, + heads = { "skeleton", "zombie", "creeper", "wither_skeleton" }, + mobitems = { "rabbit", "chicken" }, + walls = { + "andesite", "brick", "cobble", "diorite", "endbricks", + "granite", "mossycobble", "netherbrick", "prismarine", + "rednetherbrick", "redsandstone", "sandstone", + "stonebrick", "stonebrickmossy", + }, + wool = { + "black", "blue", "brown", "cyan", "green", + "grey", "light_blue", "lime", "magenta", "orange", + "pink", "purple", "red", "silver", "white", "yellow", + }, +} + +tt.register_snippet(function(itemstring) + local def = minetest.registered_items[itemstring] + local item_split = itemstring:find(":") + local id_string = itemstring:sub(item_split) + local id_modname = itemstring:sub(1, item_split - 1) + local new_id = game .. id_string + local mod_namespace = mcl_item_id.get_mod_namespace(id_modname) + for mod, ids in pairs(same_id) do + for _, id in pairs(ids) do + if itemstring == "mcl_" .. mod .. ":" .. id then + new_id = game .. ":" .. id .. "_" .. mod:gsub("s", "") + end + end + end + if mod_namespace ~= game then + new_id = mod_namespace .. id_string + end + if mod_namespace ~= id_modname then + minetest.register_alias_force(new_id, itemstring) + end + if minetest.settings:get_bool("mcl_item_id_debug", false) then + return new_id, "#555555" + end +end) \ No newline at end of file diff --git a/mods/HELP/mcl_item_id/mod.conf b/mods/HELP/mcl_item_id/mod.conf new file mode 100644 index 000000000..c45e17fd3 --- /dev/null +++ b/mods/HELP/mcl_item_id/mod.conf @@ -0,0 +1,3 @@ +name = mcl_item_id +author = NO11 +depends = tt \ No newline at end of file diff --git a/mods/HELP/mcl_tt/locale/mcl_tt.de.tr b/mods/HELP/mcl_tt/locale/mcl_tt.de.tr index 8f878afc7..54c376c3b 100644 --- a/mods/HELP/mcl_tt/locale/mcl_tt.de.tr +++ b/mods/HELP/mcl_tt/locale/mcl_tt.de.tr @@ -45,3 +45,4 @@ Mining durability: @1=Grabehaltbarkeit: @1 Block breaking strength: @1=Blockbruchstärke: @1 @1 uses=@1 Verwendungen Unlimited uses=Unbegrenzte Verwendungen +Durability: @1=Haltbarkeit: @1 diff --git a/mods/HELP/mcl_tt/locale/template.txt b/mods/HELP/mcl_tt/locale/template.txt index 1259216c7..6fb735b13 100644 --- a/mods/HELP/mcl_tt/locale/template.txt +++ b/mods/HELP/mcl_tt/locale/template.txt @@ -45,3 +45,4 @@ Mining durability: @1= Block breaking strength: @1= @1 uses= Unlimited uses= +Durability: @1= diff --git a/mods/HELP/mcl_tt/snippets_mcl.lua b/mods/HELP/mcl_tt/snippets_mcl.lua index 3c79f52e8..825776f5f 100644 --- a/mods/HELP/mcl_tt/snippets_mcl.lua +++ b/mods/HELP/mcl_tt/snippets_mcl.lua @@ -107,3 +107,8 @@ tt.register_snippet(function(itemstring) end end) +tt.register_snippet(function(itemstring, _, itemstack) + if itemstring:sub(1, 23) == "mcl_fishing:fishing_rod" or itemstring:sub(1, 12) == "mcl_bows:bow" then + return S("Durability: @1", S("@1 uses", mcl_util.calculate_durability(itemstack or ItemStack(itemstring)))) + end +end) diff --git a/mods/HUD/hudbars/init.lua b/mods/HUD/hudbars/init.lua index 08f1914ca..505ff403b 100644 --- a/mods/HUD/hudbars/init.lua +++ b/mods/HUD/hudbars/init.lua @@ -425,6 +425,7 @@ function hb.hide_hudbar(player, identifier) local name = player:get_player_name() local hudtable = hb.get_hudtable(identifier) if hudtable == nil then return false end + if hudtable.hudstate[name].hidden == true then return true end if hb.settings.bar_type == "progress_bar" then if hudtable.hudids[name].icon then player:hud_change(hudtable.hudids[name].icon, "scale", {x=0,y=0}) @@ -443,6 +444,7 @@ function hb.unhide_hudbar(player, identifier) local name = player:get_player_name() local hudtable = hb.get_hudtable(identifier) if hudtable == nil then return false end + if hudtable.hudstate[name].hidden == false then return true end local value = hudtable.hudstate[name].value local max = hudtable.hudstate[name].max if hb.settings.bar_type == "progress_bar" then diff --git a/mods/HUD/mcl_credits/locale/mcl_credits.de.tr b/mods/HUD/mcl_credits/locale/mcl_credits.de.tr index 6a38d18e6..fa26f5bc4 100644 --- a/mods/HUD/mcl_credits/locale/mcl_credits.de.tr +++ b/mods/HUD/mcl_credits/locale/mcl_credits.de.tr @@ -7,6 +7,7 @@ Creator of MineClone2=Schöpfer von MineClone2 Developers=Entwickler Jump to speed up (additionally sprint)=Springen, um zu beschleunigen (zusätzlich sprinten) Maintainers=Betreuer +MineClone5=MineClone5 Original Mod Authors=Original-Mod-Autoren Sneak to skip=Schleichen zum Überspringen Textures=Texturen diff --git a/mods/HUD/mcl_credits/locale/mcl_credits.es.tr b/mods/HUD/mcl_credits/locale/mcl_credits.es.tr new file mode 100644 index 000000000..a8886286e --- /dev/null +++ b/mods/HUD/mcl_credits/locale/mcl_credits.es.tr @@ -0,0 +1,14 @@ +# textdomain: mcl_credits +3D Models= +A faithful Open Source clone of Minecraft= +Contributors= +Creator of MineClone= +Creator of MineClone2= +Developers= +Jump to speed up (additionally sprint)= +Maintainers= +MineClone5= +Original Mod Authors= +Sneak to skip= +Textures= +Translations= \ No newline at end of file diff --git a/mods/HUD/mcl_credits/locale/mcl_credits.fr.tr b/mods/HUD/mcl_credits/locale/mcl_credits.fr.tr new file mode 100644 index 000000000..b34249eff --- /dev/null +++ b/mods/HUD/mcl_credits/locale/mcl_credits.fr.tr @@ -0,0 +1,14 @@ +# textdomain: mcl_credits +3D Models=Modèles 3D +A faithful Open Source clone of Minecraft=Un clone open source de Minecraft +Contributors=Contributeurs +Creator of MineClone=Créateur de MineClone +Creator of MineClone2=Créateur de MineClone2 +Developers=Développeurs +Jump to speed up (additionally sprint)=Saut pour accélérer (peut être combiné avec sprint) +Maintainers=Mainteneurs +MineClone5=MineClone5 +Original Mod Authors=Auteurs des mods originaux +Sneak to skip=Shift pour passer +Textures=Textures +Translations=Traductions \ No newline at end of file diff --git a/mods/HUD/mcl_credits/locale/mcl_credits.pl.tr b/mods/HUD/mcl_credits/locale/mcl_credits.pl.tr new file mode 100644 index 000000000..a8886286e --- /dev/null +++ b/mods/HUD/mcl_credits/locale/mcl_credits.pl.tr @@ -0,0 +1,14 @@ +# textdomain: mcl_credits +3D Models= +A faithful Open Source clone of Minecraft= +Contributors= +Creator of MineClone= +Creator of MineClone2= +Developers= +Jump to speed up (additionally sprint)= +Maintainers= +MineClone5= +Original Mod Authors= +Sneak to skip= +Textures= +Translations= \ No newline at end of file diff --git a/mods/HUD/mcl_credits/locale/mcl_credits.ru.tr b/mods/HUD/mcl_credits/locale/mcl_credits.ru.tr new file mode 100644 index 000000000..a8886286e --- /dev/null +++ b/mods/HUD/mcl_credits/locale/mcl_credits.ru.tr @@ -0,0 +1,14 @@ +# textdomain: mcl_credits +3D Models= +A faithful Open Source clone of Minecraft= +Contributors= +Creator of MineClone= +Creator of MineClone2= +Developers= +Jump to speed up (additionally sprint)= +Maintainers= +MineClone5= +Original Mod Authors= +Sneak to skip= +Textures= +Translations= \ No newline at end of file diff --git a/mods/HUD/mcl_title/API.md b/mods/HUD/mcl_title/API.md new file mode 100644 index 000000000..37f1c279f --- /dev/null +++ b/mods/HUD/mcl_title/API.md @@ -0,0 +1,50 @@ +# mcl_title + +Allow mods to show messages in the hud of players. + +## mcl_title.set(player, type, data) + +Show a hud message of `type` to player `player` with `data` as params. + +The element will stay for the per-player param `stay` or `data.stay` (in gametick which is 1/20 second). + +Here is a usage exemple: + +```lua +--show a title in the HUD with minecraft color "gold" +mcl_title.set(player, "title", {text="dummy text", color="gold"}) + +--show a subtitle in the HUD with hex color "#612D2D" +mcl_title.set(player, "subtitle", {text="dummy subtitle", color="#612D2D"}) + +--show an actionbar in the HUD (above the hotbar) with minecraft color "red" +mcl_title.set(player, "subtitle", {text="dummy actionbar", color="red"}) + +--show a title in the HUD with minecraft color "gold" staying for 3 seconds (override stay setting) +mcl_title.set(player, "title", {text="dummy text", color="gold", stay=60}) +``` + +## mcl_title.remove(player, type) + +Hide HUD element of type `type` for player `player`. + +## mcl_title.clear(player) + +Remove every title/subtitle/actionbar from a player. +Basicaly run `mcl_title.remove(player, type)` for every type. + +## mcl_title.params_set(player, params) + +Allow mods to set `stay` and upcomming `fadeIn`/`fadeOut` params. + +```lua +mcl_title.params_set(player, {stay = 600}) --elements with no 'data.stay' field will stay during 30s (600/20) +``` + +## mcl_title.params_get(player) + +Get `stay` and upcomming `fadeIn` and `fadeOut` params of a player as a table. + +```lua +mcl_title.params_get(player) +``` \ No newline at end of file diff --git a/mods/HUD/mcl_title/init.lua b/mods/HUD/mcl_title/init.lua new file mode 100644 index 000000000..2ea1571c8 --- /dev/null +++ b/mods/HUD/mcl_title/init.lua @@ -0,0 +1,236 @@ +--Based on: +--https://www.digminecraft.com/game_commands/title_command.php +--https://youtu.be/oVrtQRO2hpY + +--TODO: use SSCSM to reduce lag and network trafic (just send modchannel messages) +--TODO: fadeIn and fadeOut animation (needs engine change: SSCSM or native support) +--TODO: allow obfuscating text (needs engine change: SSCSM or native support) +--TODO: allow colorizing and styling of part of the text (NEEDS ENGINE CHANGE!!!) +--TODO: exactly mc like layout + +--Note that the table storing timeouts use playername as index insteed of player objects (faster) +--This is intended in order to speedup the process of removing HUD elements the the timeout is up + +local huds_idx = {} + +local hud_hide_timeouts = {} + +hud_hide_timeouts.title = {} +hud_hide_timeouts.subtitle = {} +hud_hide_timeouts.actionbar = {} + +huds_idx.title = {} +huds_idx.subtitle = {} +huds_idx.actionbar = {} + +mcl_title = {} +mcl_title.defaults = {fadein = 10, stay = 70, fadeout = 20} +mcl_title.layout = {} +mcl_title.layout.title = {position = {x = 0.5, y = 0.5}, alignment = {x = 0, y = -1.3}, size = 7} +mcl_title.layout.subtitle = {position = {x = 0.5, y = 0.5}, alignment = {x = 0, y = 1.7}, size = 4} +mcl_title.layout.actionbar = {position = {x = 0.5, y = 1}, alignment = {x = 0, y = 0}, size = 1} + +local get_color = mcl_util.get_color + +--local string = string +local pairs = pairs + +local function gametick_to_secondes(gametick) + if gametick then + return gametick / 20 + else + return nil + end +end + +--https://github.com/minetest/minetest/blob/b3b075ea02034306256b486dd45410aa765f035a/doc/lua_api.txt#L8477 +--[[ +local function style_to_bits(bold, italic) + if bold then + if italic then + return 3 + else + return 1 + end + else + if italic then + return 2 + else + return 0 + end + end +end +]] + +--PARAMS SYSTEM +local player_params = {} + +minetest.register_on_joinplayer(function(player) + --local playername = player:get_player_name() + player_params[player] = { + stay = mcl_title.defaults.stay, + --fadeIn = mcl_title.defaults.fadein, + --fadeOut = mcl_title.defaults.fadeout, + } + local _, hex_color = get_color("white") + huds_idx.title[player] = player:hud_add({ + hud_elem_type = "text", + position = mcl_title.layout.title.position, + alignment = mcl_title.layout.title.alignment, + text = "", + --style = 0, + size = {x = mcl_title.layout.title.size}, + number = hex_color, + z_index = 100, + }) + huds_idx.subtitle[player] = player:hud_add({ + hud_elem_type = "text", + position = mcl_title.layout.subtitle.position, + alignment = mcl_title.layout.subtitle.alignment, + text = "", + --style = 0, + size = {x = mcl_title.layout.subtitle.size}, + number = hex_color, + z_index = 100, + }) + huds_idx.actionbar[player] = player:hud_add({ + hud_elem_type = "text", + position = mcl_title.layout.actionbar.position, + offset = {x = 0, y = -210}, + alignment = mcl_title.layout.actionbar.alignment, + --style = 0, + text = "", + size = {x = mcl_title.layout.actionbar.size}, + number = hex_color, + z_index = 100, + }) +end) + +minetest.register_on_leaveplayer(function(player) + local playername = player:get_player_name() + + --remove player params from the list + player_params[player] = nil + + --remove HUD idx from the list (HUD elements are removed by the engine) + huds_idx.title[player] = nil + huds_idx.subtitle[player] = nil + huds_idx.actionbar[player] = nil + + --remove timers from list + hud_hide_timeouts.title[playername] = nil + hud_hide_timeouts.subtitle[playername] = nil + hud_hide_timeouts.actionbar[playername] = nil +end) + +function mcl_title.params_set(player, data) + player_params[player] = { + stay = data.stay or mcl_title.defaults.stay, + --fadeIn = data.fadeIn or mcl_title.defaults.fadein, + --fadeOut = data.fadeOut or mcl_title.defaults.fadeout, + } +end + +function mcl_title.params_get(player) + return player_params[player] +end + +--API FUNCTIONS + +function mcl_title.set(player, type, data) + if not data.color then + data.color = "white" + end + local _, hex_color = get_color(data.color) + if not hex_color then + return false + end + + player:hud_change(huds_idx[type][player], "text", data.text) + player:hud_change(huds_idx[type][player], "number", hex_color) + + --apply bold and italic + --player:hud_change(huds_idx[type][player], "style", style_to_bits(data.bold, data.italic)) + + hud_hide_timeouts[type][player:get_player_name()] = gametick_to_secondes(data.stay) or gametick_to_secondes(mcl_title.params_get(player).stay) + return true +end + +function mcl_title.remove(player, type) + if player then + player:hud_change(huds_idx[type][player], "text", "") + --player:hud_change(huds_idx[type][player], "style", 0) --no styling + end +end + +function mcl_title.clear(player) + mcl_title.remove(player, "title") + mcl_title.remove(player, "subtitle") + mcl_title.remove(player, "actionbar") +end + +minetest.register_on_dieplayer(function(player) + mcl_title.clear(player) +end) + +minetest.register_globalstep(function(dtime) + local new_timeouts = { + title = {}, + subtitle = {}, + actionbar = {}, + } + for element, content in pairs(hud_hide_timeouts) do + for name, timeout in pairs(content) do + timeout = timeout - dtime + if timeout <= 0 then + local player = minetest.get_player_by_name(name) + mcl_title.remove(player, element) + else + new_timeouts[element][name] = timeout + end + end + end + hud_hide_timeouts = new_timeouts +end) + + +--DEBUG STUFF!! +--[[ +minetest.register_chatcommand("title", { + func = function(name, param) + local player = minetest.get_player_by_name(name) + mcl_title.set(player, "title", {text=param, color="gold", bold=true, italic=true}) + end, +}) + +minetest.register_chatcommand("subtitle", { + func = function(name, param) + local player = minetest.get_player_by_name(name) + mcl_title.set(player, "subtitle", {text=param, color="gold"}) + end, +}) + +minetest.register_chatcommand("actionbar", { + func = function(name, param) + local player = minetest.get_player_by_name(name) + mcl_title.set(player, "actionbar", {text=param, color="gold"}) + end, +}) + +minetest.register_chatcommand("timeout", { + func = function(name, param) + local player = minetest.get_player_by_name(name) + mcl_title.params_set(player, {stay = 600}) + end, +}) + +minetest.register_chatcommand("all", { + func = function(name, param) + local player = minetest.get_player_by_name(name) + mcl_title.params_set(player, {stay = 600}) + mcl_title.set(player, "title", {text=param, color="gold"}) + mcl_title.set(player, "subtitle", {text=param, color="gold"}) + mcl_title.set(player, "actionbar", {text=param, color="gold"}) + end, +}) +]] \ No newline at end of file diff --git a/mods/HUD/mcl_title/mod.conf b/mods/HUD/mcl_title/mod.conf new file mode 100644 index 000000000..0f29a8118 --- /dev/null +++ b/mods/HUD/mcl_title/mod.conf @@ -0,0 +1,4 @@ +name = mcl_title +description = Add an API to add in HUD title +depends = mcl_colors +author = AFCMS \ No newline at end of file diff --git a/mods/HUD/mcl_tmp_message/API.md b/mods/HUD/mcl_tmp_message/API.md deleted file mode 100644 index 0a3fc06a3..000000000 --- a/mods/HUD/mcl_tmp_message/API.md +++ /dev/null @@ -1,7 +0,0 @@ -# mcl_temp_message - -Allow mods to show short messages in the hud of players. - -## mcl_tmp_message.message(player, message) - -Show above the hotbar a hud message to player . \ No newline at end of file diff --git a/mods/HUD/mcl_tmp_message/init.lua b/mods/HUD/mcl_tmp_message/init.lua deleted file mode 100644 index 1456cd592..000000000 --- a/mods/HUD/mcl_tmp_message/init.lua +++ /dev/null @@ -1,44 +0,0 @@ -mcl_tmp_message = {} - -local huds = {} -local hud_hide_timeouts = {} - -function mcl_tmp_message.message(player, message) - local name = player:get_player_name() - player:hud_change(huds[name], "text", message) - hud_hide_timeouts[name] = 3 -end - -minetest.register_on_joinplayer(function(player) - huds[player:get_player_name()] = player:hud_add({ - hud_elem_type = "text", - position = {x=0.5, y=1}, - offset = {x = 0, y = -210}, - alignment = {x=0, y=0}, - number = 0xFFFFFF , - text = "", - z_index = 100, - }) -end) - -minetest.register_on_leaveplayer(function(player) - local name = player:get_player_name() - huds[name] = nil - hud_hide_timeouts[name] = nil -end) - -minetest.register_globalstep(function(dtime) - local new_timeouts = {} - for name, timeout in pairs(hud_hide_timeouts) do - timeout = timeout - dtime - if timeout <= 0 then - local player = minetest.get_player_by_name(name) - if player then - player:hud_change(huds[name], "text", "") - end - else - new_timeouts[name] = timeout - end - end - hud_hide_timeouts = new_timeouts -end) diff --git a/mods/HUD/mcl_tmp_message/mod.conf b/mods/HUD/mcl_tmp_message/mod.conf deleted file mode 100644 index ad453643e..000000000 --- a/mods/HUD/mcl_tmp_message/mod.conf +++ /dev/null @@ -1,3 +0,0 @@ -name = mcl_tmp_message -author = Fleckenstein -description = A simple API to show a temporary message to a player diff --git a/mods/ITEMS/REDSTONE/mcl_dispensers/init.lua b/mods/ITEMS/REDSTONE/mcl_dispensers/init.lua index 7c2c07393..82d53c806 100644 --- a/mods/ITEMS/REDSTONE/mcl_dispensers/init.lua +++ b/mods/ITEMS/REDSTONE/mcl_dispensers/init.lua @@ -168,6 +168,60 @@ local dispenserdef = { end inv:set_stack("main", stack_id, stack) + + -- Use shears on sheeps + elseif igroups.shears then + for _, obj in pairs(minetest.get_objects_inside_radius(droppos, 1)) do + local entity = obj:get_luaentity() + if entity and not entity.child and not entity.gotten then + local entname = entity.name + local pos = obj:get_pos() + local used, texture = false + if entname == "mobs_mc:sheep" then + minetest.add_item(pos, entity.drops[2].name .. " " .. math.random(1, 3)) + if not entity.color then + entity.color = "unicolor_white" + end + entity.base_texture = { "blank.png", "mobs_mc_sheep.png" } + texture = entity.base_texture + entity.drops = { + { name = mobs_mc.items.mutton_raw, chance = 1, min = 1, max = 2 }, + } + used = true + elseif entname == "mobs_mc:snowman" then + texture = { + "mobs_mc_snowman.png", + "blank.png", "blank.png", + "blank.png", "blank.png", + "blank.png", "blank.png", + } + used = true + elseif entname == "mobs_mc:mooshroom" then + local droppos = vector.offset(pos, 0, 1.4, 0) + if entity.base_texture[1] == "mobs_mc_mooshroom_brown.png" then + minetest.add_item(droppos, mobs_mc.items.mushroom_brown .. " 5") + else + minetest.add_item(droppos, mobs_mc.items.mushroom_red .. " 5") + end + local oldyaw = obj:get_yaw() + obj:remove() + local cow = minetest.add_entity(pos, "mobs_mc:cow") + cow:set_yaw(oldyaw) + obj = cow + entity = cow:get_luaentity() + used = true + end + if used then + obj:set_properties({ textures = texture }) + entity.gotten = true + minetest.sound_play("mcl_tools_shears_cut", { pos = pos }, true) + stack:add_wear(65535 / stackdef._mcl_diggroups.shearsy.uses) + inv:set_stack("main", stack_id, stack) + break + end + end + end + -- Spawn Egg elseif igroups.spawn_egg then -- Spawn mob diff --git a/mods/ITEMS/mcl_anvils/init.lua b/mods/ITEMS/mcl_anvils/init.lua index fbf6fb751..d3b32b844 100644 --- a/mods/ITEMS/mcl_anvils/init.lua +++ b/mods/ITEMS/mcl_anvils/init.lua @@ -53,6 +53,15 @@ local function get_consumed_materials(tool, material) return materials_used end +local function contains(table, value) + for _, i in pairs(table) do + if i == value then + return true + end + end + return false +end + -- Given 2 input stacks, tells you which is the tool and which is the material. -- Returns ("tool", input1, input2) if input1 is tool and input2 is material. -- Returns ("material", input2, input1) if input1 is material and input2 is tool. @@ -60,9 +69,15 @@ end local function distinguish_tool_and_material(input1, input2) local def1 = input1:get_definition() local def2 = input2:get_definition() - if def1.type == "tool" and def1._repair_material then + local r1 = def1._repair_material + local r2 = def2._repair_material + if def1.type == "tool" and r1 and type(r1) == "table" and contains(r1, input2) then return "tool", input1, input2 - elseif def2.type == "tool" and def2._repair_material then + elseif def2.type == "tool" and r2 and type(r2) == "table" and contains(r2, input1) then + return "material", input2, input1 + elseif def1.type == "tool" and r1 then + return "tool", input1, input2 + elseif def2.type == "tool" and r2 then return "material", input2, input1 else return nil @@ -121,11 +136,28 @@ local function update_anvil_slots(meta) local distinguished, tool, material = distinguish_tool_and_material(input1, input2) if distinguished then local tooldef = tool:get_definition() + local repair = tooldef._repair_material local has_correct_material = false - if string.sub(tooldef._repair_material, 1, 6) == "group:" then - has_correct_material = minetest.get_item_group(material:get_name(), string.sub(tooldef._repair_material, 7)) ~= 0 - elseif material:get_name() == tooldef._repair_material then - has_correct_material = true + local material_name = material:get_name() + if type(repair) == "string" then + if string.sub(repair, 1, 6) == "group:" then + has_correct_material = minetest.get_item_group(material_name, string.sub(repair, 7)) ~= 0 + elseif material_name == repair then + has_correct_material = true + end + else + if contains(repair, material_name) then + has_correct_material = true + else + for _, r in pairs(repair) do + if string.sub(r, 1, 6) == "group:" then + if minetest.get_item_group(material_name, string.sub(r, 7)) ~= 0 then + has_correct_material = true + end + + end + end + end end if has_correct_material and tool:get_wear() > 0 then local materials_used = get_consumed_materials(tool, material) @@ -284,6 +316,12 @@ local function damage_anvil_by_falling(pos, distance) end end +local anvilbox = { + type = "fixed", + fixed = { + { -8 / 16, -8 / 16, -6 / 16, 8 / 16, 8 / 16, 6 / 16 }, + }, +} local anvildef = { groups = {pickaxey=1, falling_node=1, falling_node_damage=1, crush_after_fall=1, deco_block=1, anvil=1}, tiles = {"mcl_anvils_anvil_top_damaged_0.png^[transformR90", "mcl_anvils_anvil_base.png", "mcl_anvils_anvil_side.png"}, @@ -297,11 +335,14 @@ local anvildef = { node_box = { type = "fixed", fixed = { - {-8/16, 2/16, -5/16, 8/16, 8/16, 5/16}, -- top - {-5/16, -4/16, -2/16, 5/16, 5/16, 2/16}, -- middle - {-8/16, -8/16, -5/16, 8/16, -4/16, 5/16}, -- base + { -6 / 16, -8 / 16, -6 / 16, 6 / 16, -4 / 16, 6 / 16 }, + { -5 / 16, -4 / 16, -4 / 16, 5 / 16, -3 / 16, 4 / 16 }, + { -4 / 16, -3 / 16, -2 / 16, 4 / 16, 2 / 16, 2 / 16 }, + { -8 / 16, 2 / 16, -5 / 16, 8 / 16, 8 / 16, 5 / 16 }, } }, + selection_box = anvilbox, + collision_box = anvilbox, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 1200, _mcl_hardness = 5, diff --git a/mods/ITEMS/mcl_anvils/textures/mcl_anvils_anvil_top_damaged_0.png b/mods/ITEMS/mcl_anvils/textures/mcl_anvils_anvil_top_damaged_0.png index 84c64e915..43938aa72 100644 Binary files a/mods/ITEMS/mcl_anvils/textures/mcl_anvils_anvil_top_damaged_0.png and b/mods/ITEMS/mcl_anvils/textures/mcl_anvils_anvil_top_damaged_0.png differ diff --git a/mods/ITEMS/mcl_anvils/textures/mcl_anvils_anvil_top_damaged_1.png b/mods/ITEMS/mcl_anvils/textures/mcl_anvils_anvil_top_damaged_1.png index 61c2ac6ab..e8cfbe5b7 100644 Binary files a/mods/ITEMS/mcl_anvils/textures/mcl_anvils_anvil_top_damaged_1.png and b/mods/ITEMS/mcl_anvils/textures/mcl_anvils_anvil_top_damaged_1.png differ diff --git a/mods/ITEMS/mcl_anvils/textures/mcl_anvils_anvil_top_damaged_2.png b/mods/ITEMS/mcl_anvils/textures/mcl_anvils_anvil_top_damaged_2.png index 5f5cfbffa..096f65eac 100644 Binary files a/mods/ITEMS/mcl_anvils/textures/mcl_anvils_anvil_top_damaged_2.png and b/mods/ITEMS/mcl_anvils/textures/mcl_anvils_anvil_top_damaged_2.png differ diff --git a/mods/ITEMS/mcl_armor/mod.conf b/mods/ITEMS/mcl_armor/mod.conf index 9264e8362..fad2e494c 100644 --- a/mods/ITEMS/mcl_armor/mod.conf +++ b/mods/ITEMS/mcl_armor/mod.conf @@ -1,5 +1,5 @@ name = mcl_armor author = stu description = Adds craftable armor that is visible to other players. -depends = mcl_core, mcl_player, mcl_enchanting +depends = mcl_core, mcl_player, mcl_enchanting, mcl_damage optional_depends = mcl_fire, ethereal, bakedclay diff --git a/mods/ITEMS/mcl_armor/textures/mcl_armor_inv_boots_gold.png b/mods/ITEMS/mcl_armor/textures/mcl_armor_inv_boots_gold.png index dc452d413..ef1f9fa87 100644 Binary files a/mods/ITEMS/mcl_armor/textures/mcl_armor_inv_boots_gold.png and b/mods/ITEMS/mcl_armor/textures/mcl_armor_inv_boots_gold.png differ diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index dc9afe2ba..e196f69ad 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -330,7 +330,7 @@ function mcl_beds.on_rightclick(pos, player, is_top) message = select(2, lay_down(player, ppos, other)) end if message then - mcl_tmp_message.message(player, message) + mcl_title.set(player, "actionbar", {text=message, color="white", stay=60}) end else lay_down(player, nil, nil, false) diff --git a/mods/ITEMS/mcl_brewing/mod.conf b/mods/ITEMS/mcl_brewing/mod.conf index 2c27c979e..0f6217f09 100644 --- a/mods/ITEMS/mcl_brewing/mod.conf +++ b/mods/ITEMS/mcl_brewing/mod.conf @@ -1,4 +1,4 @@ name = mcl_brewing author = bzoss depends = mcl_init, mcl_formspec, mcl_sounds, mcl_potions, mcl_mobitems -optional_depends = mcl_core, doc, screwdriver +optional_depends = mcl_core, doc, screwdriver, mesecons_mvps diff --git a/mods/ITEMS/mcl_buckets/API.md b/mods/ITEMS/mcl_buckets/API.md index 53f7d3698..94ec48de5 100644 --- a/mods/ITEMS/mcl_buckets/API.md +++ b/mods/ITEMS/mcl_buckets/API.md @@ -9,13 +9,46 @@ Accept folowing params: * string: name of the node to place * function(pos): will returns name of the node to place with pos being the placement position * source_take: table of liquid source node names to take -* itemname: itemstring of the new bucket item (or nil if liquid is not takeable) +* bucketname: itemstring of the new bucket item * inventory_image: texture of the new bucket item (ignored if itemname == nil) * name: user-visible bucket description * longdesc: long explanatory description (for help) * usagehelp: short usage explanation (for help) * tt_help: very short tooltip help -* extra_check(pos, placer): (optional) function(pos) which can returns false to avoid placing the liquid. Placer is object/player who is placing the liquid, can be nil. +* extra_check(pos, placer): (optional) function(pos) * groups: optional list of item groups -This function can be called from any mod (which depends on this one) \ No newline at end of file + +**Usage exemple:** +```lua +mcl_buckets.register_liquid({ + bucketname = "dummy:bucket_dummy", + --source_place = "dummy:dummy_source", + source_place = function(pos) + if condition then + return "dummy:dummy_source" + else + return "dummy:dummy_source_nether" + end + end, + source_take = {"dummy:dummy_source"}, + inventory_image = "bucket_dummy.png", + name = S("Dummy liquid Bucket"), + longdesc = S("This bucket is filled with a dummy liquid."), + usagehelp = S("Place it to empty the bucket and create a dummy liquid source."), + tt_help = S("Places a dummy liquid source"), + extra_check = function(pos, placer) + --pos = pos where the liquid should be placed + --placer people who tried to place the bucket (can be nil) + + --no liquid node will be placed + --the bucket will not be emptied + --return false, false + + --liquid node will be placed + --the bucket will be emptied + return true, true + end, + groups = { dummy_group = 123 }, +}) +``` \ No newline at end of file diff --git a/mods/ITEMS/mcl_buckets/README.txt b/mods/ITEMS/mcl_buckets/README.md similarity index 67% rename from mods/ITEMS/mcl_buckets/README.txt rename to mods/ITEMS/mcl_buckets/README.md index 06862d589..b783cc133 100644 --- a/mods/ITEMS/mcl_buckets/README.txt +++ b/mods/ITEMS/mcl_buckets/README.md @@ -1,9 +1,12 @@ -Bucket mod. -Originally taken from Minetest Game, adapted for MineClone 2. +# MineClone2 Bucket (`mcl_bucket`) +Originally taken from Minetest Game, adapted for MineClone2. + +This mod add buckets to the game, including an API to register your own (see `API.md`). + +## License -License of source code: ------------------------ Copyright (C) 2011-2012 Kahrl + Copyright (C) 2011-2012 celeron55, Perttu Ahola This program is free software; you can redistribute it and/or modify diff --git a/mods/ITEMS/mcl_buckets/init.lua b/mods/ITEMS/mcl_buckets/init.lua index 90ccec636..931214b95 100644 --- a/mods/ITEMS/mcl_buckets/init.lua +++ b/mods/ITEMS/mcl_buckets/init.lua @@ -3,6 +3,7 @@ local modname = minetest.get_current_modname() local S = minetest.get_translator(modname) local modpath = minetest.get_modpath(modname) +-- Compatibility with old bucket mod minetest.register_alias("bucket:bucket_empty", "mcl_buckets:bucket_empty") minetest.register_alias("bucket:bucket_water", "mcl_buckets:bucket_water") minetest.register_alias("bucket:bucket_lava", "mcl_buckets:bucket_lava") @@ -11,13 +12,24 @@ local mod_doc = minetest.get_modpath("doc") local mod_mcl_core = minetest.get_modpath("mcl_core") --local mod_mclx_core = minetest.get_modpath("mclx_core") +-- Localize some functions for faster access +local vector = vector +local math = math +local string = string + +local raycast = minetest.raycast +local get_node = minetest.get_node +local add_node = minetest.add_node +local add_item = minetest.add_item + + if mod_mcl_core then minetest.register_craft({ output = "mcl_buckets:bucket_empty 1", recipe = { {"mcl_core:iron_ingot", "", "mcl_core:iron_ingot"}, {"", "mcl_core:iron_ingot", ""}, - } + }, }) end @@ -25,147 +37,218 @@ mcl_buckets = {} mcl_buckets.liquids = {} -- Sound helper functions for placing and taking liquids -local sound_place = function(itemname, pos) +local function sound_place(itemname, pos) local def = minetest.registered_nodes[itemname] if def and def.sounds and def.sounds.place then minetest.sound_play(def.sounds.place, {gain=1.0, pos = pos, pitch = 1 + math.random(-10, 10)*0.005}, true) end end -local sound_take = function(itemname, pos) +local function sound_take(itemname, pos) local def = minetest.registered_nodes[itemname] if def and def.sounds and def.sounds.dug then minetest.sound_play(def.sounds.dug, {gain=1.0, pos = pos, pitch = 1 + math.random(-10, 10)*0.005}, true) end end -local place_liquid = function(pos, itemstring) +local function place_liquid(pos, itemstring) local fullness = minetest.registered_nodes[itemstring].liquid_range sound_place(itemstring, pos) minetest.add_node(pos, {name=itemstring, param2=fullness}) end +local function give_bucket(new_bucket, itemstack, user) + local inv = user:get_inventory() + if minetest.is_creative_enabled(user:get_player_name()) then + --TODO: is a full bucket added if inv doesn't contain one? + return itemstack + else + if itemstack:get_count() == 1 then + return new_bucket + else + if inv:room_for_item("main", new_bucket) then + inv:add_item("main", new_bucket) + else + add_item(user:get_pos(), new_bucket) + end + itemstack:take_item() + return itemstack + end + end +end + +local pointable_sources = {} + +local function bucket_raycast(user) + --local pos = user:get_pos() + local pos = user:get_pos() + --local pos = vector.add(user:get_pos(), user:get_bone_position("Head_Control")) + pos.y = pos.y + user:get_properties().eye_height + local look_dir = user:get_look_dir() + look_dir = vector.multiply(look_dir, 5) + local pos2 = vector.add(pos, look_dir) + + local ray = raycast(pos, pos2, false, true) + if ray then + for pointed_thing in ray do + if pointed_thing and pointable_sources[get_node(pointed_thing.above).name] then + --minetest.chat_send_all("found!") + return {under=pointed_thing.under,above=pointed_thing.above} + end + end + end + return nil +end + +local function get_node_place(source_place, place_pos) + local node_place + if type(source_place) == "function" then + node_place = source_place(place_pos) + else + node_place = source_place + end + return node_place +end + +local function get_extra_check(check, pos, user) + local result + local take_bucket + if check then + result, take_bucket = check(pos, user) + if result == nil then result = true end + if take_bucket == nil then take_bucket = true end + else + result = true + take_bucket = true + end + return result, take_bucket +end + +local function get_bucket_drop(itemstack, user, take_bucket) + -- Handle bucket item and inventory stuff + if take_bucket and not minetest.is_creative_enabled(user:get_player_name()) then + -- Add empty bucket and put it into inventory, if possible. + -- Drop empty bucket otherwise. + local new_bucket = ItemStack("mcl_buckets:bucket_empty") + if itemstack:get_count() == 1 then + return new_bucket + else + local inv = user:get_inventory() + if inv:room_for_item("main", new_bucket) then + inv:add_item("main", new_bucket) + else + add_item(user:get_pos(), new_bucket) + end + itemstack:take_item() + return itemstack + end + else + return itemstack + end +end + function mcl_buckets.register_liquid(def) - for i=1, #def.source_take do - mcl_buckets.liquids[def.source_take[i]] = { + for _,source in ipairs(def.source_take) do + mcl_buckets.liquids[source] = { source_place = def.source_place, - source_take = def.source_take[i], + source_take = source, on_take = def.on_take, - itemname = def.itemname, + bucketname = def.bucketname, } + pointable_sources[source] = true if type(def.source_place) == "string" then - mcl_buckets.liquids[def.source_place] = mcl_buckets.liquids[def.source_take[i]] + mcl_buckets.liquids[def.source_place] = mcl_buckets.liquids[source] end end - if def.itemname then - minetest.register_craftitem(def.itemname, { - description = def.name, - _doc_items_longdesc = def.longdesc, - _doc_items_usagehelp = def.usagehelp, - _tt_help = def.tt_help, - inventory_image = def.inventory_image, - stack_max = 1, - groups = def.groups, - on_place = function(itemstack, user, pointed_thing) - -- Must be pointing to node - if pointed_thing.type ~= "node" then - return - end + if def.bucketname == nil or def.bucketname == "" then + error(string.format("[mcl_bucket] Invalid itemname then registering [%s]!", def.name)) + end - local node = minetest.get_node(pointed_thing.under) - local place_pos = pointed_thing.under - local nn = node.name - local nodedef = minetest.registered_nodes[nn] - -- Call on_rightclick if the pointed node defines it - if user and not user:get_player_control().sneak then - if nodedef and nodedef.on_rightclick then - return nodedef.on_rightclick(place_pos, node, user, itemstack) or itemstack - end - end + minetest.register_craftitem(def.bucketname, { + description = def.name, + _doc_items_longdesc = def.longdesc, + _doc_items_usagehelp = def.usagehelp, + _tt_help = def.tt_help, + inventory_image = def.inventory_image, + stack_max = 1, + groups = def.groups, + on_place = function(itemstack, user, pointed_thing) + -- Must be pointing to node + if pointed_thing.type ~= "node" then + return + end + -- Call on_rightclick if the pointed node defines it + local new_stack = mcl_util.call_on_rightclick(itemstack, user, pointed_thing) + if new_stack then + return new_stack + end - local node_place - if type(def.source_place) == "function" then - node_place = def.source_place(place_pos) - else - node_place = def.source_place - end - -- Check if pointing to a buildable node - --local item = itemstack:get_name() + local undernode = get_node(pointed_thing.under) + local abovenode = get_node(pointed_thing.above) + local buildable1 = minetest.registered_nodes[undernode.name] and minetest.registered_nodes[undernode.name].buildable_to + local buildable2 = minetest.registered_nodes[abovenode.name] and minetest.registered_nodes[abovenode.name].buildable_to + if not buildable1 and not buildable2 then return itemstack end --if both nodes aren't buildable_to, skip - if def.extra_check and def.extra_check(place_pos, user) == true and nodedef and nodedef.buildable_to then - -- buildable; replace the node + if buildable1 then + local result, take_bucket = get_extra_check(def.extra_check, pointed_thing.under, user) + if result then + local node_place = get_node_place(def.source_place, pointed_thing.under) local pns = user:get_player_name() - if minetest.is_protected(place_pos, pns) then - minetest.record_protection_violation(place_pos, pns) + + -- Check protection + if minetest.is_protected(pointed_thing.under, pns) then + minetest.record_protection_violation(pointed_thing.under, pns) return itemstack end - place_liquid(place_pos, node_place) + + -- Place liquid + place_liquid(pointed_thing.under, node_place) + + -- Update doc mod if mod_doc and doc.entry_exists("nodes", node_place) then doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place) end - else - -- not buildable to; place the liquid above - -- check if the node above can be replaced - local abovenode = minetest.get_node(pointed_thing.above) - if minetest.registered_nodes[abovenode.name] and minetest.registered_nodes[abovenode.name].buildable_to then - local pn = user:get_player_name() - if minetest.is_protected(pointed_thing.above, pn) then - minetest.record_protection_violation(pointed_thing.above, pn) - return itemstack - end - place_liquid(pointed_thing.above, node_place) - if mod_doc and doc.entry_exists("nodes", node_place) then - doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place) - end - else - -- do not remove the bucket with the liquid - return - end end + return get_bucket_drop(itemstack, user, take_bucket) + elseif buildable2 then + local result, take_bucket = get_extra_check(def.extra_check, pointed_thing.above, user) + if result then + local node_place = get_node_place(def.source_place, pointed_thing.above) + local pns = user:get_player_name() - -- Handle bucket item and inventory stuff - if not minetest.is_creative_enabled(user:get_player_name()) then - -- Add empty bucket and put it into inventory, if possible. - -- Drop empty bucket otherwise. - local new_bucket = ItemStack("mcl_buckets:bucket_empty") - if itemstack:get_count() == 1 then - return new_bucket - else - local inv = user:get_inventory() - if inv:room_for_item("main", new_bucket) then - inv:add_item("main", new_bucket) - else - minetest.add_item(user:get_pos(), new_bucket) - end - itemstack:take_item() + -- Check protection + if minetest.is_protected(pointed_thing.above, pns) then + minetest.record_protection_violation(pointed_thing.above, pns) return itemstack end - else - return - end - end, - _on_dispense = function(stack, pos, droppos, dropnode, dropdir) - --local iname = stack:get_name() - local buildable = minetest.registered_nodes[dropnode.name].buildable_to or dropnode.name == "mcl_portals:portal" - --if def.extra_check and def.extra_check(droppos, nil) == false then - -- Fail placement of liquid - if def.extra_check and def.extra_check(droppos, nil) == true and buildable then - -- buildable; replace the node - local node_place - if type(def.source_place) == "function" then - node_place = def.source_place(droppos) - else - node_place = def.source_place + -- Place liquid + place_liquid(pointed_thing.above, node_place) + + -- Update doc mod + if mod_doc and doc.entry_exists("nodes", node_place) then + doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place) end - place_liquid(droppos, node_place) - stack:set_name("mcl_buckets:bucket_empty") end - return stack - end, - }) - end + return get_bucket_drop(itemstack, user, take_bucket) + else + return itemstack + end + end, + _on_dispense = function(stack, pos, droppos, dropnode, dropdir) + local buildable = minetest.registered_nodes[dropnode.name].buildable_to or dropnode.name == "mcl_portals:portal" + if not buildable then return stack end + local result, take_bucket = get_extra_check(def.extra_check, droppos, nil) + if result then -- Fail placement of liquid if result is false + place_liquid(droppos, get_node_place(def.source_place, droppos)) + end + if take_bucket then + stack:set_name("mcl_buckets:bucket_empty") + end + return stack + end, + }) end minetest.register_craftitem("mcl_buckets:bucket_empty", { @@ -173,8 +256,7 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", { _doc_items_longdesc = S("A bucket can be used to collect and release liquids."), _doc_items_usagehelp = S("Punch a liquid source to collect it. You can then use the filled bucket to place the liquid somewhere else."), _tt_help = S("Collects liquids"), - - liquids_pointable = true, + --liquids_pointable = true, inventory_image = "bucket.png", stack_max = 16, on_place = function(itemstack, user, pointed_thing) @@ -184,74 +266,70 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", { end -- Call on_rightclick if the pointed node defines it + local new_stack = mcl_util.call_on_rightclick(itemstack, user, pointed_thing) + if new_stack then + return new_stack + end + local node = minetest.get_node(pointed_thing.under) local nn = node.name - if user and not user:get_player_control().sneak then - if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].on_rightclick then - return minetest.registered_nodes[nn].on_rightclick(pointed_thing.under, node, user, itemstack) or itemstack - end - end - -- Can't steal liquids - if minetest.is_protected(pointed_thing.above, user:get_player_name()) then - minetest.record_protection_violation(pointed_thing.under, user:get_player_name()) - return itemstack - end - - -- Check if pointing to a liquid source - local liquiddef = mcl_buckets.liquids[nn] local new_bucket - if liquiddef and liquiddef.itemname and (nn == liquiddef.source_take) then - - -- Fill bucket, but not in Creative Mode - if not minetest.is_creative_enabled(user:get_player_name()) then - new_bucket = ItemStack({name = liquiddef.itemname}) - if liquiddef.on_take then - liquiddef.on_take(user) - end + local liquid_node = bucket_raycast(user) + if liquid_node then + if minetest.is_protected(liquid_node.above, user:get_player_name()) then + minetest.record_protection_violation(liquid_node.above, user:get_player_name()) end + local liquid_name = get_node(liquid_node.above).name + if liquid_name then + local liquid_def = mcl_buckets.liquids[liquid_name] + if liquid_def then + --minetest.chat_send_all("test") + -- Fill bucket, but not in Creative Mode + -- FIXME: remove this line + --if not minetest.is_creative_enabled(user:get_player_name()) then + if not false then + new_bucket = ItemStack({name = liquid_def.bucketname}) + if liquid_def.on_take then + liquid_def.on_take(user) + end + end + add_node(liquid_node.above, {name="air"}) + sound_take(nn, liquid_node.above) - minetest.add_node(pointed_thing.under, {name="air"}) - sound_take(nn, pointed_thing.under) - - if mod_doc and doc.entry_exists("nodes", nn) then - doc.mark_entry_as_revealed(user:get_player_name(), "nodes", nn) - end - - elseif nn == "mcl_cauldrons:cauldron_3" then - -- Take water out of full cauldron - minetest.set_node(pointed_thing.under, {name="mcl_cauldrons:cauldron"}) - if not minetest.is_creative_enabled(user:get_player_name()) then - new_bucket = ItemStack("mcl_buckets:bucket_water") - end - sound_take("mcl_core:water_source", pointed_thing.under) - elseif nn == "mcl_cauldrons:cauldron_3r" then - -- Take river water out of full cauldron - minetest.set_node(pointed_thing.under, {name="mcl_cauldrons:cauldron"}) - if not minetest.is_creative_enabled(user:get_player_name()) then - new_bucket = ItemStack("mcl_buckets:bucket_river_water") - end - sound_take("mclx_core:river_water_source", pointed_thing.under) - end - - -- Add liquid bucket and put it into inventory, if possible. - -- Drop new bucket otherwise. - if new_bucket then - if itemstack:get_count() == 1 then - return new_bucket - else - local inv = user:get_inventory() - if inv:room_for_item("main", new_bucket) then - inv:add_item("main", new_bucket) + if mod_doc and doc.entry_exists("nodes", liquid_name) then + doc.mark_entry_as_revealed(user:get_player_name(), "nodes", liquid_name) + end + if new_bucket then + return give_bucket(new_bucket, itemstack, user) + end else - minetest.add_item(user:get_pos(), new_bucket) + minetest.log("error", string.format("[mcl_buckets] Node [%s] has invalid group [_mcl_bucket_pointable]!", liquid_name)) end - if not minetest.is_creative_enabled(user:get_player_name()) then - itemstack:take_item() - end - return itemstack end - end + return itemstack + else + -- FIXME: replace this ugly code by cauldrons API + if nn == "mcl_cauldrons:cauldron_3" then + -- Take water out of full cauldron + minetest.set_node(pointed_thing.under, {name="mcl_cauldrons:cauldron"}) + if not minetest.is_creative_enabled(user:get_player_name()) then + new_bucket = ItemStack("mcl_buckets:bucket_water") + end + sound_take("mcl_core:water_source", pointed_thing.under) + elseif nn == "mcl_cauldrons:cauldron_3r" then + -- Take river water out of full cauldron + minetest.set_node(pointed_thing.under, {name="mcl_cauldrons:cauldron"}) + if not minetest.is_creative_enabled(user:get_player_name()) then + new_bucket = ItemStack("mcl_buckets:bucket_river_water") + end + sound_take("mclx_core:river_water_source", pointed_thing.under) + end + if new_bucket then + return give_bucket(new_bucket, itemstack, user) + end + end + return itemstack end, _on_dispense = function(stack, pos, droppos, dropnode, dropdir) -- Fill empty bucket with liquid or drop bucket if no liquid @@ -259,9 +337,9 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", { local liquiddef = mcl_buckets.liquids[dropnode.name] local new_bucket - if liquiddef and liquiddef.itemname and (dropnode.name == liquiddef.source_take) then + if liquiddef and liquiddef.bucketname and (dropnode.name == liquiddef.source_take) then -- Fill bucket - new_bucket = ItemStack({name = liquiddef.itemname}) + new_bucket = ItemStack({name = liquiddef.bucketname}) sound_take(dropnode.name, droppos) collect_liquid = true end diff --git a/mods/ITEMS/mcl_buckets/mod.conf b/mods/ITEMS/mcl_buckets/mod.conf index 5a78e70ad..0d7b764b8 100644 --- a/mods/ITEMS/mcl_buckets/mod.conf +++ b/mods/ITEMS/mcl_buckets/mod.conf @@ -1,6 +1,6 @@ name = mcl_buckets author = Kahrl description = -depends = mcl_worlds +depends = mcl_worlds, mcl_util optional_depends = mcl_core, mclx_core, doc diff --git a/mods/ITEMS/mcl_buckets/register.lua b/mods/ITEMS/mcl_buckets/register.lua index 863aa074c..1a7c8fe14 100644 --- a/mods/ITEMS/mcl_buckets/register.lua +++ b/mods/ITEMS/mcl_buckets/register.lua @@ -3,7 +3,7 @@ local mod_mcl_core = minetest.get_modpath("mcl_core") local mod_mclx_core = minetest.get_modpath("mclx_core") local has_awards = minetest.get_modpath("awards") -local sound_place = function(itemname, pos) +local function sound_place(itemname, pos) local def = minetest.registered_nodes[itemname] if def and def.sounds and def.sounds.place then minetest.sound_play(def.sounds.place, {gain=1.0, pos = pos, pitch = 1 + math.random(-10, 10)*0.005}, true) @@ -34,7 +34,7 @@ if mod_mcl_core then awards.unlock(user:get_player_name(), "mcl:hotStuff") end end, - itemname = "mcl_buckets:bucket_lava", + bucketname = "mcl_buckets:bucket_lava", inventory_image = "bucket_lava.png", name = S("Lava Bucket"), longdesc = S("A bucket can be used to collect and release liquids. This one is filled with hot lava, safely contained inside. Use with caution."), @@ -46,22 +46,13 @@ if mod_mcl_core then mcl_buckets.register_liquid({ source_place = "mcl_core:water_source", source_take = {"mcl_core:water_source"}, - itemname = "mcl_buckets:bucket_water", + bucketname = "mcl_buckets:bucket_water", inventory_image = "bucket_water.png", name = S("Water Bucket"), longdesc = S("A bucket can be used to collect and release liquids. This one is filled with water."), usagehelp = S("Place it to empty the bucket and create a water source."), tt_help = S("Places a water source"), extra_check = function(pos, placer) - -- Check protection - local placer_name = "" - if placer then - placer_name = placer:get_player_name() - end - if placer and minetest.is_protected(pos, placer_name) then - minetest.record_protection_violation(pos, placer_name) - return false - end local nn = minetest.get_node(pos).name -- Pour water into cauldron if minetest.get_item_group(nn, "cauldron") ~= 0 then @@ -70,13 +61,13 @@ if mod_mcl_core then minetest.set_node(pos, {name="mcl_cauldrons:cauldron_3"}) end sound_place("mcl_core:water_source", pos) - return false + return false, true -- Evaporate water if used in Nether (except on cauldron) else local dim = mcl_worlds.pos_to_dimension(pos) if dim == "nether" then minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true) - return false + return false, true end end end, @@ -89,22 +80,13 @@ if mod_mclx_core then mcl_buckets.register_liquid({ source_place = "mclx_core:river_water_source", source_take = {"mclx_core:river_water_source"}, - itemname = "mcl_buckets:bucket_river_water", + bucketname = "mcl_buckets:bucket_river_water", inventory_image = "bucket_river_water.png", name = S("River Water Bucket"), longdesc = S("A bucket can be used to collect and release liquids. This one is filled with river water."), usagehelp = S("Place it to empty the bucket and create a river water source."), tt_help = S("Places a river water source"), extra_check = function(pos, placer) - -- Check protection - local placer_name = "" - if placer then - placer_name = placer:get_player_name() - end - if placer and minetest.is_protected(pos, placer_name) then - minetest.record_protection_violation(pos, placer_name) - return false - end local nn = minetest.get_node(pos).name -- Pour into cauldron if minetest.get_item_group(nn, "cauldron") ~= 0 then @@ -113,13 +95,13 @@ if mod_mclx_core then minetest.set_node(pos, {name="mcl_cauldrons:cauldron_3r"}) end sound_place("mcl_core:water_source", pos) - return false + return false, true else -- Evaporate water if used in Nether (except on cauldron) local dim = mcl_worlds.pos_to_dimension(pos) if dim == "nether" then minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true) - return false + return false, true end end end, diff --git a/mods/ITEMS/mcl_chests/init.lua b/mods/ITEMS/mcl_chests/init.lua index cd66c3fc4..69f6a601d 100644 --- a/mods/ITEMS/mcl_chests/init.lua +++ b/mods/ITEMS/mcl_chests/init.lua @@ -1133,7 +1133,7 @@ for color, desc in pairs(boxtypes) do if mod_doc then if is_canonical then longdesc = S("A shulker box is a portable container which provides 27 inventory slots for any item except shulker boxes. Shulker boxes keep their inventory when broken, so shulker boxes as well as their contents can be taken as a single item. Shulker boxes come in many different colors.") - usagehelp = S("To access the inventory of a shulker box, place and right-click it. To take a shulker box and its contents with you, just break and collect it, the items will not fall out.") + usagehelp = S("To access the inventory of a shulker box, place and right-click it. To take a shulker box and its contents with you, just break and collect it, the items will not fall out. Place the shulker box again to be able to retrieve its contents.") entry_name = S("Shulker Box") else create_entry = false diff --git a/mods/ITEMS/mcl_chests/locale/template.txt b/mods/ITEMS/mcl_chests/locale/template.txt index 1d947184b..d680c24c9 100644 --- a/mods/ITEMS/mcl_chests/locale/template.txt +++ b/mods/ITEMS/mcl_chests/locale/template.txt @@ -24,7 +24,7 @@ Red Shulker Box= Grey Shulker Box= Black Shulker Box= A shulker box is a portable container which provides 27 inventory slots for any item except shulker boxes. Shulker boxes keep their inventory when broken, so shulker boxes as well as their contents can be taken as a single item. Shulker boxes come in many different colors.= -To access the inventory of a shulker box, place and right-click it. To take a shulker box and its contents with you, just break and collect it, the items will not fall out.= +To access the inventory of a shulker box, place and right-click it. To take a shulker box and its contents with you, just break and collect it, the items will not fall out. Place the shulker box again to be able to retrieve its contents.= Shulker Box= Large Chest= Inventory= diff --git a/mods/ITEMS/mcl_core/functions.lua b/mods/ITEMS/mcl_core/functions.lua index eceb81c51..2ef73af72 100644 --- a/mods/ITEMS/mcl_core/functions.lua +++ b/mods/ITEMS/mcl_core/functions.lua @@ -184,6 +184,7 @@ minetest.register_abm({ end, }) +-- Cactus mechanisms minetest.register_abm({ label = "Cactus growth", nodenames = {"mcl_core:cactus"}, @@ -195,19 +196,31 @@ minetest.register_abm({ end, }) --- Make cactus destroy items minetest.register_abm({ - label = "Cactus destroy items", + label = "Cactus mechanisms", nodenames = {"mcl_core:cactus"}, interval = 1, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) - for _,object in pairs(minetest.get_objects_inside_radius(pos, 0.9)) do + for _, object in pairs(minetest.get_objects_inside_radius(pos, 0.9)) do local entity = object:get_luaentity() if entity and entity.name == "__builtin:item" then object:remove() end end + local posses = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } } + for _, p in pairs(posses) do + if minetest.registered_nodes[minetest.get_node(vector.new(pos.x + p[1], pos.y, pos.z + p[2])).name].walkable then + local posy = pos.y + while minetest.get_node(vector.new(pos.x, posy, pos.z)).name == "mcl_core:cactus" do + local pos = vector.new(pos.x, posy, pos.z) + minetest.remove_node(pos) + minetest.add_item(vector.offset(pos, math.random(-0.5, 0.5), 0, math.random(-0.5, 0.5)), "mcl_core:cactus") + posy = posy + 1 + end + break + end + end end, }) diff --git a/mods/ITEMS/mcl_end/chorus_plant.lua b/mods/ITEMS/mcl_end/chorus_plant.lua index 24307b5ed..4dc54db18 100644 --- a/mods/ITEMS/mcl_end/chorus_plant.lua +++ b/mods/ITEMS/mcl_end/chorus_plant.lua @@ -453,7 +453,7 @@ function mcl_end.grow_chorus_plant_step(pos, node, pr) end --- ABM --- -local seed = minetest.get_mapgen_params().seed +local seed = minetest.get_mapgen_setting("seed") local pr = PseudoRandom(seed) minetest.register_abm({ label = "Chorus plant growth", diff --git a/mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.es.tr b/mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.es.tr new file mode 100644 index 000000000..e66eb06a5 --- /dev/null +++ b/mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.es.tr @@ -0,0 +1,3 @@ +# textdomain: mcl_fireworks +Firework Rocket= +Flight Duration:= \ No newline at end of file diff --git a/mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.fr.tr b/mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.fr.tr new file mode 100644 index 000000000..b02faa428 --- /dev/null +++ b/mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.fr.tr @@ -0,0 +1,3 @@ +# textdomain: mcl_fireworks +Firework Rocket=Fusée +Flight Duration:=Durée de vol : \ No newline at end of file diff --git a/mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.ru.tr b/mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.ru.tr new file mode 100644 index 000000000..e66eb06a5 --- /dev/null +++ b/mods/ITEMS/mcl_fireworks/locale/mcl_fireworks.ru.tr @@ -0,0 +1,3 @@ +# textdomain: mcl_fireworks +Firework Rocket= +Flight Duration:= \ No newline at end of file diff --git a/mods/ITEMS/mcl_maps/locale/mcl_maps.fr.tr b/mods/ITEMS/mcl_maps/locale/mcl_maps.fr.tr index 9ef7cd5c5..1808e839d 100644 --- a/mods/ITEMS/mcl_maps/locale/mcl_maps.fr.tr +++ b/mods/ITEMS/mcl_maps/locale/mcl_maps.fr.tr @@ -1,5 +1,8 @@ # textdomain: mcl_maps Empty Map=Carte Vierge Empty maps are not useful as maps, but they can be stacked and turned to maps which can be used.=Les cartes vierges ne sont pas utiles en tant que cartes, mais elles peuvent être empilées et transformées en cartes utilisables. -Rightclick to start using the map (which can't be stacked anymore).=Clic droit pour commencer à utiliser la carte (qui ne peut plus être empilée). +Rightclick to create a filled map (which can't be stacked anymore).=Clic droit pour créer une carte remplie (qui ne peut plus être empilée). Map=Carte +Shows a map image.=Affiche une carte. +When created, the map saves the nearby area as an image that can be viewed any time by holding the map.=Lors de sa création, la carte sauvegarde le terrain proche sous forme d'image qui peut être consultée n'importe quand en tenant la carte dans la main. +Hold the map in your hand. This will display a map on your screen.=Tenez la carte dans votre main. Cela affichera la carte à l'écran. diff --git a/mods/ITEMS/mcl_portals/mod.conf b/mods/ITEMS/mcl_portals/mod.conf index d99344a76..610b590c6 100644 --- a/mods/ITEMS/mcl_portals/mod.conf +++ b/mods/ITEMS/mcl_portals/mod.conf @@ -1,4 +1,4 @@ name = mcl_portals description = Adds buildable portals to the Nether and End dimensions. -depends = mcl_nether, mcl_end, mcl_particles, mcl_spawn +depends = mcl_nether, mcl_end, mcl_particles, mcl_spawn, mcl_credits optional_depends = awards, doc diff --git a/mods/ITEMS/mcl_portals/portal_end.lua b/mods/ITEMS/mcl_portals/portal_end.lua index d591537e1..e4982c39b 100644 --- a/mods/ITEMS/mcl_portals/portal_end.lua +++ b/mods/ITEMS/mcl_portals/portal_end.lua @@ -4,6 +4,8 @@ local table = table local vector = vector local math = math +local has_doc = minetest.get_modpath("doc") + -- Parameters --local SPAWN_MIN = mcl_vars.mg_end_min+70 --local SPAWN_MAX = mcl_vars.mg_end_min+98 @@ -339,7 +341,7 @@ minetest.register_node("mcl_portals:end_portal_frame_eye", { _mcl_hardness = -1, }) -if minetest.get_modpath("doc") then +if has_doc then doc.add_entry_alias("nodes", "mcl_portals:end_portal_frame", "nodes", "mcl_portals:end_portal_frame_eye") end @@ -366,7 +368,7 @@ minetest.override_item("mcl_end:ender_eye", { end minetest.set_node(pointed_thing.under, { name = "mcl_portals:end_portal_frame_eye", param2 = node.param2 }) - if minetest.get_modpath("doc") then + if has_doc then doc.mark_entry_as_revealed(user:get_player_name(), "nodes", "mcl_portals:end_portal_frame") end minetest.sound_play( @@ -381,7 +383,7 @@ minetest.override_item("mcl_end:ender_eye", { -- Epic 'portal open' sound effect that can be heard everywhere minetest.sound_play("mcl_portals_open_end_portal", {gain=0.8}, true) end_portal_area(ppos) - if minetest.get_modpath("doc") then + if has_doc then doc.mark_entry_as_revealed(user:get_player_name(), "nodes", "mcl_portals:portal_end") end end @@ -389,7 +391,3 @@ minetest.override_item("mcl_end:ender_eye", { return itemstack end, }) -minetest.override_item("mcl_core:bedrock", { - after_destruct = destroy_portal, -}) - diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 09b95115a..c3b034b66 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -35,13 +35,13 @@ local function potions_init_icons(player) local name = player:get_player_name() icon_ids[name] = {} for e=1, EFFECT_TYPES do - local x = -7 + -38 * e + local x = -52 * e - 2 local id = player:hud_add({ hud_elem_type = "image", text = "blank.png", position = { x = 1, y = 0 }, - offset = { x = x, y = 272 }, - scale = { x = 2, y = 2 }, + offset = { x = x, y = 3 }, + scale = { x = 3, y = 3 }, alignment = { x = 1, y = 1 }, z_index = 100, }) diff --git a/mods/MISC/mcl_temp_helper_recipes/init.lua b/mods/MISC/mcl_temp_helper_recipes/init.lua index 420cd6c2e..b7607946d 100644 --- a/mods/MISC/mcl_temp_helper_recipes/init.lua +++ b/mods/MISC/mcl_temp_helper_recipes/init.lua @@ -35,40 +35,6 @@ minetest.register_craft({ }, }) -minetest.register_craft({ - output = "mcl_armor:helmet_chain", - recipe = { - { "xpanes:bar_flat", "mcl_core:iron_ingot", "xpanes:bar_flat" }, - { "xpanes:bar_flat", "", "xpanes:bar_flat" }, - } -}) - -minetest.register_craft({ - output = "mcl_armor:leggings_chain", - recipe = { - { "xpanes:bar_flat", "mcl_core:iron_ingot", "xpanes:bar_flat" }, - { "xpanes:bar_flat", "", "xpanes:bar_flat" }, - { "xpanes:bar_flat", "", "xpanes:bar_flat" }, - } -}) - -minetest.register_craft({ - output = "mcl_armor:boots_chain", - recipe = { - { "xpanes:bar_flat", "", "xpanes:bar_flat" }, - { "xpanes:bar_flat", "", "xpanes:bar_flat" }, - } -}) - -minetest.register_craft({ - output = "mcl_armor:chestplate_chain", - recipe = { - { "xpanes:bar_flat", "", "xpanes:bar_flat" }, - { "xpanes:bar_flat", "mcl_core:iron_ingot", "xpanes:bar_flat" }, - { "xpanes:bar_flat", "xpanes:bar_flat", "xpanes:bar_flat" }, - } -}) - -- Make red sand, red sandstone and more craftable in v6 -- NOTE: When you change these, also update mcl_craftguide for the "v6" icon in -- the craft guide! diff --git a/mods/PLAYER/mcl_hunger/hunger.lua b/mods/PLAYER/mcl_hunger/hunger.lua index 5dec8b1b0..d9a6fd5fe 100644 --- a/mods/PLAYER/mcl_hunger/hunger.lua +++ b/mods/PLAYER/mcl_hunger/hunger.lua @@ -152,26 +152,18 @@ function mcl_hunger.item_eat(hunger_change, replace_with_item, poisontime, poiso -- If false, force item to not spawn any food partiles when eaten if def._food_particles ~= false and texture and texture ~= "" then local v = user:get_velocity() or user:get_player_velocity() - local minvel = vector.add(v, {x=-1, y=1, z=-1}) - local maxvel = vector.add(v, {x=1, y=2, z=1}) - - minetest.add_particlespawner({ - amount = math.min(math.max(8, hunger_change*2), 25), - time = 0.1, - minpos = {x=pos.x, y=pos.y, z=pos.z}, - maxpos = {x=pos.x, y=pos.y, z=pos.z}, - minvel = minvel, - maxvel = maxvel, - minacc = {x=0, y=-5, z=0}, - maxacc = {x=0, y=-9, z=0}, - minexptime = 1, - maxexptime = 1, - minsize = 1, - maxsize = 2, - collisiondetection = true, - vertical = false, - texture = texture, - }) + for i = 0, math.min(math.max(8, hunger_change*2), 25) do + minetest.add_particle({ + pos = { x = pos.x, y = pos.y, z = pos.z }, + velocity = vector.add(v, { x = math.random(-1, 1), y = math.random(1, 2), z = math.random(-1, 1) }), + acceleration = { x = 0, y = math.random(-9, -5), z = 0 }, + expirationtime = 1, + size = math.random(1, 2), + collisiondetection = true, + vertical = false, + texture = "[combine:3x3:" .. -i .. "," .. -i .. "=" .. texture, + }) + end end minetest.sound_play("mcl_hunger_bite", { max_hear_distance = 12, diff --git a/mods/PLAYER/mcl_playerplus/mod.conf b/mods/PLAYER/mcl_playerplus/mod.conf index 6989957d7..b77c9e2e5 100644 --- a/mods/PLAYER/mcl_playerplus/mod.conf +++ b/mods/PLAYER/mcl_playerplus/mod.conf @@ -1,5 +1,5 @@ name = mcl_playerplus author = TenPlus1 description = Adds some simple player-related gameplay effects: Hurt by touching a cactus, suffocation and more. -depends = mcl_init, mcl_core, mcl_particles, mcl_hunger, playerphysics, mcl_playerinfo, mcl_weather, mcl_spawn, mcl_enchanting, mcl_damage +depends = mcl_init, mcl_core, mcl_particles, mcl_hunger, playerphysics, mcl_playerinfo, mcl_weather, mcl_spawn, mcl_enchanting, mcl_damage, mcl_sprint diff --git a/mods/PLAYER/mcl_sprint/init.lua b/mods/PLAYER/mcl_sprint/init.lua index 73a518c42..4c0d609c9 100644 --- a/mods/PLAYER/mcl_sprint/init.lua +++ b/mods/PLAYER/mcl_sprint/init.lua @@ -69,18 +69,19 @@ local function setSprinting(playerName, sprinting) --Sets the state of a player local controls = player:get_player_control() if players[playerName] then players[playerName].sprinting = sprinting + local fov_old = players[playerName].fov + local fov_new = fov_old + local fade_time = .15 if sprinting == true or controls.RMB and string.find(player:get_wielded_item():get_name(), "mcl_bows:bow") and player:get_wielded_item():get_name() ~= "mcl_bows:bow" then if sprinting == true then - players[playerName].fov = math.min(players[playerName].fov + 0.05, 1.2) - players[playerName].fade_time = .15 + fov_new = math.min(players[playerName].fov + 0.05, 1.2) else - players[playerName].fov = .7 + fov_new = .7 players[playerName].fade_time = .3 end - player:set_fov(players[playerName].fov, true, players[playerName].fade_time) if sprinting == true then playerphysics.add_physics_factor(player, "speed", "mcl_sprint:sprint", mcl_sprint.SPEED) end @@ -88,12 +89,15 @@ local function setSprinting(playerName, sprinting) --Sets the state of a player and player:get_wielded_item():get_name() ~= "mcl_bows:bow_0" and player:get_wielded_item():get_name() ~= "mcl_bows:bow_1" and player:get_wielded_item():get_name() ~= "mcl_bows:bow_2" then - players[playerName].fov = math.max(players[playerName].fov - 0.05, 1.0) - player:set_fov(players[playerName].fov, true, 0.15) + fov_new = math.max(players[playerName].fov - 0.05, 1.0) if sprinting == false then playerphysics.remove_physics_factor(player, "speed", "mcl_sprint:sprint") end end + if fov_new ~= fov_old then + players[playerName].fov = fov_new + player:set_fov(fov_new, true, fade_time) + end return true end return false diff --git a/settingtypes.txt b/settingtypes.txt index ea1c1a50a..f605019ad 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -153,3 +153,7 @@ fix_doubleplants (Mcimport double plant fixes) bool true # Allow players to create Minecraft-like maps. enable_real_maps (Enable Real Maps) 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 \ No newline at end of file