From 692758bd6d5d9792105620e4c753c809393419cb Mon Sep 17 00:00:00 2001 From: Johannes Fritz Date: Fri, 24 Mar 2023 13:26:40 -0500 Subject: [PATCH 001/155] Remove deprecated usages of image property in tile defs --- mods/ITEMS/mcl_beds/respawn_anchor.lua | 2 +- mods/ITEMS/mcl_crimson/init.lua | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mods/ITEMS/mcl_beds/respawn_anchor.lua b/mods/ITEMS/mcl_beds/respawn_anchor.lua index f167599c7..781a82953 100644 --- a/mods/ITEMS/mcl_beds/respawn_anchor.lua +++ b/mods/ITEMS/mcl_beds/respawn_anchor.lua @@ -45,7 +45,7 @@ for i=0,4 do description=S("Respawn Anchor"), tiles = { { - image="respawn_anchor_top_on.png^[noalpha", + name = "respawn_anchor_top_on.png^[noalpha", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0} }, "respawn_anchor_bottom.png", diff --git a/mods/ITEMS/mcl_crimson/init.lua b/mods/ITEMS/mcl_crimson/init.lua index 1c30c0fd5..dff620dde 100644 --- a/mods/ITEMS/mcl_crimson/init.lua +++ b/mods/ITEMS/mcl_crimson/init.lua @@ -331,7 +331,7 @@ minetest.register_node("mcl_crimson:warped_hyphae", { "mcl_crimson_warped_hyphae.png", "mcl_crimson_warped_hyphae.png", { - image="mcl_crimson_warped_hyphae_side.png", + name = "mcl_crimson_warped_hyphae_side.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0} }, }, @@ -370,7 +370,7 @@ minetest.register_node("mcl_crimson:warped_hyphae_bark", { _doc_items_longdesc = S("This is a decorative block surrounded by the bark of an hyphae."), tiles = { { - image="mcl_crimson_warped_hyphae_side.png", + name = "mcl_crimson_warped_hyphae_side.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0} }, }, @@ -525,7 +525,7 @@ minetest.register_node("mcl_crimson:crimson_hyphae", { "mcl_crimson_crimson_hyphae.png", "mcl_crimson_crimson_hyphae.png", { - image="mcl_crimson_crimson_hyphae_side.png", + name = "mcl_crimson_crimson_hyphae_side.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0} }, }, @@ -545,7 +545,7 @@ minetest.register_node("mcl_crimson:crimson_hyphae_bark", { _doc_items_longdesc = S("This is a decorative block surrounded by the bark of an hyphae."), tiles = { { - image="mcl_crimson_crimson_hyphae_side.png", + name = "mcl_crimson_crimson_hyphae_side.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0} }, }, From 049a4a11f4e3c23d2d71e6783a42af1382717837 Mon Sep 17 00:00:00 2001 From: Wbjitscool Date: Mon, 27 Mar 2023 00:00:09 +0000 Subject: [PATCH 002/155] Update 'mods/ITEMS/REDSTONE/mesecons_pressureplates/locale/template.txt' updated template.txt --- mods/ITEMS/REDSTONE/mesecons_pressureplates/locale/template.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ITEMS/REDSTONE/mesecons_pressureplates/locale/template.txt b/mods/ITEMS/REDSTONE/mesecons_pressureplates/locale/template.txt index 96eb3f922..2abe21b04 100644 --- a/mods/ITEMS/REDSTONE/mesecons_pressureplates/locale/template.txt +++ b/mods/ITEMS/REDSTONE/mesecons_pressureplates/locale/template.txt @@ -7,6 +7,7 @@ Dark Oak Pressure Plate= Spruce Pressure Plate= Jungle Pressure Plate= A wooden pressure plate is a redstone component which supplies its surrounding blocks with redstone power while any movable object (including dropped items, players and mobs) rests on top of it.= +Polished Blackstone Pressure Plate= Stone Pressure Plate= A stone pressure plate is a redstone component which supplies its surrounding blocks with redstone power while a player or mob stands on top of it. It is not triggered by anything else.= Provides redstone power when pushed= From c0fa2c38bd048dc7ff25491cc24abc6f388082b6 Mon Sep 17 00:00:00 2001 From: Wbjitscool Date: Mon, 27 Mar 2023 00:02:29 +0000 Subject: [PATCH 003/155] Update 'mods/ITEMS/REDSTONE/mesecons_pressureplates/init.lua' added polished blackstone pressure plate --- .../ITEMS/REDSTONE/mesecons_pressureplates/init.lua | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/mods/ITEMS/REDSTONE/mesecons_pressureplates/init.lua b/mods/ITEMS/REDSTONE/mesecons_pressureplates/init.lua index 97a9a223b..3dca8aa0c 100644 --- a/mods/ITEMS/REDSTONE/mesecons_pressureplates/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_pressureplates/init.lua @@ -262,4 +262,17 @@ mesecon.register_pressure_plate( { player = true, mob = true }, S("A stone pressure plate is a redstone component which supplies its surrounding blocks with redstone power while a player or mob stands on top of it. It is not triggered by anything else.")) +mesecon.register_pressure_plate( + "mesecons_pressureplates:pressure_plate_polished_blackstone", + S("Polished Blackstone Pressure Plate"), + {"mcl_blackstone_polished.png"}, + {"mcl_blackstone_polished.png"}, + "mcl_blackstone_polished.png", + nil, + {{"mcl_blackstone:blackstone_polished", "mcl_blackstone:blackstone_polished"}}, + mcl_sounds.node_sound_stone_defaults(), + {pickaxey=1, material_stone=1}, + { player = true, mob = true }, + S("A polished blackstone pressure plate is a redstone component which supplies its surrounding blocks with redstone power while a player or mob stands on top of it. It is not triggered by anything else.")) + From e3978c4d22ee0a62d97101851760b918248388d4 Mon Sep 17 00:00:00 2001 From: Wbjitscool Date: Mon, 27 Mar 2023 00:05:52 +0000 Subject: [PATCH 004/155] Update 'mods/ITEMS/REDSTONE/mesecons_button/locale/template.txt' updated template.txt for buttons --- mods/ITEMS/REDSTONE/mesecons_button/locale/template.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ITEMS/REDSTONE/mesecons_button/locale/template.txt b/mods/ITEMS/REDSTONE/mesecons_button/locale/template.txt index 4c352b878..e721736a1 100644 --- a/mods/ITEMS/REDSTONE/mesecons_button/locale/template.txt +++ b/mods/ITEMS/REDSTONE/mesecons_button/locale/template.txt @@ -2,6 +2,7 @@ Use the button to push it.= Stone Button= A stone button is a redstone component made out of stone which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1 second.= +Polished Blackstone Button= Oak Button= Acacia Button= Birch Button= From a10235f3309d73f19c0149c9a32297f6e1596535 Mon Sep 17 00:00:00 2001 From: Wbjitscool Date: Mon, 27 Mar 2023 00:07:48 +0000 Subject: [PATCH 005/155] Update 'mods/ITEMS/REDSTONE/mesecons_button/init.lua' added in a Polished Blackstone Button --- mods/ITEMS/REDSTONE/mesecons_button/init.lua | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/mods/ITEMS/REDSTONE/mesecons_button/init.lua b/mods/ITEMS/REDSTONE/mesecons_button/init.lua index 449e70135..f7d6c7105 100644 --- a/mods/ITEMS/REDSTONE/mesecons_button/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_button/init.lua @@ -216,6 +216,18 @@ mesecon.register_button( S("A stone button is a redstone component made out of stone which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1 second."), "mesecons_button_push") +mesecon.register_button( + "polished_blackstone", + S("Polished Blackstone Button"), + "mcl_blackstone_polished.png", + "mcl_blackstone:blackstone_polished", + mcl_sounds.node_sound_stone_defaults(), + {material_stone=1,handy=1,pickaxey=1}, + 1, + false, + S("A polished blackstone button is a redstone component made out of polished blackstone which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1 second."), + "mesecons_button_push") + local woods = { { "wood", "mcl_core:wood", "default_wood.png", S("Oak Button") }, { "acaciawood", "mcl_core:acaciawood", "default_acacia_wood.png", S("Acacia Button") }, From 87ca144c4e3cdda6a8e50f4f9269d1982b51c528 Mon Sep 17 00:00:00 2001 From: Wbjitscool Date: Mon, 27 Mar 2023 00:23:53 +0000 Subject: [PATCH 006/155] Update 'mods/ITEMS/REDSTONE/mesecons_button/locale/template.txt' --- mods/ITEMS/REDSTONE/mesecons_button/locale/template.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ITEMS/REDSTONE/mesecons_button/locale/template.txt b/mods/ITEMS/REDSTONE/mesecons_button/locale/template.txt index e721736a1..421d02b63 100644 --- a/mods/ITEMS/REDSTONE/mesecons_button/locale/template.txt +++ b/mods/ITEMS/REDSTONE/mesecons_button/locale/template.txt @@ -3,6 +3,7 @@ Use the button to push it.= Stone Button= A stone button is a redstone component made out of stone which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1 second.= Polished Blackstone Button= +A polished blackstone button is a redstone component made out of polished blackstone which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1 second.= Oak Button= Acacia Button= Birch Button= From bfa566242183d00e78acfbb6ae36011b7817bf3c Mon Sep 17 00:00:00 2001 From: Wbjitscool Date: Mon, 27 Mar 2023 00:24:40 +0000 Subject: [PATCH 007/155] Update 'mods/ITEMS/REDSTONE/mesecons_pressureplates/locale/template.txt' --- mods/ITEMS/REDSTONE/mesecons_pressureplates/locale/template.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ITEMS/REDSTONE/mesecons_pressureplates/locale/template.txt b/mods/ITEMS/REDSTONE/mesecons_pressureplates/locale/template.txt index 2abe21b04..1239dd668 100644 --- a/mods/ITEMS/REDSTONE/mesecons_pressureplates/locale/template.txt +++ b/mods/ITEMS/REDSTONE/mesecons_pressureplates/locale/template.txt @@ -8,6 +8,7 @@ Spruce Pressure Plate= Jungle Pressure Plate= A wooden pressure plate is a redstone component which supplies its surrounding blocks with redstone power while any movable object (including dropped items, players and mobs) rests on top of it.= Polished Blackstone Pressure Plate= +A polished blackstone pressure plate is a redstone component which supplies its surrounding blocks with redstone power while a player or mob stands on top of it. It is not triggered by anything else.= Stone Pressure Plate= A stone pressure plate is a redstone component which supplies its surrounding blocks with redstone power while a player or mob stands on top of it. It is not triggered by anything else.= Provides redstone power when pushed= From 24265708711ead0c89bf7e03e92834b3938602d3 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 27 Mar 2023 03:11:33 +0100 Subject: [PATCH 008/155] Fix for light night rain and dark day rain issue --- mods/ENVIRONMENT/mcl_weather/skycolor.lua | 38 ++++++++++++++++++----- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/mods/ENVIRONMENT/mcl_weather/skycolor.lua b/mods/ENVIRONMENT/mcl_weather/skycolor.lua index 711f46caa..0adb5566d 100644 --- a/mods/ENVIRONMENT/mcl_weather/skycolor.lua +++ b/mods/ENVIRONMENT/mcl_weather/skycolor.lua @@ -211,17 +211,39 @@ mcl_weather.skycolor = { player:set_moon({visible = false}) player:set_stars({visible = false}) - local lf = mcl_weather.get_current_light_factor() + local light_factor = mcl_weather.get_current_light_factor() if mcl_weather.skycolor.current_layer_name() == "lightning" then mcl_weather.skycolor.override_day_night_ratio(player, 1) - elseif lf then - local w = minetest.get_timeofday() - local light = (w * (lf*2)) - if light > 1 then - light = 1 - (light - 1) + elseif light_factor then + local time = minetest.get_timeofday() + -- 0.5 = 1 + -- 0 = 0 + -- 0.99 = 0 + + -- greater than 0.5, is + + -- less than 0.5 = time / 0.5 + + -- 0.6 = 0.8 + -- 0.9 = 0.2 + + -- 0.6 = 0.4 + -- 0.9 = 0.1 + -- 2 * (1 - time) + + local light_multiplier = time * 2 + if time > 0.5 then + light_multiplier = 2 * (1 - time) + else + light_multiplier = time / 0.5 end - light = (light * lf) + 0.15 - mcl_weather.skycolor.override_day_night_ratio(player, light) + local minimum_light_level = 0.10 + + minetest.log("New light_multiplier: " .. tostring(light_multiplier)) + local new_light = (light_factor * (light_multiplier * (1-minimum_light_level))) + minimum_light_level + minetest.log("new_light: " .. tostring(new_light)) + + mcl_weather.skycolor.override_day_night_ratio(player, new_light) else mcl_weather.skycolor.override_day_night_ratio(player, nil) end From 61a4595c1b07a65402abc98cf74f6adac13153b7 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 27 Mar 2023 03:38:49 +0100 Subject: [PATCH 009/155] Fix rain light levels so that day rain is brighter and night rain is darker --- mods/ENVIRONMENT/mcl_weather/skycolor.lua | 49 ++++++++++------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/mods/ENVIRONMENT/mcl_weather/skycolor.lua b/mods/ENVIRONMENT/mcl_weather/skycolor.lua index 0adb5566d..aea469760 100644 --- a/mods/ENVIRONMENT/mcl_weather/skycolor.lua +++ b/mods/ENVIRONMENT/mcl_weather/skycolor.lua @@ -1,6 +1,8 @@ local mods_loaded = false local NIGHT_VISION_RATIO = 0.45 +local MINIMUM_LIGHT_LEVEL = 0.2 + local water_color = "#3F76E4" local mg_name = minetest.get_mapgen_setting("mg_name") @@ -45,6 +47,24 @@ function mcl_weather.set_sky_color(player, def) }) end +-- Function to work out light modifier at different times +-- Noon is brightest, midnight is darkest, 0600 and 18000 is in the middle of this +local function get_light_modifier(time) + -- 0.1 = 0.2 + -- 0.4 = 0.8 + -- 0.5 = 1 + -- 0.6 = 0.8 + -- 0.9 = 0.2 + + local light_multiplier = time * 2 + if time > 0.5 then + light_multiplier = 2 * (1 - time) + else + light_multiplier = time / 0.5 + end + return light_multiplier +end + mcl_weather.skycolor = { -- Should be activated before do any effect. active = true, @@ -216,33 +236,8 @@ mcl_weather.skycolor = { mcl_weather.skycolor.override_day_night_ratio(player, 1) elseif light_factor then local time = minetest.get_timeofday() - -- 0.5 = 1 - -- 0 = 0 - -- 0.99 = 0 - - -- greater than 0.5, is - - -- less than 0.5 = time / 0.5 - - -- 0.6 = 0.8 - -- 0.9 = 0.2 - - -- 0.6 = 0.4 - -- 0.9 = 0.1 - -- 2 * (1 - time) - - local light_multiplier = time * 2 - if time > 0.5 then - light_multiplier = 2 * (1 - time) - else - light_multiplier = time / 0.5 - end - local minimum_light_level = 0.10 - - minetest.log("New light_multiplier: " .. tostring(light_multiplier)) - local new_light = (light_factor * (light_multiplier * (1-minimum_light_level))) + minimum_light_level - minetest.log("new_light: " .. tostring(new_light)) - + local light_multiplier = get_light_modifier(time) + local new_light = math.max(light_factor * light_multiplier, MINIMUM_LIGHT_LEVEL) mcl_weather.skycolor.override_day_night_ratio(player, new_light) else mcl_weather.skycolor.override_day_night_ratio(player, nil) From 8a129fa00ca5889c9041610b41fa25fa7adf242e Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Wed, 29 Mar 2023 09:45:04 -0600 Subject: [PATCH 010/155] Add slab and stair groups to crimson and warped slabs and stairs --- mods/ITEMS/mcl_crimson/init.lua | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_crimson/init.lua b/mods/ITEMS/mcl_crimson/init.lua index dff620dde..03d0a7caa 100644 --- a/mods/ITEMS/mcl_crimson/init.lua +++ b/mods/ITEMS/mcl_crimson/init.lua @@ -5,6 +5,9 @@ local modpath = minetest.get_modpath(modname) -- by debiankaios -- adapted for mcl2 by cora +local wood_slab_groups = {handy = 1, axey = 1, flammable = 3, material_wood = 1, fire_encouragement = 5, fire_flammability = 20, wood_slab = 1} +local wood_stair_groups = {handy = 1, axey = 1, flammable = 3, material_wood = 1, fire_encouragement = 5, fire_flammability = 20, wood_stairs = 1} + local function generate_warped_tree(pos) minetest.place_schematic(pos,modpath.."/schematics/warped_fungus_1.mts","random",nil,false,"place_center_x,place_center_z") end @@ -434,7 +437,8 @@ minetest.register_node("mcl_crimson:warped_hyphae_wood", { _mcl_hardness = 2, }) -mcl_stairs.register_stair_and_slab_simple("warped_hyphae_wood", "mcl_crimson:warped_hyphae_wood", S("Warped Stair"), S("Warped Slab"), S("Double Warped Slab")) +mcl_stairs.register_stair("warped_hyphae_wood", "mcl_crimson:warped_hyphae_wood", wood_stair_groups, false, S("Warped Stair")) +mcl_stairs.register_slab("warped_hyphae_wood", "mcl_crimson:warped_hyphae_wood", wood_slab_groups, false, S("Warped Slab")) minetest.register_craft({ output = "mcl_crimson:warped_hyphae_wood 4", @@ -643,7 +647,8 @@ minetest.register_craft({ }, }) -mcl_stairs.register_stair_and_slab_simple("crimson_hyphae_wood", "mcl_crimson:crimson_hyphae_wood", S("Crimson Stair"), S("Crimson Slab"), S("Double Crimson Slab")) +mcl_stairs.register_stair("crimson_hyphae_wood", "mcl_crimson:crimson_hyphae_wood", wood_stair_groups, false, S("Crimson Stair")) +mcl_stairs.register_slab("crimson_hyphae_wood", "mcl_crimson:crimson_hyphae_wood", wood_slab_groups, false, S("Crimson Slab")) mcl_dye.register_on_bone_meal_apply(function(pt,user) if not pt.type == "node" then return end From 2bd36b5d6643b1007a15a0b12c1a89a6271c1804 Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Wed, 29 Mar 2023 11:41:48 -0600 Subject: [PATCH 011/155] Make lecterns require wood slabs for crafting Otherwise you can use stone slabs to craft lecterns, which doesn't make sense --- mods/ITEMS/mcl_lectern/init.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_lectern/init.lua b/mods/ITEMS/mcl_lectern/init.lua index e6b7e3db8..98366b7b8 100644 --- a/mods/ITEMS/mcl_lectern/init.lua +++ b/mods/ITEMS/mcl_lectern/init.lua @@ -130,9 +130,9 @@ end minetest.register_craft({ output = "mcl_lectern:lectern", recipe = { - {"group:slab", "group:slab", "group:slab"}, + {"group:wood_slab", "group:wood_slab", "group:wood_slab"}, {"", "mcl_books:bookshelf", ""}, - {"", "group:slab", ""}, + {"", "group:wood_slab", ""}, } }) From f284b1ca0ed328af437e944f858998c0f57a9a62 Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Wed, 29 Mar 2023 15:23:15 -0600 Subject: [PATCH 012/155] Fix minor issue with mcl_stairs.register_stair function --- mods/ITEMS/mcl_stairs/api.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_stairs/api.lua b/mods/ITEMS/mcl_stairs/api.lua index 34afb018e..49daad9bf 100644 --- a/mods/ITEMS/mcl_stairs/api.lua +++ b/mods/ITEMS/mcl_stairs/api.lua @@ -71,8 +71,6 @@ end -- Node will be called mcl_stairs:stair_ function mcl_stairs.register_stair(subname, recipeitem, groups, images, description, sounds, blast_resistance, hardness, corner_stair_texture_override) - groups.stair = 1 - groups.building_block = 1 if recipeitem then if not images then @@ -92,6 +90,9 @@ function mcl_stairs.register_stair(subname, recipeitem, groups, images, descript end end + groups.stair = 1 + groups.building_block = 1 + minetest.register_node(":mcl_stairs:stair_" .. subname, { description = description, _doc_items_longdesc = S("Stairs are useful to reach higher places by walking over them; jumping is not required. Placing stairs in a corner pattern will create corner stairs. Stairs placed on the ceiling or at the upper half of the side of a block will be placed upside down."), From b08b6034ac55a142534708cf7ffef551df847d21 Mon Sep 17 00:00:00 2001 From: SmokeyDope Date: Sat, 25 Mar 2023 19:41:13 +0000 Subject: [PATCH 013/155] Add texture making documentation --- TEXTURES.md | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 TEXTURES.md diff --git a/TEXTURES.md b/TEXTURES.md new file mode 100644 index 000000000..3dd3f7e56 --- /dev/null +++ b/TEXTURES.md @@ -0,0 +1,57 @@ +#Making Textures In Mineclone2 + +Textures are a crucial asset for all items, nodes, and models in mineclone2. This document is for artist who would like to make and modify textures for mineclone2. While no means comprehensive, this document contains the basic important information for beginners to get started with texture curation and optimization. + +## Minetest Wiki +For more detailed information on creating and modifing texture packs for Minetest/Mineclone2, please visit the Minetest wiki's page on creating a texture pack. Click [here](https://wiki.minetest.net/Creating_texture_packs) to view the wiki page on creating texture packs. + +## GIMP Tutorials Pixel Art Guide +GIMP Tutorials has an excellent guide to making pixel art in GIMP. If you would like further clarification as well as screenshots for what we are about to cover, it is an excellent resource to turn to. Click [here](https://thegimptutorials.com/how-to-make-pixel-art/) to view the guide + +##Recommended Software + +###GIMP + +GIMP (Gnu Image Manipulation Program) is a very popular and free image editing software supported on Windows, MacOS, and most Linux distributions. It is recommended to use GIMP to create and modify textures within the minetest engine. + +Download GIMP [here](http://gimp.org/) + +#Getting Started +##Creating a new file +the first thing to do is open GIMP and create a new file to work in by opening the File menu and choosing New. + +Choose width of 16 and height of 16 for the image size. While higher resolution textures are possible, The default size is 16x16. It is recommended you use this size as well, as it is universally supported on all systems. + +##Zoom In +Next, you'll want to zoom in as the canvas is very small at the default zoom level. To do this either use CTRL + mousewheel, +/-, or navigate to the View menu > zoom > zoom in + +##Grid +Now, we'll want to turn on the grid. Open the edit menu and enable the 'show grid' option. + +The default grid size is 10 pixels, we want to change it to a 1 pixel grid. Go to the Image menu and choose 'configure grid. + +In the Spacing section, change both the Horizontal and Vertical pixel settings to 1.00 then click ok and the grid will update. + +##Pencil Tool & Color Picking +The most useful brush type for pixel art is the Pencil tool. Its nested under the paintbrush tool in the toolbox, or you can use the keyboard shortcut 'N'. + +Once the pencil tool is selected, navigate to the sliders on the left side of the canvas and change brush size to 1 pixel. + +Now choose a color! You can do this by clicking on the two colored squares under the toolbox. The Color Picker tool is also a good option if you already have a reference image for color palette. + +##How to export optimally + +Once you have finished up a texture and are ready to export it, navigate to the file menu > export as... and make sure the file name extention is .png + +After clicking 'Export', a menu will appear with a bunch of options checked. Make sure to uncheck all of these options!!! This will drastically reduce the file size from multiple kilobytes to a couple of hundred bytes. Finally click 'Export' one more time. + +###Further optimization +For those running a GNU/linux distribution, you most likely have the 'optipng command available to you. + +Open up the terminal in the directory where your exported texture is located, and run this command +``` +optipng -o7 *.png +``` +This will further optimize all the textures in the directory. + +NOTE: If you would like to further edit a texture that has been optipng'd in GIMP, you must manually set the color palette back to RBG after opening. Navigate to Image menu > Mode > select RGB From 4226b2a8badb9071b735d5e87b5ec7a030a216b5 Mon Sep 17 00:00:00 2001 From: SmokeyDope Date: Sat, 25 Mar 2023 19:55:00 +0000 Subject: [PATCH 014/155] Add link to optipng in textures.md and fix some formatting --- TEXTURES.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/TEXTURES.md b/TEXTURES.md index 3dd3f7e56..eecfed3b2 100644 --- a/TEXTURES.md +++ b/TEXTURES.md @@ -1,4 +1,4 @@ -#Making Textures In Mineclone2 +# Making Textures In Mineclone2 Textures are a crucial asset for all items, nodes, and models in mineclone2. This document is for artist who would like to make and modify textures for mineclone2. While no means comprehensive, this document contains the basic important information for beginners to get started with texture curation and optimization. @@ -8,47 +8,47 @@ For more detailed information on creating and modifing texture packs for Minetes ## GIMP Tutorials Pixel Art Guide GIMP Tutorials has an excellent guide to making pixel art in GIMP. If you would like further clarification as well as screenshots for what we are about to cover, it is an excellent resource to turn to. Click [here](https://thegimptutorials.com/how-to-make-pixel-art/) to view the guide -##Recommended Software +## Recommended Software -###GIMP +### GIMP GIMP (Gnu Image Manipulation Program) is a very popular and free image editing software supported on Windows, MacOS, and most Linux distributions. It is recommended to use GIMP to create and modify textures within the minetest engine. Download GIMP [here](http://gimp.org/) -#Getting Started -##Creating a new file +# Getting Started +## Creating a new file the first thing to do is open GIMP and create a new file to work in by opening the File menu and choosing New. Choose width of 16 and height of 16 for the image size. While higher resolution textures are possible, The default size is 16x16. It is recommended you use this size as well, as it is universally supported on all systems. -##Zoom In +## Zoom In Next, you'll want to zoom in as the canvas is very small at the default zoom level. To do this either use CTRL + mousewheel, +/-, or navigate to the View menu > zoom > zoom in -##Grid +## Configure Grid Now, we'll want to turn on the grid. Open the edit menu and enable the 'show grid' option. The default grid size is 10 pixels, we want to change it to a 1 pixel grid. Go to the Image menu and choose 'configure grid. In the Spacing section, change both the Horizontal and Vertical pixel settings to 1.00 then click ok and the grid will update. -##Pencil Tool & Color Picking +## Pencil Tool & Color Picking The most useful brush type for pixel art is the Pencil tool. Its nested under the paintbrush tool in the toolbox, or you can use the keyboard shortcut 'N'. Once the pencil tool is selected, navigate to the sliders on the left side of the canvas and change brush size to 1 pixel. Now choose a color! You can do this by clicking on the two colored squares under the toolbox. The Color Picker tool is also a good option if you already have a reference image for color palette. -##How to export optimally +## How to export optimally Once you have finished up a texture and are ready to export it, navigate to the file menu > export as... and make sure the file name extention is .png After clicking 'Export', a menu will appear with a bunch of options checked. Make sure to uncheck all of these options!!! This will drastically reduce the file size from multiple kilobytes to a couple of hundred bytes. Finally click 'Export' one more time. -###Further optimization -For those running a GNU/linux distribution, you most likely have the 'optipng command available to you. +###Further optimization with OptiPNG +For those running a GNU/linux distribution, you most likely have the 'optipng' command available to you. If it does not come with your system by default, the software homepage can be found [here](https://optipng.sourceforge.net/) where you can download and install from source. -Open up the terminal in the directory where your exported texture is located, and run this command +First, Open up the terminal in the directory where your exported texture is located (or navigate to the directory with the 'cd your/directory/path/to/textures'), then run this command ``` optipng -o7 *.png ``` From c3e37cb840341d9c7a4bb71a8f6a6555cd23dbe7 Mon Sep 17 00:00:00 2001 From: SmokeyDope Date: Sat, 25 Mar 2023 19:55:43 +0000 Subject: [PATCH 015/155] One more formatting adjust --- TEXTURES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TEXTURES.md b/TEXTURES.md index eecfed3b2..ec2507956 100644 --- a/TEXTURES.md +++ b/TEXTURES.md @@ -45,7 +45,7 @@ Once you have finished up a texture and are ready to export it, navigate to the After clicking 'Export', a menu will appear with a bunch of options checked. Make sure to uncheck all of these options!!! This will drastically reduce the file size from multiple kilobytes to a couple of hundred bytes. Finally click 'Export' one more time. -###Further optimization with OptiPNG +### Further optimization with OptiPNG For those running a GNU/linux distribution, you most likely have the 'optipng' command available to you. If it does not come with your system by default, the software homepage can be found [here](https://optipng.sourceforge.net/) where you can download and install from source. First, Open up the terminal in the directory where your exported texture is located (or navigate to the directory with the 'cd your/directory/path/to/textures'), then run this command From 8a1c885faf9e354879fe27ee2f387fb3a07bd124 Mon Sep 17 00:00:00 2001 From: SmokeyDope Date: Sun, 26 Mar 2023 17:48:47 +0000 Subject: [PATCH 016/155] Update optipng command to ACFMS' recommendation --- TEXTURES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TEXTURES.md b/TEXTURES.md index ec2507956..1cf10641f 100644 --- a/TEXTURES.md +++ b/TEXTURES.md @@ -50,7 +50,7 @@ For those running a GNU/linux distribution, you most likely have the 'optipng' c First, Open up the terminal in the directory where your exported texture is located (or navigate to the directory with the 'cd your/directory/path/to/textures'), then run this command ``` -optipng -o7 *.png +optipng -o7 -zm1-9 -nc -clobber *.png ``` This will further optimize all the textures in the directory. From bef204f5480af852deabd4d81fef9baec9dabed6 Mon Sep 17 00:00:00 2001 From: Johannes Fritz Date: Mon, 27 Mar 2023 12:09:13 -0500 Subject: [PATCH 017/155] Remove mcl_player_init --- mods/PLAYER/mcl_meshhand/init.lua | 4 ++++ mods/PLAYER/mcl_player_init/init.lua | 4 ---- mods/PLAYER/mcl_player_init/mod.conf | 3 --- 3 files changed, 4 insertions(+), 7 deletions(-) delete mode 100644 mods/PLAYER/mcl_player_init/init.lua delete mode 100644 mods/PLAYER/mcl_player_init/mod.conf diff --git a/mods/PLAYER/mcl_meshhand/init.lua b/mods/PLAYER/mcl_meshhand/init.lua index 864a7c20b..a28efd502 100644 --- a/mods/PLAYER/mcl_meshhand/init.lua +++ b/mods/PLAYER/mcl_meshhand/init.lua @@ -91,6 +91,10 @@ else minetest.register_on_joinplayer(mcl_meshhand.update_player) end +minetest.register_on_joinplayer(function(player) + player:get_inventory():set_size("hand", 1) +end) + -- This is needed to deal damage when punching mobs -- with random items in hand in survival mode minetest.override_item("", { diff --git a/mods/PLAYER/mcl_player_init/init.lua b/mods/PLAYER/mcl_player_init/init.lua deleted file mode 100644 index 52967a441..000000000 --- a/mods/PLAYER/mcl_player_init/init.lua +++ /dev/null @@ -1,4 +0,0 @@ -minetest.register_on_joinplayer(function(player) - -- Settable hand - player:get_inventory():set_size("hand", 1) -end) diff --git a/mods/PLAYER/mcl_player_init/mod.conf b/mods/PLAYER/mcl_player_init/mod.conf deleted file mode 100644 index d7a86c438..000000000 --- a/mods/PLAYER/mcl_player_init/mod.conf +++ /dev/null @@ -1,3 +0,0 @@ -name = mcl_player_init -author = Wuzzy -description = Initialize player gameplay stuff that are neither model nor HUD-related From f8e994ae78ac3a5600e98862f96b7fe83c6b62ec Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Tue, 28 Mar 2023 01:43:25 +0100 Subject: [PATCH 018/155] Create new dtime timer utility. --- mods/CORE/mcl_util/init.lua | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/mods/CORE/mcl_util/init.lua b/mods/CORE/mcl_util/init.lua index b6c0956cd..601a46c9f 100644 --- a/mods/CORE/mcl_util/init.lua +++ b/mods/CORE/mcl_util/init.lua @@ -34,6 +34,36 @@ function mcl_util.mcl_log(message, module, bypass_default_logger) end end +-- This is a dtime timer than can be used in on_step functions so it works every x seconds +-- self - Object you want to store timer data on. E.g. mob or a minecart +-- dtime - The time since last run of on_step, should be passed in to function +-- timer_name - This is the name of the timer and also the key to store the data. No spaces + lowercase. +-- threshold - The time before it returns successful. 0.2 if you want to run it 5 times a second. +function mcl_util.check_dtime_timer(self, dtime, timer_name, threshold) + if not self or not threshold or not dtime then return end + if not timer_name or timer_name == "" then return end + + if not self._timers then + self._timers = {} + end + + if not self._timers[timer_name] then + self._timers[timer_name] = 0 + else + self._timers[timer_name] = self._timers[timer_name] + dtime + --minetest.log("dtime: " .. tostring(self._timers[timer_name])) + end + + if self._timers[timer_name] > threshold then + --minetest.log("Over threshold") + self._timers[timer_name] = 0 + return true + --else + --minetest.log("Not over threshold") + end + return false +end + function mcl_util.file_exists(name) if type(name) ~= "string" then return end local f = io.open(name) From 59f4a62fd643005489402fddf155cb57ba809bc0 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Tue, 28 Mar 2023 01:51:51 +0100 Subject: [PATCH 019/155] Move hopper minecarts off item entity. Do not run every on_step. Use more accurate object search location. Cut down object search distance. --- mods/ENTITIES/mcl_item_entity/init.lua | 120 +------------------ mods/ENTITIES/mcl_minecarts/init.lua | 153 ++++++++++++++++++++++--- 2 files changed, 141 insertions(+), 132 deletions(-) diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index 48a2f34cb..8ee718f59 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -7,12 +7,7 @@ local pool = {} local tick = false -local LOGGING_ON = minetest.settings:get_bool("mcl_logging_item_entities", false) -local function mcl_log(message) - if LOGGING_ON then - mcl_util.mcl_log(message, "[Item Entities]", true) - end -end + minetest.register_on_joinplayer(function(player) pool[player:get_player_name()] = 0 @@ -408,115 +403,7 @@ local function cxcz(o, cw, one, zero) return o end -local function hopper_take_item(self, pos) - --mcl_log("self.itemstring: ".. self.itemstring) - --mcl_log("self.itemstring: ".. minetest.pos_to_string(pos)) - local objs = minetest.get_objects_inside_radius(pos, 2) - - if objs and self.itemstring then - --mcl_log("there is an itemstring. Number of objs: ".. #objs) - - for k, v in pairs(objs) do - local ent = v:get_luaentity() - - -- Don't forget actual hoppers - if ent and ent.name == "mcl_minecarts:hopper_minecart" then - local taken_items = false - - mcl_log("ent.name: " .. tostring(ent.name)) - mcl_log("ent pos: " .. tostring(ent.object:get_pos())) - - local inv = mcl_entity_invs.load_inv(ent, 5) - - if not inv then - mcl_log("No inv") - return false - end - - local current_itemstack = ItemStack(self.itemstring) - - mcl_log("inv. size: " .. ent._inv_size) - if inv:room_for_item("main", current_itemstack) then - mcl_log("Room") - inv:add_item("main", current_itemstack) - self.object:get_luaentity().itemstring = "" - self.object:remove() - taken_items = true - else - mcl_log("no Room") - end - - if not taken_items then - local items_remaining = current_itemstack:get_count() - - -- This will take part of a floating item stack if no slot can hold the full amount - for i = 1, ent._inv_size, 1 do - local stack = inv:get_stack("main", i) - - mcl_log("i: " .. tostring(i)) - mcl_log("Items remaining: " .. items_remaining) - mcl_log("Name: " .. tostring(stack:get_name())) - - if current_itemstack:get_name() == stack:get_name() then - mcl_log("We have a match. Name: " .. tostring(stack:get_name())) - - local room_for = stack:get_stack_max() - stack:get_count() - mcl_log("Room for: " .. tostring(room_for)) - - if room_for == 0 then - -- Do nothing - mcl_log("No room") - elseif room_for < items_remaining then - mcl_log("We have more items remaining than space") - - items_remaining = items_remaining - room_for - stack:set_count(stack:get_stack_max()) - inv:set_stack("main", i, stack) - taken_items = true - else - local new_stack_size = stack:get_count() + items_remaining - stack:set_count(new_stack_size) - mcl_log("We have more than enough space. Now holds: " .. new_stack_size) - - inv:set_stack("main", i, stack) - items_remaining = 0 - - self.object:get_luaentity().itemstring = "" - self.object:remove() - - taken_items = true - break - end - - mcl_log("Count: " .. tostring(stack:get_count())) - mcl_log("stack max: " .. tostring(stack:get_stack_max())) - --mcl_log("Is it empty: " .. stack:to_string()) - end - - if i == ent._inv_size and taken_items then - mcl_log("We are on last item and still have items left. Set final stack size: " .. items_remaining) - current_itemstack:set_count(items_remaining) - --mcl_log("Itemstack2: " .. current_itemstack:to_string()) - self.itemstring = current_itemstack:to_string() - end - end - end - - --Add in, and delete - if taken_items then - mcl_log("Saving") - mcl_entity_invs.save_inv(ent) - return taken_items - else - mcl_log("No need to save") - end - end - end - end - - return false -end minetest.register_entity(":__builtin:item", { initial_properties = { @@ -793,11 +680,6 @@ minetest.register_entity(":__builtin:item", { end local p = self.object:get_pos() - -- If hopper has taken item, it has gone, and no operations should be conducted on this item - if hopper_take_item(self, p) then - return - end - local node = minetest.get_node(p) local in_unloaded = node.name == "ignore" diff --git a/mods/ENTITIES/mcl_minecarts/init.lua b/mods/ENTITIES/mcl_minecarts/init.lua index aa9ef7edc..92136c37f 100644 --- a/mods/ENTITIES/mcl_minecarts/init.lua +++ b/mods/ENTITIES/mcl_minecarts/init.lua @@ -11,6 +11,14 @@ mcl_minecarts.check_float_time = 15 dofile(mcl_minecarts.modpath.."/functions.lua") dofile(mcl_minecarts.modpath.."/rails.lua") +local LOGGING_ON = minetest.settings:get_bool("mcl_logging_minecarts", false) +local function mcl_log(message) + if LOGGING_ON then + mcl_util.mcl_log(message, "[Minecarts]", true) + end +end + + local function detach_driver(self) if not self._driver then return @@ -51,6 +59,134 @@ end local activate_normal_minecart = detach_driver +local function hopper_take_item(self, dtime) + local pos = self.object:get_pos() + if not pos then return end + + if not self or self.name ~= "mcl_minecarts:hopper_minecart" then return end + + if mcl_util.check_dtime_timer(self, dtime, "hoppermc_take", 0.15) then + --minetest.log("The check timer was triggered: " .. dump(pos) .. ", name:" .. self.name) + else + --minetest.log("The check timer was not triggered") + return + end + + --mcl_log("self.itemstring: ".. self.itemstring) + + local above_pos = vector.offset(pos, 0, 0.9, 0) + --mcl_log("self.itemstring: ".. minetest.pos_to_string(above_pos)) + local objs = minetest.get_objects_inside_radius(above_pos, 1.25) + + if objs then + + mcl_log("there is an itemstring. Number of objs: ".. #objs) + + for k, v in pairs(objs) do + local ent = v:get_luaentity() + + if ent._removed or not ent.itemstring or ent.itemstring == "" then + --minetest.log("Ignore this item") + break + end + + -- Don't forget actual hoppers + + local taken_items = false + + mcl_log("ent.name: " .. tostring(ent.name)) + mcl_log("ent pos: " .. tostring(ent.object:get_pos())) + + local inv = mcl_entity_invs.load_inv(self, 5) + + if not inv then + mcl_log("No inv") + return false + end + + local current_itemstack = ItemStack(ent.itemstring) + + mcl_log("inv. size: " .. self._inv_size) + if inv:room_for_item("main", current_itemstack) then + mcl_log("Room") + inv:add_item("main", current_itemstack) + ent.object:get_luaentity().itemstring = "" + ent.object:remove() + taken_items = true + else + mcl_log("no Room") + end + + if not taken_items then + local items_remaining = current_itemstack:get_count() + + -- This will take part of a floating item stack if no slot can hold the full amount + for i = 1, self._inv_size, 1 do + local stack = inv:get_stack("main", i) + + mcl_log("i: " .. tostring(i)) + mcl_log("Items remaining: " .. items_remaining) + mcl_log("Name: " .. tostring(stack:get_name())) + + if current_itemstack:get_name() == stack:get_name() then + mcl_log("We have a match. Name: " .. tostring(stack:get_name())) + + local room_for = stack:get_stack_max() - stack:get_count() + mcl_log("Room for: " .. tostring(room_for)) + + if room_for == 0 then + -- Do nothing + mcl_log("No room") + elseif room_for < items_remaining then + mcl_log("We have more items remaining than space") + + items_remaining = items_remaining - room_for + stack:set_count(stack:get_stack_max()) + inv:set_stack("main", i, stack) + taken_items = true + else + local new_stack_size = stack:get_count() + items_remaining + stack:set_count(new_stack_size) + mcl_log("We have more than enough space. Now holds: " .. new_stack_size) + + inv:set_stack("main", i, stack) + items_remaining = 0 + + ent.object:get_luaentity().itemstring = "" + ent.object:remove() + + taken_items = true + break + end + + mcl_log("Count: " .. tostring(stack:get_count())) + mcl_log("stack max: " .. tostring(stack:get_stack_max())) + --mcl_log("Is it empty: " .. stack:to_string()) + end + + if i == self._inv_size and taken_items then + mcl_log("We are on last item and still have items left. Set final stack size: " .. items_remaining) + current_itemstack:set_count(items_remaining) + --mcl_log("Itemstack2: " .. current_itemstack:to_string()) + ent.itemstring = current_itemstack:to_string() + end + end + end + + --Add in, and delete + if taken_items then + mcl_log("Saving") + mcl_entity_invs.save_inv(ent) + return taken_items + else + mcl_log("No need to save") + end + end + end + + return false +end + -- Table for item-to-entity mapping. Keys: itemstring, Values: Corresponding entity ID local entity_mapping = {} @@ -182,6 +318,8 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o local passenger_attach_position = vector.new(0, -1.75, 0) function cart:on_step(dtime) + hopper_take_item(self, dtime) + local ctrl, player = nil, nil if self._driver then player = minetest.get_player_by_name(self._driver) @@ -266,19 +404,8 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o return end - -- Drop items and remove cart entity - local pname = "" - if player then - pname = player:get_player_name() - end - if not minetest.is_creative_enabled(pname) then - for d=1, #drop do - minetest.add_item(self.object:get_pos(), drop[d]) - end - end - - self.object:remove() - return + -- Do not drop minecart. It goes off the rails too frequently, and anyone using them for farms won't + -- notice and lose their iron and not bother. Not cool until fixed. end self._last_float_check = 0 end From 53923dd5fa8afd281ec85e900a008d98d3f31975 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Tue, 28 Mar 2023 18:06:25 +0100 Subject: [PATCH 020/155] Move on_step code to functions to help see profiling impact --- mods/ENTITIES/mcl_item_entity/init.lua | 331 +++++++++++++------------ 1 file changed, 171 insertions(+), 160 deletions(-) diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index 8ee718f59..0ebee0d05 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -403,7 +403,174 @@ local function cxcz(o, cw, one, zero) return o end +local function nodes_destroy_items (self, moveresult, def, nn) + local lg = minetest.get_item_group(nn, "lava") + local fg = minetest.get_item_group(nn, "fire") + local dg = minetest.get_item_group(nn, "destroys_items") + if (def and (lg ~= 0 or fg ~= 0 or dg == 1)) then + --Wait 2 seconds to allow mob drops to be cooked, & picked up instead of instantly destroyed. + if self.age > 2 and minetest.get_item_group(self.itemstring, "fire_immune") == 0 then + if dg ~= 2 then + minetest.sound_play("builtin_item_lava", { pos = self.object:get_pos(), gain = 0.5 }) + end + self._removed = true + self.object:remove() + return true + 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 + -- TODO We need to play a sound when it gets destroyed + self._removed = true + self.object:remove() + return true + end + end + end +end + +local function push_out_item_stuck_in_solid(self, dtime, p, def, is_in_water) + if not is_in_water and def and def.walkable and def.groups and def.groups.opaque == 1 then + local shootdir + local cx = (p.x % 1) - 0.5 + local cz = (p.z % 1) - 0.5 + local order = {} + + -- First prepare the order in which the 4 sides are to be checked. + -- 1st: closest + -- 2nd: other direction + -- 3rd and 4th: other axis + if math.abs(cx) < math.abs(cz) then + order = cxcz(order, cx, "x", "z") + order = cxcz(order, cz, "z", "x") + else + order = cxcz(order, cz, "z", "x") + order = cxcz(order, cx, "x", "z") + end + + -- Check which one of the 4 sides is free + for o = 1, #order do + local nn = minetest.get_node(vector.add(p, order[o])).name + local def = minetest.registered_nodes[nn] + if def and def.walkable == false and nn ~= "ignore" then + shootdir = order[o] + break + end + end + -- If none of the 4 sides is free, shoot upwards + if shootdir == nil then + shootdir = vector.new(0, 1, 0) + local nn = minetest.get_node(vector.add(p, shootdir)).name + if nn == "ignore" then + -- Do not push into ignore + return true + end + end + + -- Set new item moving speed accordingly + local newv = vector.multiply(shootdir, 3) + self.object:set_acceleration(vector.zero()) + self.object:set_velocity(newv) + disable_physics(self.object, self, false, false) + + + if shootdir.y == 0 then + self._force = newv + p.x = math.floor(p.x) + p.y = math.floor(p.y) + p.z = math.floor(p.z) + self._forcestart = p + self._forcetimer = 1 + end + return true + end + + -- This code is run after the entity got a push from above “push away” code. + -- It is responsible for making sure the entity is entirely outside the solid node + -- (with its full collision box), not just its center. + if self._forcetimer > 0 then + local cbox = self.object:get_properties().collisionbox + local ok = false + if self._force.x > 0 and (p.x > (self._forcestart.x + 0.5 + (cbox[4] - cbox[1]) / 2)) then ok = true + elseif self._force.x < 0 and (p.x < (self._forcestart.x + 0.5 - (cbox[4] - cbox[1]) / 2)) then ok = true + elseif self._force.z > 0 and (p.z > (self._forcestart.z + 0.5 + (cbox[6] - cbox[3]) / 2)) then ok = true + elseif self._force.z < 0 and (p.z < (self._forcestart.z + 0.5 - (cbox[6] - cbox[3]) / 2)) then ok = true end + -- Item was successfully forced out. No more pushing + if ok then + self._forcetimer = -1 + self._force = nil + enable_physics(self.object, self) + else + self._forcetimer = self._forcetimer - dtime + end + return true + elseif self._force then + self._force = nil + enable_physics(self.object, self) + return true + end +end + +local function move_items_in_water (self, p, def, node, is_floating, is_in_water) + -- Move item around on flowing liquids; add 'source' check to allow items to continue flowing a bit in the source block of flowing water. + if def and not is_floating and (def.liquidtype == "flowing" or def.liquidtype == "source") then + self._flowing = true + + --[[ Get flowing direction (function call from flowlib), if there's a liquid. + NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7. + Luckily, this is exactly what we need if we only care about water, which has this flowing distance. ]] + local vec = flowlib.quick_flow(p, node) + -- Just to make sure we don't manipulate the speed for no reason + if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then + -- Minecraft Wiki: Flowing speed is "about 1.39 meters per second" + local f = 1.2 + -- Set new item moving speed into the direciton of the liquid + local newv = vector.multiply(vec, f) + -- Swap to acceleration instead of a static speed to better mimic MC mechanics. + self.object:set_acceleration(vector.new(newv.x, -0.22, newv.z)) + + self.physical_state = true + self._flowing = true + self.object:set_properties({ + physical = true + }) + return true + end + if is_in_water and def.liquidtype == "source" then + local cur_vec = self.object:get_velocity() + -- apply some acceleration in the opposite direction so it doesn't slide forever + local vec = { + x = 0 - cur_vec.x * 0.9, + y = 3 - cur_vec.y * 0.9, + z = 0 - cur_vec.z * 0.9 + } + self.object:set_acceleration(vec) + -- slow down the item in water + local vel = self.object:get_velocity() + if vel.y < 0 then + vel.y = vel.y * 0.9 + end + self.object:set_velocity(vel) + if self.physical_state ~= false or self._flowing ~= true then + self.physical_state = true + self._flowing = true + self.object:set_properties({ + physical = true + }) + end + end + elseif self._flowing == true and not is_in_water and not is_floating then + -- Disable flowing physics if not on/in flowing liquid + self._flowing = false + enable_physics(self.object, self, true) + return true + end +end minetest.register_entity(":__builtin:item", { initial_properties = { @@ -672,8 +839,7 @@ minetest.register_entity(":__builtin:item", { -- otherwise there might have some data corruption. if self.itemstring == "" then minetest.log("warning", - "Item entity with empty itemstring found at " .. minetest.pos_to_string(self.object:get_pos()) .. - "! Deleting it now.") + "Item entity with empty itemstring found and being deleted at: " .. minetest.pos_to_string(self.object:get_pos())) self._removed = true self.object:remove() return @@ -724,167 +890,12 @@ minetest.register_entity(":__builtin:item", { -- Destroy item in lava, fire or special nodes local def = minetest.registered_nodes[nn] - local lg = minetest.get_item_group(nn, "lava") - local fg = minetest.get_item_group(nn, "fire") - local dg = minetest.get_item_group(nn, "destroys_items") - if (def and (lg ~= 0 or fg ~= 0 or dg == 1)) then - --Wait 2 seconds to allow mob drops to be cooked, & picked up instead of instantly destroyed. - if self.age > 2 and minetest.get_item_group(self.itemstring, "fire_immune") == 0 then - if dg ~= 2 then - minetest.sound_play("builtin_item_lava", { pos = self.object:get_pos(), gain = 0.5 }) - end - self._removed = true - self.object:remove() - return - 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 + if nodes_destroy_items(self, moveresult, def, nn) then return end - -- Push item out when stuck inside solid opaque node - if not is_in_water and def and def.walkable and def.groups and def.groups.opaque == 1 then - local shootdir - local cx = (p.x % 1) - 0.5 - local cz = (p.z % 1) - 0.5 - local order = {} + if push_out_item_stuck_in_solid(self, dtime, p, def, is_in_water) then return end - -- First prepare the order in which the 4 sides are to be checked. - -- 1st: closest - -- 2nd: other direction - -- 3rd and 4th: other axis - if math.abs(cx) < math.abs(cz) then - order = cxcz(order, cx, "x", "z") - order = cxcz(order, cz, "z", "x") - else - order = cxcz(order, cz, "z", "x") - order = cxcz(order, cx, "x", "z") - end - - -- Check which one of the 4 sides is free - for o = 1, #order do - local nn = minetest.get_node(vector.add(p, order[o])).name - local def = minetest.registered_nodes[nn] - if def and def.walkable == false and nn ~= "ignore" then - shootdir = order[o] - break - end - end - -- If none of the 4 sides is free, shoot upwards - if shootdir == nil then - shootdir = vector.new(0, 1, 0) - local nn = minetest.get_node(vector.add(p, shootdir)).name - if nn == "ignore" then - -- Do not push into ignore - return - end - end - - -- Set new item moving speed accordingly - local newv = vector.multiply(shootdir, 3) - self.object:set_acceleration(vector.zero()) - self.object:set_velocity(newv) - disable_physics(self.object, self, false, false) - - - if shootdir.y == 0 then - self._force = newv - p.x = math.floor(p.x) - p.y = math.floor(p.y) - p.z = math.floor(p.z) - self._forcestart = p - self._forcetimer = 1 - end - return - end - - -- This code is run after the entity got a push from above “push away” code. - -- It is responsible for making sure the entity is entirely outside the solid node - -- (with its full collision box), not just its center. - if self._forcetimer > 0 then - local cbox = self.object:get_properties().collisionbox - local ok = false - if self._force.x > 0 and (p.x > (self._forcestart.x + 0.5 + (cbox[4] - cbox[1]) / 2)) then ok = true - elseif self._force.x < 0 and (p.x < (self._forcestart.x + 0.5 - (cbox[4] - cbox[1]) / 2)) then ok = true - elseif self._force.z > 0 and (p.z > (self._forcestart.z + 0.5 + (cbox[6] - cbox[3]) / 2)) then ok = true - elseif self._force.z < 0 and (p.z < (self._forcestart.z + 0.5 - (cbox[6] - cbox[3]) / 2)) then ok = true end - -- Item was successfully forced out. No more pushing - if ok then - self._forcetimer = -1 - self._force = nil - enable_physics(self.object, self) - else - self._forcetimer = self._forcetimer - dtime - end - return - elseif self._force then - self._force = nil - enable_physics(self.object, self) - return - end - - -- Move item around on flowing liquids; add 'source' check to allow items to continue flowing a bit in the source block of flowing water. - if def and not is_floating and (def.liquidtype == "flowing" or def.liquidtype == "source") then - self._flowing = true - - --[[ Get flowing direction (function call from flowlib), if there's a liquid. - NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7. - Luckily, this is exactly what we need if we only care about water, which has this flowing distance. ]] - local vec = flowlib.quick_flow(p, node) - -- Just to make sure we don't manipulate the speed for no reason - if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then - -- Minecraft Wiki: Flowing speed is "about 1.39 meters per second" - local f = 1.2 - -- Set new item moving speed into the direciton of the liquid - local newv = vector.multiply(vec, f) - -- Swap to acceleration instead of a static speed to better mimic MC mechanics. - self.object:set_acceleration(vector.new(newv.x, -0.22, newv.z)) - - self.physical_state = true - self._flowing = true - self.object:set_properties({ - physical = true - }) - return - end - if is_in_water and def.liquidtype == "source" then - local cur_vec = self.object:get_velocity() - -- apply some acceleration in the opposite direction so it doesn't slide forever - local vec = { - x = 0 - cur_vec.x * 0.9, - y = 3 - cur_vec.y * 0.9, - z = 0 - cur_vec.z * 0.9 - } - self.object:set_acceleration(vec) - -- slow down the item in water - local vel = self.object:get_velocity() - if vel.y < 0 then - vel.y = vel.y * 0.9 - end - self.object:set_velocity(vel) - if self.physical_state ~= false or self._flowing ~= true then - self.physical_state = true - self._flowing = true - self.object:set_properties({ - physical = true - }) - end - end - elseif self._flowing == true and not is_in_water and not is_floating then - -- Disable flowing physics if not on/in flowing liquid - self._flowing = false - enable_physics(self.object, self, true) - return - end + if move_items_in_water (self, p, def, node, is_floating, is_in_water) then return end -- If node is not registered or node is walkably solid and resting on nodebox local nn = minetest.get_node(vector.offset(p, 0, -0.5, 0)).name From f7bdf7481c702da2e0e2f8df7c591d176ba7b040 Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Mon, 27 Mar 2023 11:02:51 -0600 Subject: [PATCH 021/155] Update ruined portal loot table --- mods/MAPGEN/mcl_structures/ruined_portal.lua | 45 +++++++++++++++----- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/mods/MAPGEN/mcl_structures/ruined_portal.lua b/mods/MAPGEN/mcl_structures/ruined_portal.lua index 00d2d682c..0f7df6686 100644 --- a/mods/MAPGEN/mcl_structures/ruined_portal.lua +++ b/mods/MAPGEN/mcl_structures/ruined_portal.lua @@ -49,8 +49,8 @@ local def = { end, loot = { ["mcl_chests:chest_small" ] ={{ - stacks_min = 2, - stacks_max = 6, + stacks_min = 4, + stacks_max = 8, items = { { itemstring = "mcl_core:iron_nugget", weight = 40, amount_min = 9, amount_max = 18 }, { itemstring = "mcl_core:flint", weight = 40, amount_min = 1, amount_max=4 }, @@ -60,19 +60,44 @@ local def = { { itemstring = "mcl_core:gold_nugget", weight = 15, amount_min = 4, amount_max = 24 }, { itemstring = "mcl_core:apple_gold", weight = 15, }, - { itemstring = "mcl_books:book", weight = 1, func = function(stack, pr) + { itemstring = "mcl_tools:axe_gold", weight = 15, func = function(stack, pr) + mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) + end }, + { itemstring = "mcl_farming:hoe_gold", weight = 15, func = function(stack, pr) + mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) + end }, + { itemstring = "mcl_tools:pick_gold", weight = 15, func = function(stack, pr) + mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) + end }, + { itemstring = "mcl_tools:shovel_gold", weight = 15, func = function(stack, pr) + mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) + end }, + { itemstring = "mcl_tools:sword_gold", weight = 15, func = function(stack, pr) mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) end }, - --{ itemstring = "mcl_bamboo:bamboo", weight = 15, amount_min = 1, amount_max=3 }, --FIXME BAMBOO - { itemstring = "mcl_core:diamond", weight = 3, amount_min = 1, amount_max = 3 }, - { itemstring = "mcl_mobitems:saddle", weight = 3, }, - { itemstring = "mcl_core:emerald", weight = 2, amount_min = 1, amount_max = 3 }, + { itemstring = "mcl_armor:helmet_gold", weight = 15, func = function(stack, pr) + mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) + end }, + { itemstring = "mcl_armor:chestplate_gold", weight = 15, func = function(stack, pr) + mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) + end }, + { itemstring = "mcl_armor:leggings_gold", weight = 15, func = function(stack, pr) + mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) + end }, + { itemstring = "mcl_armor:boots_gold", weight = 15, func = function(stack, pr) + mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) + end }, - { itemstring = "mcl_mobitems:iron_horse_armor", weight = 1, }, + { itemstring = "mcl_potions:speckled_melon", weight = 5, amount_min = 4, amount_max = 12 }, + { itemstring = "mcl_farming:carrot_item_gold", weight = 5, amount_min = 4, amount_max = 12 }, + + { itemstring = "mcl_core:gold_ingot", weight = 5, amount_min = 2, amount_max = 8 }, + { itemstring = "mcl_clock:clock", weight = 5, }, { itemstring = "mcl_mobitems:gold_horse_armor", weight = 1, }, - { itemstring = "mcl_mobitems:diamond_horse_armor", weight = 1, }, - { itemstring = "mcl_core:apple_gold", weight = 15, }, + { itemstring = "mcl_core:goldblock", weight = 1, amount_min = 1, amount_max = 2 }, + { itemstring = "mcl_bells:bell", weight = 1, }, + { itemstring = "mcl_core:apple_gold_enchanted", weight = 1, }, } }} } From 0abc0ffc48099dc5db5e813a10313bdde30336e1 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Thu, 30 Mar 2023 01:46:29 +0100 Subject: [PATCH 022/155] Mapgen optimisations --- mods/MAPGEN/mcl_biomes/init.lua | 106 +++++++++++++++++---------- mods/MAPGEN/mcl_mapgen_core/init.lua | 23 ++++-- 2 files changed, 84 insertions(+), 45 deletions(-) diff --git a/mods/MAPGEN/mcl_biomes/init.lua b/mods/MAPGEN/mcl_biomes/init.lua index 30e3fac2d..ddb537b39 100644 --- a/mods/MAPGEN/mcl_biomes/init.lua +++ b/mods/MAPGEN/mcl_biomes/init.lua @@ -6066,50 +6066,82 @@ if mg_name ~= "singlenode" then for _, f in pairs(deco_ids_trees) do minetest.set_gen_notify({decoration = true}, {f}) end + + local function mangrove_roots_gen(gennotify, pr) + for _, f in pairs(deco_ids_trees) do + for _, pos in ipairs(gennotify["decoration#" .. f] or {}) do + local nn = minetest.find_nodes_in_area(vector.offset(pos, -8, -1, -8), vector.offset(pos, 8, 0, 8), {"mcl_mangrove:mangrove_roots"}) + for _, v in pairs(nn) do + local l = pr:next(2, 16) + local n = minetest.get_node(vector.offset(v, 0, -1, 0)).name + if minetest.get_item_group(n, "water") > 0 then + local wl = "mcl_mangrove:water_logged_roots" + if n:find("river") then + wl = "mcl_mangrove:river_water_logged_roots" + end + minetest.bulk_set_node(minetest.find_nodes_in_area(vector.offset(v, 0, 0, 0), vector.offset(v, 0, -l, 0), {"group:water"}), {name = wl}) + elseif n == "mcl_mud:mud" then + minetest.bulk_set_node(minetest.find_nodes_in_area(vector.offset(v, 0, 0, 0), vector.offset(v, 0, -l, 0), {"mcl_mud:mud"}), {name = "mcl_mangrove:mangrove_mud_roots"}) + elseif n == "air" then + minetest.bulk_set_node(minetest.find_nodes_in_area(vector.offset(v, 0, 0, 0), vector.offset(v, 0, -l, 0), {"air"}), {name = "mcl_mangrove:mangrove_roots"}) + end + end + end + end + end + + local function chorus_gen (gennotify, pr) + for _, pos in ipairs(gennotify["decoration#" .. deco_id_chorus_plant] or {}) do + local x, y, z = pos.x, pos.y, pos.z + if x < -10 or x > 10 or z < -10 or z > 10 then + local realpos = {x = x, y = y + 1, z = z} + local node = minetest.get_node(realpos) + if node and node.name == "mcl_end:chorus_flower" then + mcl_end.grow_chorus_plant(realpos, node, pr) + end + end + end + end + + local function crimson_warped_gen(gennotify) + for _, f in pairs(deco_ids_fungus) do + for _, pos in ipairs(gennotify["decoration#" .. f] or {}) do + minetest.fix_light(vector.offset(pos, -8, -8, -8), vector.offset(pos, 8, 8, 8)) + end + end + end + if deco_id_chorus_plant or deco_ids_fungus or deco_ids_trees then mcl_mapgen_core.register_generator("chorus_grow", nil, function(minp, maxp, blockseed) local gennotify = minetest.get_mapgen_object("gennotify") local pr = PseudoRandom(blockseed + 14) - for _, f in pairs(deco_ids_trees) do - for _, pos in ipairs(gennotify["decoration#" .. f] or {}) do - local nn = minetest.find_nodes_in_area(vector.offset(pos, -8, -1, -8), vector.offset(pos, 8, 0, 8), {"mcl_mangrove:mangrove_roots"}) - for _, v in pairs(nn) do - local l = pr:next(2, 16) - local n = minetest.get_node(vector.offset(v, 0, -1, 0)).name - if minetest.get_item_group(n, "water") > 0 then - local wl = "mcl_mangrove:water_logged_roots" - if n:find("river") then - wl = "mcl_mangrove:river_water_logged_roots" - end - minetest.bulk_set_node(minetest.find_nodes_in_area(vector.offset(v, 0, 0, 0), vector.offset(v, 0, -l, 0), {"group:water"}), {name = wl}) - elseif n == "mcl_mud:mud" then - minetest.bulk_set_node(minetest.find_nodes_in_area(vector.offset(v, 0, 0, 0), vector.offset(v, 0, -l, 0), {"mcl_mud:mud"}), {name = "mcl_mangrove:mangrove_mud_roots"}) - elseif n == "air" then - minetest.bulk_set_node(minetest.find_nodes_in_area(vector.offset(v, 0, 0, 0), vector.offset(v, 0, -l, 0), {"air"}), {name = "mcl_mangrove:mangrove_roots"}) - end - end + + if not (maxp.y < mcl_vars.mg_overworld_min or minp.y > mcl_vars.mg_overworld_max) then + local biomemap = minetest.get_mapgen_object("biomemap") + --minetest.log("mangrove stuff: " .. dump(biomemap)) + local swamp_biome_id = minetest.get_biome_id("MangroveSwamp") + local swamp_shore_id = minetest.get_biome_id("MangroveSwamp_shore") + local is_swamp = table.indexof(biomemap, swamp_biome_id) ~= -1 + local is_swamp_shore = table.indexof(biomemap, swamp_shore_id) ~= -1 + + if is_swamp or is_swamp_shore then + --minetest.log("Mangrove swamp biomes...") + --minetest.log("is_swamp: " .. dump(is_swamp)) + --minetest.log("is_swamp_shore: " .. dump(is_swamp_shore)) + mangrove_roots_gen(gennotify, pr) + else + --minetest.log("is not mangrove swamp biomes...") end end - if minp.y > -26900 then - return + + if not (maxp.y < mcl_vars.mg_end_min or minp.y > mcl_vars.mg_end_max) then + --minetest.log("chorus stuff") + chorus_gen(gennotify, pr) end - for _, pos in ipairs(gennotify["decoration#" .. deco_id_chorus_plant] or {}) do - local x, y, z = pos.x, pos.y, pos.z - if x < -10 or x > 10 or z < -10 or z > 10 then - local realpos = {x = x, y = y + 1, z = z} - local node = minetest.get_node(realpos) - if node and node.name == "mcl_end:chorus_flower" then - mcl_end.grow_chorus_plant(realpos, node, pr) - end - end - end - if minp.y > mcl_vars.mg_nether_max then - return - end - for _, f in pairs(deco_ids_fungus) do - for _, pos in ipairs(gennotify["decoration#" .. f] or {}) do - minetest.fix_light(vector.offset(pos, -8, -8, -8), vector.offset(pos, 8, 8, 8)) - end + + if not (maxp.y < mcl_vars.mg_nether_min or minp.y > mcl_vars.mg_nether_max) then + --minetest.log("nether stuff") + crimson_warped_gen(gennotify) end end) end diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index b9d0e5b48..9e401a4ff 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -346,14 +346,21 @@ local function world_structure(vm, data, data2, emin, emax, area, minp, maxp, bl end local function block_fixes_grass(vm, data, data2, emin, emax, area, minp, maxp, blockseed) - local biomemap = minetest.get_mapgen_object("biomemap") - local lvm_used = false - local pr = PseudoRandom(blockseed) - if minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min then - -- Set param2 (=color) of nodes which use the grass colour palette. - lvm_used = set_grass_palette(minp,maxp,data2,area,biomemap,{"group:grass_palette"}) - end - return lvm_used + if maxp.y < mcl_vars.mg_overworld_min then + --minetest.log("Exit grass fix") + return + else + --minetest.log("Grass fixes") + end + + local biomemap = minetest.get_mapgen_object("biomemap") + local lvm_used = false + + if minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min then + -- Set param2 (=color) of nodes which use the grass colour palette. + lvm_used = set_grass_palette(minp,maxp,data2,area,biomemap,{"group:grass_palette"}) + end + return lvm_used end From 771044236f80032a5c09b2f9107a5411cacfe57e Mon Sep 17 00:00:00 2001 From: Johannes Fritz Date: Wed, 29 Mar 2023 10:45:11 -0500 Subject: [PATCH 023/155] Don't drop beds in creative --- mods/ITEMS/mcl_beds/api.lua | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/mods/ITEMS/mcl_beds/api.lua b/mods/ITEMS/mcl_beds/api.lua index 05a95f79d..9d46eca39 100644 --- a/mods/ITEMS/mcl_beds/api.lua +++ b/mods/ITEMS/mcl_beds/api.lua @@ -4,7 +4,6 @@ local minetest_get_node = minetest.get_node local minetest_get_node_or_nil = minetest.get_node_or_nil local minetest_remove_node = minetest.remove_node local minetest_facedir_to_dir = minetest.facedir_to_dir -local minetest_add_item = minetest.add_item local vector_add = vector.add local vector_subtract = vector.subtract @@ -85,7 +84,6 @@ local function destruct_bed(pos, oldnode) local pos2, node2, bottom = get_bed_next_node(pos, oldnode) if bottom then - minetest_add_item(pos, node.name) if node2 and string.sub(node2.name, -4) == "_top" then minetest_remove_node(pos2) end @@ -158,7 +156,7 @@ function mcl_beds.register_bed(name, def) sounds = def.sounds or default_sounds, selection_box = common_box, collision_box = common_box, - drop = "", + drop = def.recipe and name or "", node_placement_prediction = "", on_place = function(itemstack, placer, pointed_thing) @@ -241,7 +239,7 @@ function mcl_beds.register_bed(name, def) _mcl_hardness = 0.2, _mcl_blast_resistance = 1, sounds = def.sounds or default_sounds, - drop = "", + drop = def.recipe and name or "", selection_box = common_box, collision_box = common_box, From 9c83755f533c76270428ece04ee9941f1db0614d Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Wed, 29 Mar 2023 17:28:13 -0600 Subject: [PATCH 024/155] Make banners drop when support node is dug and when banner node is dug --- mods/ITEMS/mcl_banners/init.lua | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mods/ITEMS/mcl_banners/init.lua b/mods/ITEMS/mcl_banners/init.lua index cc0e02e66..f50488b35 100644 --- a/mods/ITEMS/mcl_banners/init.lua +++ b/mods/ITEMS/mcl_banners/init.lua @@ -113,14 +113,6 @@ local function on_dig_banner(pos, node, digger) minetest.record_protection_violation(pos, name) return end - -- Drop item - local meta = minetest.get_meta(pos) - local item = meta:get_inventory():get_stack("banner", 1) - if not item:is_empty() then - minetest.handle_node_drops(pos, {item:to_string()}, digger) - else - minetest.handle_node_drops(pos, {"mcl_banners:banner_item_white"}, digger) - end -- Remove node minetest.remove_node(pos) end @@ -141,6 +133,14 @@ local function on_destruct_banner(pos, hanging) local ent = v:get_luaentity() if ent and ent.name == nodename then v:remove() + -- Drop item + local meta = minetest.get_meta(pos) + local item = meta:get_inventory():get_stack("banner", 1) + if not item:is_empty() then + minetest.handle_node_drops(pos, {item:to_string()}, digger) + else + minetest.handle_node_drops(pos, {"mcl_banners:banner_item_white"}, digger) + end end end end From a98f79763bcaa453501512a7454e8b177838ea52 Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Wed, 29 Mar 2023 17:31:23 -0600 Subject: [PATCH 025/155] Remove unused digger variable that I forgot --- mods/ITEMS/mcl_banners/init.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_banners/init.lua b/mods/ITEMS/mcl_banners/init.lua index f50488b35..b1e9070c6 100644 --- a/mods/ITEMS/mcl_banners/init.lua +++ b/mods/ITEMS/mcl_banners/init.lua @@ -137,9 +137,9 @@ local function on_destruct_banner(pos, hanging) local meta = minetest.get_meta(pos) local item = meta:get_inventory():get_stack("banner", 1) if not item:is_empty() then - minetest.handle_node_drops(pos, {item:to_string()}, digger) + minetest.handle_node_drops(pos, {item:to_string()}) else - minetest.handle_node_drops(pos, {"mcl_banners:banner_item_white"}, digger) + minetest.handle_node_drops(pos, {"mcl_banners:banner_item_white"}) end end end From 088922dc33d0f6bca2369dd35d1455079399bd6a Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Wed, 29 Mar 2023 17:37:04 -0600 Subject: [PATCH 026/155] Make sure banner drops, even if banner entity doesn't exist --- mods/ITEMS/mcl_banners/init.lua | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mods/ITEMS/mcl_banners/init.lua b/mods/ITEMS/mcl_banners/init.lua index b1e9070c6..bd71338ee 100644 --- a/mods/ITEMS/mcl_banners/init.lua +++ b/mods/ITEMS/mcl_banners/init.lua @@ -133,16 +133,16 @@ local function on_destruct_banner(pos, hanging) local ent = v:get_luaentity() if ent and ent.name == nodename then v:remove() - -- Drop item - local meta = minetest.get_meta(pos) - local item = meta:get_inventory():get_stack("banner", 1) - if not item:is_empty() then - minetest.handle_node_drops(pos, {item:to_string()}) - else - minetest.handle_node_drops(pos, {"mcl_banners:banner_item_white"}) - end end end + -- Drop item + local meta = minetest.get_meta(pos) + local item = meta:get_inventory():get_stack("banner", 1) + if not item:is_empty() then + minetest.handle_node_drops(pos, {item:to_string()}) + else + minetest.handle_node_drops(pos, {"mcl_banners:banner_item_white"}) + end end local function on_destruct_standing_banner(pos) From 80f038da4aa79e7f542c921377cf849cee0f1bf9 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Thu, 30 Mar 2023 20:10:10 +0100 Subject: [PATCH 027/155] Do not run kelp lbm every time --- mods/ITEMS/mcl_ocean/kelp.lua | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/mods/ITEMS/mcl_ocean/kelp.lua b/mods/ITEMS/mcl_ocean/kelp.lua index 8827546a3..7ddb4da7d 100644 --- a/mods/ITEMS/mcl_ocean/kelp.lua +++ b/mods/ITEMS/mcl_ocean/kelp.lua @@ -525,15 +525,6 @@ function kelp.lbm_register(pos) kelp.init_age(pos, nil, true) end -minetest.register_lbm({ - label = "Kelp initialise", - name = "mcl_ocean:kelp_init", - nodenames = { "group:kelp" }, - run_at_every_load = true, -- so old kelps are also initialised - action = kelp.lbm_register, -}) - - -------------------------------------------------------------------------------- -- Kelp registration API -------------------------------------------------------------------------------- @@ -725,6 +716,19 @@ minetest.register_craft({ burntime = 200, }) +-------------------------------------------------------------------------------- +-- Kelp ABM + LBM's +-------------------------------------------------------------------------------- + + +minetest.register_lbm({ + label = "Kelp initialise", + name = "mcl_ocean:kelp_init_83", + nodenames = { "group:kelp" }, + run_at_every_load = false, -- so old kelps are also initialised + action = kelp.lbm_register, +}) + minetest.register_abm({ label = "Kelp drops", nodenames = { "group:kelp" }, From 8edffeb40da191ce953af2c31537b00b173c3193 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Thu, 30 Mar 2023 23:39:57 +0100 Subject: [PATCH 028/155] Map gen kelp should init age also --- mods/ITEMS/mcl_ocean/kelp.lua | 75 ++++++++++++++--------------------- 1 file changed, 29 insertions(+), 46 deletions(-) diff --git a/mods/ITEMS/mcl_ocean/kelp.lua b/mods/ITEMS/mcl_ocean/kelp.lua index 7ddb4da7d..1084dfa77 100644 --- a/mods/ITEMS/mcl_ocean/kelp.lua +++ b/mods/ITEMS/mcl_ocean/kelp.lua @@ -216,41 +216,34 @@ local function store_age (pos, age) end end -local function retrieve_age (pos, include_nil) +local function retrieve_age (pos) local meta = mt_get_meta(pos) - - if include_nil then - local age_set = meta:contains("mcl_ocean:kelp_age") - if not age_set then - return nil - end + local age_set = meta:contains("mcl_ocean:kelp_age") + if not age_set then + return nil end - return meta:get_int("mcl_ocean:kelp_age") + + local age = meta:get_int("mcl_ocean:kelp_age") + --minetest.log("age: " .. tostring(age)) + return age end -- Initialise a kelp's age. -function kelp.init_age(pos, age, from_lbm) +function kelp.init_age(pos) -- Watched params: pos -- Optional params: age, from_lbm - local new_age + local age = retrieve_age(pos) - local stored_age = retrieve_age(pos, from_lbm) - - if age then - --minetest.log("age: " .. tostring(age)) - store_age(pos, age) - new_age = age - elseif not stored_age then - new_age = kelp.roll_init_age() + if not age then + age = kelp.roll_init_age() --minetest.log("no kelp age set so init with: " .. tostring(new_age)) - store_age(pos, new_age) + store_age(pos, age) else - --minetest.log("stored_age: " .. tostring(stored_age)) - new_age = stored_age + --minetest.log("stored_age: " .. tostring(age)) end - return new_age + return age end -- Apply next kelp height. The surface is swapped. so on_construct is skipped. @@ -380,27 +373,24 @@ end local function grow_kelp (pos) local node = mt_get_node(pos) + local age = retrieve_age(pos) - if kelp.roll_growth() then - local age = retrieve_age(pos) + if not age then + --minetest.log("init a new age as not set: " .. mt_pos_to_string(pos)) + age = kelp.init_age(pos) + end - if not age then - --minetest.log("init a new age as not set: " .. mt_pos_to_string(pos)) - kelp.init_age(pos, nil) - end - - if kelp.is_age_growable(age) then - --minetest.log("age growable: ".. tostring(age) .. ", pos: ".. mt_pos_to_string(pos)) - kelp.next_grow(age+1, pos, node) - else - --minetest.log("age not: ".. tostring(age) .. ", pos: ".. mt_pos_to_string(pos)) - end + if kelp.is_age_growable(age) then + --minetest.log("age growable: ".. tostring(age) .. ", pos: ".. mt_pos_to_string(pos)) + kelp.next_grow(age+1, pos, node) + else + --minetest.log("age not: ".. tostring(age) .. ", pos: ".. mt_pos_to_string(pos)) end end function kelp.surface_on_construct(pos) --minetest.log("on construct kelp called") - kelp.init_age(pos, nil) + kelp.init_age(pos) end @@ -509,20 +499,13 @@ function kelp.kelp_on_place(itemstack, placer, pointed_thing) itemstack:take_item() end - -- Initialize age and timer when it's planted on a new surface. - local init_age = kelp.roll_init_age() - - if new_surface then - kelp.init_age(pos_under, init_age) - else - store_age(pos_under, init_age) - end + kelp.init_age(pos_under) return itemstack end function kelp.lbm_register(pos) - kelp.init_age(pos, nil, true) + kelp.init_age(pos) end -------------------------------------------------------------------------------- @@ -749,7 +732,7 @@ minetest.register_abm({ minetest.register_abm({ label = "Kelp growth", nodenames = { "group:kelp" }, - interval = 17, --17 + interval = 17, chance = 28, catch_up = false, action = grow_kelp, From 3e6b43ad4784e03edc898e4063ca9966c8d0e36c Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Thu, 30 Mar 2023 22:24:42 +0100 Subject: [PATCH 029/155] Elytra moves quicker than mapgen can cope. A bit performance hit on servers. Make this configurable. --- mods/PLAYER/mcl_playerplus/init.lua | 23 +++++++++++++++-------- settingtypes.txt | 6 ++++++ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/mods/PLAYER/mcl_playerplus/init.lua b/mods/PLAYER/mcl_playerplus/init.lua index 0e774ee2f..8ace0a9a9 100644 --- a/mods/PLAYER/mcl_playerplus/init.lua +++ b/mods/PLAYER/mcl_playerplus/init.lua @@ -22,6 +22,20 @@ local math = math -- Internal player state local mcl_playerplus_internal = {} +-- Could occassionally hit about 4.6 but servers and high power machines struggle to keep up with this. +-- Until mapgen can keep up, it's best to limit for server performance etc. +local elytra_vars = { + slowdown_mult = 0.0, -- amount of vel to take per sec + fall_speed = 0.2, -- amount of vel to fall down per sec + speedup_mult = 2, -- amount of speed to add based on look dir + max_speed = tonumber(minetest.settings:get("mcl_elytra_max_speed")) or 4.0, -- was 6 max amount to multiply against look direction when flying + pitch_penalty = 1.3, -- if pitching up, slow down at this rate as a multiplier + rocket_speed = tonumber(minetest.settings:get("mcl_elytra_rocket_speed")) or 3.5, --was 5.5 +} + +--minetest.log("action", "elytra_vars.max_speed: " .. dump(elytra_vars.max_speed)) +--minetest.log("action", "elytra_vars.rocket_speed: " .. dump(elytra_vars.rocket_speed)) + local time = 0 local look_pitch = 0 @@ -136,14 +150,7 @@ local function clamp(num, min, max) return math.min(max, math.max(num, min)) end -local elytra_vars = { - slowdown_mult = 0.0, -- amount of vel to take per sec - fall_speed = 0.2, -- amount of vel to fall down per sec - speedup_mult = 2, -- amount of speed to add based on look dir - max_speed = 6, -- max amount to multiply against look direction when flying - pitch_penalty = 1.3, -- if pitching up, slow down at this rate as a multiplier - rocket_speed = 5.5, -} + local player_props_elytra = { collisionbox = { -0.35, 0, -0.35, 0.35, 0.8, 0.35 }, diff --git a/settingtypes.txt b/settingtypes.txt index 628641c54..00235e79d 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -61,6 +61,12 @@ mcl_playersSleepingPercentage (Players Sleeping Percentage) int 100 # setting, so players always keep their inventory on death. mcl_keepInventory (Keep inventory on death) bool false +# Elytra maximum speed cap +mcl_elytra_max_speed (Elytra maximum speed cap) float 4.0 2.5 6.0 + +# Elytra rocket speed cap +mcl_elytra_rocket_speed (Elytra rocket speed cap) float 3.5 2.0 5.5 + # If enabled, chat messages are shown to everyone when a player dies. mcl_showDeathMessages (Show death messages) bool true From 87bf3aed5992d46374e9bdad420e3c19dfb1783a Mon Sep 17 00:00:00 2001 From: MrRar Date: Sun, 2 Apr 2023 12:19:39 -0500 Subject: [PATCH 030/155] Don't drop banners in creative mode --- mods/ITEMS/mcl_banners/init.lua | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/mods/ITEMS/mcl_banners/init.lua b/mods/ITEMS/mcl_banners/init.lua index bd71338ee..18b50928a 100644 --- a/mods/ITEMS/mcl_banners/init.lua +++ b/mods/ITEMS/mcl_banners/init.lua @@ -113,6 +113,17 @@ local function on_dig_banner(pos, node, digger) minetest.record_protection_violation(pos, name) return end + + local inv = minetest.get_meta(pos):get_inventory() + local item = inv:get_stack("banner", 1) + local item_str = item:is_empty() and "mcl_banners:banner_item_white" + or item:to_string() + + minetest.handle_node_drops(pos, { item_str }, digger) + + item:set_count(0) + inv:set_stack("banner", 1, item) + -- Remove node minetest.remove_node(pos) end @@ -135,13 +146,12 @@ local function on_destruct_banner(pos, hanging) v:remove() end end - -- Drop item - local meta = minetest.get_meta(pos) - local item = meta:get_inventory():get_stack("banner", 1) + + -- Drop item only if it was not handled in on_dig_banner + local inv = minetest.get_meta(pos):get_inventory() + local item = inv:get_stack("banner", 1) if not item:is_empty() then minetest.handle_node_drops(pos, {item:to_string()}) - else - minetest.handle_node_drops(pos, {"mcl_banners:banner_item_white"}) end end From c83574802f6234d4f16ae1c9ceac44d27a8b6f04 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 3 Apr 2023 02:06:58 +0100 Subject: [PATCH 031/155] Ensure enchanted netherite armour is fire immune to lava etc. --- mods/ENTITIES/mcl_item_entity/init.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index 0ebee0d05..218689059 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -409,8 +409,14 @@ local function nodes_destroy_items (self, moveresult, def, nn) local dg = minetest.get_item_group(nn, "destroys_items") if (def and (lg ~= 0 or fg ~= 0 or dg == 1)) then + local item_name = self.itemstring + local name, _ = item_name:match"^(%S+)%s+(.+)" + if name then + item_name = name + end + --Wait 2 seconds to allow mob drops to be cooked, & picked up instead of instantly destroyed. - if self.age > 2 and minetest.get_item_group(self.itemstring, "fire_immune") == 0 then + if self.age > 2 and minetest.get_item_group(item_name, "fire_immune") == 0 then if dg ~= 2 then minetest.sound_play("builtin_item_lava", { pos = self.object:get_pos(), gain = 0.5 }) end From 6817a8535b1c05bdb1de698335387fe027a1c384 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 3 Apr 2023 17:50:48 +0100 Subject: [PATCH 032/155] Get item name correctly. --- mods/ENTITIES/mcl_item_entity/init.lua | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index 218689059..3103a1104 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -409,11 +409,8 @@ local function nodes_destroy_items (self, moveresult, def, nn) local dg = minetest.get_item_group(nn, "destroys_items") if (def and (lg ~= 0 or fg ~= 0 or dg == 1)) then - local item_name = self.itemstring - local name, _ = item_name:match"^(%S+)%s+(.+)" - if name then - item_name = name - end + local item_string = self.itemstring + local item_name = ItemStack(item_string):get_name() --Wait 2 seconds to allow mob drops to be cooked, & picked up instead of instantly destroyed. if self.age > 2 and minetest.get_item_group(item_name, "fire_immune") == 0 then From 93bc5bb5f8d98b0224db9498fe559a320ec9e26e Mon Sep 17 00:00:00 2001 From: Johannes Fritz Date: Mon, 3 Apr 2023 12:33:50 -0500 Subject: [PATCH 033/155] Slow down the pressure plate timer --- mods/ITEMS/REDSTONE/mesecons_pressureplates/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/REDSTONE/mesecons_pressureplates/init.lua b/mods/ITEMS/REDSTONE/mesecons_pressureplates/init.lua index 3dca8aa0c..41cc8211a 100644 --- a/mods/ITEMS/REDSTONE/mesecons_pressureplates/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_pressureplates/init.lua @@ -1,6 +1,6 @@ local S = minetest.get_translator(minetest.get_current_modname()) -local PRESSURE_PLATE_INTERVAL = 0.04 +local PRESSURE_PLATE_INTERVAL = 0.25 local pp_box_off = { type = "fixed", From 9c8463d2e336d7dea1ce63095daaeb6d97e5ad23 Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Wed, 5 Apr 2023 14:43:07 +0200 Subject: [PATCH 034/155] add basic bed-chat --- mods/ITEMS/mcl_beds/functions.lua | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index 294dfc483..58df7c65d 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -202,7 +202,7 @@ local function lay_down(player, pos, bed_pos, state, skip) return true end -local function update_formspecs(finished, ges) +local function update_formspecs(finished, ges, singlular_player) --singlular_player isn't a boolean, just a player thats allowed to be nil here local ges = ges or #minetest.get_connected_players() local form_n = "size[12,5;true]" local all_in_bed = players_in_bed_setting() <= (player_in_bed * 100) / ges @@ -211,8 +211,17 @@ local function update_formspecs(finished, ges) local button_abort = "button_exit[4,3;4,0.75;leave;"..F(S("Abort sleep")).."]" local bg_presleep = "bgcolor[#00000080;true]" local bg_sleep = "bgcolor[#000000FF;true]" + local chatbox = "field[5,2;1,1;chatmessage;"..F(S("Chat:"))..";]" + local chatsubmit = "button[5,4;1,2;chatsubmit;"..F(S("send!")).."]" + + form_n = form_n .. chatbox .. chatsubmit --because these should be in the formspec in ANY case, they might as well be added here already if finished then + if singlular_player ~= nil then + minetest.close_formspec(singlular_player:get_player_name(),"mcl_beds_form") + return + end + for name,_ in pairs(mcl_beds.player) do minetest.close_formspec(name, "mcl_beds_form") end @@ -253,6 +262,11 @@ local function update_formspecs(finished, ges) form_n = form_n .. "label[0.5,1;"..F(text).."]" end + if singlular_player ~= nil then + minetest.show_formspec(singlular_player:get_player_name(),"mcl_beds_form",form_n) + return + end + for name,_ in pairs(mcl_beds.player) do minetest.show_formspec(name, "mcl_beds_form", form_n) end @@ -429,6 +443,13 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if formname ~= "mcl_beds_form" then return end + + if fields.chatsubmit and fields.chatmessage ~= "" then + minetest.chat_send_all(minetest.format_chat_message(player:get_player_name(), fields.chatmessage)) + update_formspecs(false,nil,player) + return --no need to check other conditions anymore + end + if fields.quit or fields.leave then lay_down(player, nil, nil, false) update_formspecs(false) From a026bbd3c4ce1e0d4247eeb1d2d812e85dd00d08 Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Wed, 5 Apr 2023 15:45:16 +0200 Subject: [PATCH 035/155] minor bed changes --- mods/ITEMS/mcl_beds/functions.lua | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index 58df7c65d..8b64ffb42 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -202,7 +202,7 @@ local function lay_down(player, pos, bed_pos, state, skip) return true end -local function update_formspecs(finished, ges, singlular_player) --singlular_player isn't a boolean, just a player thats allowed to be nil here +local function update_formspecs(finished, ges) local ges = ges or #minetest.get_connected_players() local form_n = "size[12,5;true]" local all_in_bed = players_in_bed_setting() <= (player_in_bed * 100) / ges @@ -211,17 +211,12 @@ local function update_formspecs(finished, ges, singlular_player) --singlular_pla local button_abort = "button_exit[4,3;4,0.75;leave;"..F(S("Abort sleep")).."]" local bg_presleep = "bgcolor[#00000080;true]" local bg_sleep = "bgcolor[#000000FF;true]" - local chatbox = "field[5,2;1,1;chatmessage;"..F(S("Chat:"))..";]" - local chatsubmit = "button[5,4;1,2;chatsubmit;"..F(S("send!")).."]" + local chatbox = "field[1,4.5;9,1;chatmessage;"..F(S("Chat:"))..";]" + local chatsubmit = "button[10,3.75;1,2;chatsubmit;"..F(S("send!")).."]" form_n = form_n .. chatbox .. chatsubmit --because these should be in the formspec in ANY case, they might as well be added here already if finished then - if singlular_player ~= nil then - minetest.close_formspec(singlular_player:get_player_name(),"mcl_beds_form") - return - end - for name,_ in pairs(mcl_beds.player) do minetest.close_formspec(name, "mcl_beds_form") end @@ -262,11 +257,6 @@ local function update_formspecs(finished, ges, singlular_player) --singlular_pla form_n = form_n .. "label[0.5,1;"..F(text).."]" end - if singlular_player ~= nil then - minetest.show_formspec(singlular_player:get_player_name(),"mcl_beds_form",form_n) - return - end - for name,_ in pairs(mcl_beds.player) do minetest.show_formspec(name, "mcl_beds_form", form_n) end @@ -446,8 +436,6 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if fields.chatsubmit and fields.chatmessage ~= "" then minetest.chat_send_all(minetest.format_chat_message(player:get_player_name(), fields.chatmessage)) - update_formspecs(false,nil,player) - return --no need to check other conditions anymore end if fields.quit or fields.leave then From 645e20afa417888242a9bd143260293b5f1e6fbd Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Wed, 5 Apr 2023 15:45:48 +0200 Subject: [PATCH 036/155] translation updates --- mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr | 4 +++- mods/ITEMS/mcl_beds/locale/template.txt | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr b/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr index 7fe400b7f..79ed0ded9 100644 --- a/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr +++ b/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr @@ -40,4 +40,6 @@ You will fall asleep when all players are in bed.=Sie werden einschlafen, wenn a You will fall asleep when @1% of all players are in bed.=Sie werden einschlafen, wenn @1% der Spieler im Bett sind. You're in bed.=Sie sind im Bett. Allows you to sleep=Zum Einschafen -Respawn Anchor=Seelenanker \ No newline at end of file +Respawn Anchor=Seelenanker +Chat:=Chat: +send!=senden! \ No newline at end of file diff --git a/mods/ITEMS/mcl_beds/locale/template.txt b/mods/ITEMS/mcl_beds/locale/template.txt index 69c493880..4f6611149 100644 --- a/mods/ITEMS/mcl_beds/locale/template.txt +++ b/mods/ITEMS/mcl_beds/locale/template.txt @@ -41,3 +41,5 @@ You will fall asleep when @1% of all players are in bed.= You're in bed.= Allows you to sleep= Respawn Anchor= +Chat:= +send!= \ No newline at end of file From 7fe1be2c18be119c164a4ed0abf9ab113e79c603 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 3 Apr 2023 00:41:39 +0100 Subject: [PATCH 037/155] Add error handling to sunlight checking to prevent crashing and improve diagnosis. --- mods/CORE/mcl_util/init.lua | 18 +++++++++++++ mods/ENTITIES/mcl_mobs/physics.lua | 2 +- mods/ENVIRONMENT/mcl_raids/init.lua | 2 +- mods/ENVIRONMENT/mcl_zombie_sieges/init.lua | 2 +- .../REDSTONE/mesecons_solarpanel/init.lua | 26 +++++-------------- 5 files changed, 28 insertions(+), 22 deletions(-) diff --git a/mods/CORE/mcl_util/init.lua b/mods/CORE/mcl_util/init.lua index 601a46c9f..2b3e0918a 100644 --- a/mods/CORE/mcl_util/init.lua +++ b/mods/CORE/mcl_util/init.lua @@ -64,6 +64,24 @@ function mcl_util.check_dtime_timer(self, dtime, timer_name, threshold) return false end +-- Minetest 5.3.0 or less can only measure the light level. This came in at 5.4 +-- This function has been known to fail in multiple places so the error handling is added increase safety and improve +-- debugging. See: +-- https://git.minetest.land/MineClone2/MineClone2/issues/1392 +function mcl_util.get_natural_light (pos, time) + local status, retVal = pcall(minetest.get_natural_light, pos, time) + if status then + return retVal + else + minetest.log("warning", "Failed to get natural light at pos: " .. dump(pos) .. ", time: " .. dump(time)) + if (pos) then + local node = minetest.get_node(pos) + minetest.log("warning", "Node at pos: " .. dump(node.name)) + end + end + return 0 +end + function mcl_util.file_exists(name) if type(name) ~= "string" then return end local f = io.open(name) diff --git a/mods/ENTITIES/mcl_mobs/physics.lua b/mods/ENTITIES/mcl_mobs/physics.lua index 956eb992c..4ef72eed7 100644 --- a/mods/ENTITIES/mcl_mobs/physics.lua +++ b/mods/ENTITIES/mcl_mobs/physics.lua @@ -643,7 +643,7 @@ function mob_class:do_env_damage() --minetest.log("warning", "Pos is ignored: " .. dump(pos)) end - local sunlight = minetest.get_natural_light(pos, self.time_of_day) + local sunlight = mcl_util.get_natural_light(pos, self.time_of_day) if self.light_damage ~= 0 and (sunlight or 0) > 12 then if self:deal_light_damage(pos, self.light_damage) then diff --git a/mods/ENVIRONMENT/mcl_raids/init.lua b/mods/ENVIRONMENT/mcl_raids/init.lua index 8c996f0ce..8e7c644ae 100644 --- a/mods/ENVIRONMENT/mcl_raids/init.lua +++ b/mods/ENVIRONMENT/mcl_raids/init.lua @@ -240,7 +240,7 @@ end local function start_firework_rocket(pos) local p = get_point_on_circle(pos,math.random(32,64),32) local n = minetest.get_node(p) - local l = minetest.get_natural_light(pos,0.5) + local l = mcl_util.get_natural_light(pos,0.5) if n.name ~= "air" or l <= minetest.LIGHT_MAX then return end local o = minetest.add_entity(p,"mcl_bows:rocket_entity") o:get_luaentity()._harmless = true diff --git a/mods/ENVIRONMENT/mcl_zombie_sieges/init.lua b/mods/ENVIRONMENT/mcl_zombie_sieges/init.lua index c2a53d79a..fefb17fa5 100644 --- a/mods/ENVIRONMENT/mcl_zombie_sieges/init.lua +++ b/mods/ENVIRONMENT/mcl_zombie_sieges/init.lua @@ -1,7 +1,7 @@ local zombie_siege_enabled = minetest.settings:get_bool("mcl_raids_zombie_siege", false) local function check_spawn_pos(pos) - return minetest.get_natural_light(pos) < 7 + return mcl_util.get_natural_light(pos) < 7 end local function spawn_zombies(self) diff --git a/mods/ITEMS/REDSTONE/mesecons_solarpanel/init.lua b/mods/ITEMS/REDSTONE/mesecons_solarpanel/init.lua index 129c28eea..7780cbfee 100644 --- a/mods/ITEMS/REDSTONE/mesecons_solarpanel/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_solarpanel/init.lua @@ -35,29 +35,17 @@ local function path_to_sunlight_exists(position, light_level) end local function sunlight_visible(position) - local light_level - -- Minetest 5.4.0+ can measure the daylight level at a position - if nil ~= minetest.get_natural_light then - light_level = minetest.get_natural_light( - position, - nil - ) - if light_level >= 12 then - return true - end - else -- Minetest 5.3.0 or less can only measure the light level + local light_level = mcl_util.get_natural_light (position) + if light_level >= 12 then + --minetest.log("Light is greater than 12") + return true + else local time = minetest.get_timeofday() * 24000 -- only check light level during day if time > 6000 and time < 18000 then - light_level = minetest.get_node_light( - position, - nil - ) + light_level = minetest.get_node_light(position, nil) if light_level >= 12 then - return path_to_sunlight_exists( - position, - 12 - ) + return path_to_sunlight_exists(position, 12) end end end From 786aaf7a6d902d93997885f5b923b21eeb188373 Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Fri, 7 Apr 2023 11:58:03 +0200 Subject: [PATCH 038/155] check for shout priv --- mods/ITEMS/mcl_beds/functions.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index 8b64ffb42..9def86870 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -435,6 +435,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end if fields.chatsubmit and fields.chatmessage ~= "" then + if not minetest.check_player_privs(player,"shout") then + minetest.chat_send_player(player:get_player_name(),S("You are missing the 'shout' privilege! It's required in order to talk in chat...")) minetest.chat_send_all(minetest.format_chat_message(player:get_player_name(), fields.chatmessage)) end From 4b1cc017a9feb73d8c8bec260b9c4461e6a8711c Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Fri, 7 Apr 2023 11:58:27 +0200 Subject: [PATCH 039/155] fix syntax --- mods/ITEMS/mcl_beds/functions.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index 9def86870..be60adec8 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -437,6 +437,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if fields.chatsubmit and fields.chatmessage ~= "" then if not minetest.check_player_privs(player,"shout") then minetest.chat_send_player(player:get_player_name(),S("You are missing the 'shout' privilege! It's required in order to talk in chat...")) + return + end minetest.chat_send_all(minetest.format_chat_message(player:get_player_name(), fields.chatmessage)) end From fca23ba47fb07a9e4e60fce275d66841d5eb0cb3 Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Fri, 7 Apr 2023 11:59:07 +0200 Subject: [PATCH 040/155] update traslation template --- mods/ITEMS/mcl_beds/locale/template.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_beds/locale/template.txt b/mods/ITEMS/mcl_beds/locale/template.txt index 4f6611149..f86a21642 100644 --- a/mods/ITEMS/mcl_beds/locale/template.txt +++ b/mods/ITEMS/mcl_beds/locale/template.txt @@ -42,4 +42,5 @@ You're in bed.= Allows you to sleep= Respawn Anchor= Chat:= -send!= \ No newline at end of file +send!= +You are missing the 'shout' privilege! It's required in order to talk in chat...= \ No newline at end of file From 2366969e00fe500b6c17955c7f6fccbb34198381 Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Fri, 7 Apr 2023 12:00:36 +0200 Subject: [PATCH 041/155] update german translation --- mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr b/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr index 79ed0ded9..183d07790 100644 --- a/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr +++ b/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr @@ -42,4 +42,5 @@ You're in bed.=Sie sind im Bett. Allows you to sleep=Zum Einschafen Respawn Anchor=Seelenanker Chat:=Chat: -send!=senden! \ No newline at end of file +send!=senden! +You are missing the 'shout' privilege! It's required in order to talk in chat...=Ihnen fehlt das 'shout' Privileg! Es wird benötigt, um im Chat reden zu können... \ No newline at end of file From ac4073a259efc247164dc28d7ec4ff914ef0eb96 Mon Sep 17 00:00:00 2001 From: syl Date: Fri, 7 Apr 2023 17:05:06 +0200 Subject: [PATCH 042/155] Improve french translation --- mods/HUD/awards/locale/awards.fr.tr | 2 +- mods/HUD/hudbars/locale/hudbars.fr.tr | 4 ++-- mods/PLAYER/mcl_hunger/locale/mcl_hunger.fr.tr | 4 ++-- mods/PLAYER/mcl_skins/locale/mcl_skins.fr.tr | 7 ++++--- mods/PLAYER/mcl_spawn/locale/mcl_spawn.fr.tr | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/mods/HUD/awards/locale/awards.fr.tr b/mods/HUD/awards/locale/awards.fr.tr index 38959ccef..767848a69 100644 --- a/mods/HUD/awards/locale/awards.fr.tr +++ b/mods/HUD/awards/locale/awards.fr.tr @@ -61,4 +61,4 @@ Advancement “@1” does not exist.=Le progrès «@1» n'existe pas. @1 has made the advancement @2=@1 a obtenu le progrès @2 Mine a block: @1=Miner un bloc : @1 Mine blocks: @1×@2=Miner des blocs : @1×@2 -Awards are disabled, enable them first by using /awards enable!=Les récompenses sont désactivés, activez les d'abord en utilisant /awards enable ! +Awards are disabled, enable them first by using /awards enable!=Les récompenses sont désactivées, activez les d'abord en utilisant /awards enable ! diff --git a/mods/HUD/hudbars/locale/hudbars.fr.tr b/mods/HUD/hudbars/locale/hudbars.fr.tr index b31b7b0c1..586caa718 100644 --- a/mods/HUD/hudbars/locale/hudbars.fr.tr +++ b/mods/HUD/hudbars/locale/hudbars.fr.tr @@ -1,6 +1,6 @@ # textdomain: hudbars Health=Santé -Breath=Breath +Breath=Respiration # Default format string for progress bar-style HUD bars, e.g. “Health 5/20” -@1: @2/@3=@1: @2/@3 +@1: @2/@3=@1 : @2/@3 diff --git a/mods/PLAYER/mcl_hunger/locale/mcl_hunger.fr.tr b/mods/PLAYER/mcl_hunger/locale/mcl_hunger.fr.tr index 811868b3a..04f809c58 100644 --- a/mods/PLAYER/mcl_hunger/locale/mcl_hunger.fr.tr +++ b/mods/PLAYER/mcl_hunger/locale/mcl_hunger.fr.tr @@ -2,7 +2,7 @@ @1 succumbed to the poison.=@1 a succombé au poison. Food=Nourriture Saturation=Saturation -%s: %.1f/%d=%s: %.1f/%d +%s: %.1f/%d=%s : %.1f/%d Exhaust.=Échappement. -%s: %d/%d=%s: %d/%d +%s: %d/%d=%s : %d/%d @1 starved to death.=@1 est mort de faim. diff --git a/mods/PLAYER/mcl_skins/locale/mcl_skins.fr.tr b/mods/PLAYER/mcl_skins/locale/mcl_skins.fr.tr index db937b040..6eb0a17c2 100644 --- a/mods/PLAYER/mcl_skins/locale/mcl_skins.fr.tr +++ b/mods/PLAYER/mcl_skins/locale/mcl_skins.fr.tr @@ -1,13 +1,14 @@ # textdomain: mcl_skins +Skins=Costumes Templates=Modèles Arm size=Taille des bras -Bases=Teint +Bases=Teints Footwears=Chaussures Eyes=Yeux Mouths=Bouches Bottoms=Bas -Tops=Haut +Tops=Hauts Hairs=Cheveux -Headwears=Coiffe +Headwears=Coiffes Open skin configuration screen.=Ouvrir l'écran de configuration du costume. Select=Sélectionner \ No newline at end of file diff --git a/mods/PLAYER/mcl_spawn/locale/mcl_spawn.fr.tr b/mods/PLAYER/mcl_spawn/locale/mcl_spawn.fr.tr index a2e5fbd8e..a833f8ad0 100644 --- a/mods/PLAYER/mcl_spawn/locale/mcl_spawn.fr.tr +++ b/mods/PLAYER/mcl_spawn/locale/mcl_spawn.fr.tr @@ -2,4 +2,4 @@ New respawn position set!=Nouvelle position de réapparition définie ! Respawn position cleared!=Position de réapparition supprimée ! Couldn't get level of your respawn anchor!=Impossible d'obtenir le niveau de votre ancre de réapparition ! -Your spawn bed was missing or blocked, and you had no charged respawn anchor!=Votre lit d'apparition était manquant ou bloqué, et vou n'avez pas d'ancre de réapparition chargée ! \ No newline at end of file +Your spawn bed was missing or blocked, and you had no charged respawn anchor!=Votre lit d'apparition était manquant ou bloqué, et vous n'avez pas d'ancre de réapparition chargée ! From a55cbaadd6bddc3a94fb48f85c074067c4761485 Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Sun, 9 Apr 2023 18:32:15 +0200 Subject: [PATCH 043/155] take 'chat_message_limit_per_10sec' into account --- mods/ITEMS/mcl_beds/functions.lua | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index be60adec8..2bb460347 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -429,6 +429,24 @@ minetest.register_on_leaveplayer(function(player) update_formspecs(false, #players) end) + +local message_rate_limit = tonumber(minetest.settings:get("chat_message_limit_per_10sec")) or 8 --NEVER change this! if this was java, i would've declared it as final +local playermessagecounter = {} +--[[ + This table stores how many messages a player XY has sent (only while being in a bed) within 10 secs + It gets reset after 10 secs using a globalstep +]] + +local globalstep_timer = 0 +minetest.register_globalstep(function(dtime) + globalstep_timer = globalstep_timer + dtime + if globalstep_timer >= 10 then + globalstep_timer = 0 + playermessagecounter = {} + minetest.log("reset counter") + end +end) + minetest.register_on_player_receive_fields(function(player, formname, fields) if formname ~= "mcl_beds_form" then return @@ -439,6 +457,17 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) minetest.chat_send_player(player:get_player_name(),S("You are missing the 'shout' privilege! It's required in order to talk in chat...")) return end + + if playermessagecounter[player:get_player_name()] == nil then + playermessagecounter[player:get_player_name()] = 0 + end + + if playermessagecounter[player:get_player_name()] >= message_rate_limit then -- == should do as well + minetest.chat_send_player(player:get_player_name(),S("You exceeded the maximum number of messages per 10 seconds! " .. "(" .. tostring(message_rate_limit) .. ")")) + return + end + + playermessagecounter[player:get_player_name()] = playermessagecounter[player:get_player_name()] + 1 minetest.chat_send_all(minetest.format_chat_message(player:get_player_name(), fields.chatmessage)) end From 145be4c83045d1c9ce3dfe58496cc020f9f4b984 Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Sun, 9 Apr 2023 18:32:52 +0200 Subject: [PATCH 044/155] remove debug logging --- mods/ITEMS/mcl_beds/functions.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index 2bb460347..33bdc0e27 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -443,7 +443,6 @@ minetest.register_globalstep(function(dtime) if globalstep_timer >= 10 then globalstep_timer = 0 playermessagecounter = {} - minetest.log("reset counter") end end) From 899d6196245f70c6843fbd463825bbff2f75b42a Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Sun, 9 Apr 2023 18:35:03 +0200 Subject: [PATCH 045/155] fix translator syntax --- mods/ITEMS/mcl_beds/functions.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index 33bdc0e27..8b63fa596 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -462,7 +462,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end if playermessagecounter[player:get_player_name()] >= message_rate_limit then -- == should do as well - minetest.chat_send_player(player:get_player_name(),S("You exceeded the maximum number of messages per 10 seconds! " .. "(" .. tostring(message_rate_limit) .. ")")) + minetest.chat_send_player(player:get_player_name(),S("You exceeded the maximum number of messages per 10 seconds! ") .. "(" .. tostring(message_rate_limit) .. ")") return end From d9ac803f5bcf6958f4889d111450c6276fdc496b Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Sun, 9 Apr 2023 18:37:02 +0200 Subject: [PATCH 046/155] update translations --- mods/ITEMS/mcl_beds/functions.lua | 2 +- mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr | 3 ++- mods/ITEMS/mcl_beds/locale/template.txt | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index 8b63fa596..0bbf0eca8 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -462,7 +462,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end if playermessagecounter[player:get_player_name()] >= message_rate_limit then -- == should do as well - minetest.chat_send_player(player:get_player_name(),S("You exceeded the maximum number of messages per 10 seconds! ") .. "(" .. tostring(message_rate_limit) .. ")") + minetest.chat_send_player(player:get_player_name(),S("You exceeded the maximum number of messages per 10 seconds!") .. " (" .. tostring(message_rate_limit) .. ")") return end diff --git a/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr b/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr index 183d07790..e0d00f62a 100644 --- a/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr +++ b/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr @@ -43,4 +43,5 @@ Allows you to sleep=Zum Einschafen Respawn Anchor=Seelenanker Chat:=Chat: send!=senden! -You are missing the 'shout' privilege! It's required in order to talk in chat...=Ihnen fehlt das 'shout' Privileg! Es wird benötigt, um im Chat reden zu können... \ No newline at end of file +You are missing the 'shout' privilege! It's required in order to talk in chat...=Ihnen fehlt das 'shout' Privileg! Es wird benötigt, um im Chat reden zu können... +You exceeded the maximum number of messages per 10 seconds!=Sie haben die maximale Anzahl an Chatnachrichten pro 10 Sekunden überschritten! \ No newline at end of file diff --git a/mods/ITEMS/mcl_beds/locale/template.txt b/mods/ITEMS/mcl_beds/locale/template.txt index f86a21642..a3b635675 100644 --- a/mods/ITEMS/mcl_beds/locale/template.txt +++ b/mods/ITEMS/mcl_beds/locale/template.txt @@ -43,4 +43,5 @@ Allows you to sleep= Respawn Anchor= Chat:= send!= -You are missing the 'shout' privilege! It's required in order to talk in chat...= \ No newline at end of file +You are missing the 'shout' privilege! It's required in order to talk in chat...= +You exceeded the maximum number of messages per 10 seconds!= \ No newline at end of file From 75595115a038c932ce806ef5298c084a69f16922 Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Sun, 9 Apr 2023 18:45:23 +0200 Subject: [PATCH 047/155] move rate checks to seperate function --- mods/ITEMS/mcl_beds/functions.lua | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index 0bbf0eca8..cb3e8ff0a 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -446,6 +446,17 @@ minetest.register_globalstep(function(dtime) end end) +local function exceeded_rate_limit(playername) --Note: will also take care of increasing value + if playermessagecounter[playername] == nil then + playermessagecounter[playername] = 0 + end + if playermessagecounter[playername] >= message_rate_limit then -- == should do as well + return true + end + playermessagecounter[playername] = playermessagecounter[playername] + 1 + return false +end + minetest.register_on_player_receive_fields(function(player, formname, fields) if formname ~= "mcl_beds_form" then return @@ -457,16 +468,11 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) return end - if playermessagecounter[player:get_player_name()] == nil then - playermessagecounter[player:get_player_name()] = 0 - end - - if playermessagecounter[player:get_player_name()] >= message_rate_limit then -- == should do as well + if exceeded_rate_limit(player:get_player_name()) then minetest.chat_send_player(player:get_player_name(),S("You exceeded the maximum number of messages per 10 seconds!") .. " (" .. tostring(message_rate_limit) .. ")") return end - playermessagecounter[player:get_player_name()] = playermessagecounter[player:get_player_name()] + 1 minetest.chat_send_all(minetest.format_chat_message(player:get_player_name(), fields.chatmessage)) end From 62c014363de79c8c937b47a28c98dcb27327458a Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Sun, 9 Apr 2023 18:50:34 +0200 Subject: [PATCH 048/155] 'fix' multiline comment --- mods/ITEMS/mcl_beds/functions.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index cb3e8ff0a..ea77d9571 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -435,7 +435,7 @@ local playermessagecounter = {} --[[ This table stores how many messages a player XY has sent (only while being in a bed) within 10 secs It gets reset after 10 secs using a globalstep -]] +--]] local globalstep_timer = 0 minetest.register_globalstep(function(dtime) From bf9989beb91a01b3a4ffb4f4c0d917c1bd9554b1 Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Sun, 9 Apr 2023 19:51:55 +0200 Subject: [PATCH 049/155] add default message button --- mods/ITEMS/mcl_beds/functions.lua | 38 ++++++++++++++--------- mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr | 3 +- mods/ITEMS/mcl_beds/locale/template.txt | 3 +- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index ea77d9571..56e4a232b 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -211,8 +211,9 @@ local function update_formspecs(finished, ges) local button_abort = "button_exit[4,3;4,0.75;leave;"..F(S("Abort sleep")).."]" local bg_presleep = "bgcolor[#00000080;true]" local bg_sleep = "bgcolor[#000000FF;true]" - local chatbox = "field[1,4.5;9,1;chatmessage;"..F(S("Chat:"))..";]" - local chatsubmit = "button[10,3.75;1,2;chatsubmit;"..F(S("send!")).."]" + local chatbox = "field[0.2,4.5;9,1;chatmessage;"..F(S("Chat:"))..";]" + local chatsubmit = "button[9.2,3.75;1,2;chatsubmit;"..F(S("send!")).."]" + local defaultmessagebutton = "button[10.2,3.75;1,2;defaultmessage;zzZzzZ]" form_n = form_n .. chatbox .. chatsubmit --because these should be in the formspec in ANY case, they might as well be added here already @@ -241,6 +242,7 @@ local function update_formspecs(finished, ges) text = text .. "\n" .. comment form_n = form_n .. bg_presleep form_n = form_n .. button_leave + form_n = form_n .. defaultmessagebutton --Players should only be able to see that button when: -Skipping the night is possible -There aren't enoght players sleeping yet end form_n = form_n .. "label[0.5,1;"..F(text).."]" else @@ -429,7 +431,6 @@ minetest.register_on_leaveplayer(function(player) update_formspecs(false, #players) end) - local message_rate_limit = tonumber(minetest.settings:get("chat_message_limit_per_10sec")) or 8 --NEVER change this! if this was java, i would've declared it as final local playermessagecounter = {} --[[ @@ -446,16 +447,25 @@ minetest.register_globalstep(function(dtime) end end) -local function exceeded_rate_limit(playername) --Note: will also take care of increasing value +local function exceeded_rate_limit(playername) --Note: will also take care of increasing value and sending feedback message if needed if playermessagecounter[playername] == nil then playermessagecounter[playername] = 0 end if playermessagecounter[playername] >= message_rate_limit then -- == should do as well + minetest.chat_send_player(playername,S("You exceeded the maximum number of messages per 10 seconds!") .. " (" .. tostring(message_rate_limit) .. ")") return true end playermessagecounter[playername] = playermessagecounter[playername] + 1 return false -end +end + +local function shout_priv_check(player) + if not minetest.check_player_privs(player,"shout") then + minetest.chat_send_player(player:get_player_name(),S("You are missing the 'shout' privilege! It's required in order to talk in chat...")) + return false + end + return true +end minetest.register_on_player_receive_fields(function(player, formname, fields) if formname ~= "mcl_beds_form" then @@ -463,18 +473,18 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end if fields.chatsubmit and fields.chatmessage ~= "" then - if not minetest.check_player_privs(player,"shout") then - minetest.chat_send_player(player:get_player_name(),S("You are missing the 'shout' privilege! It's required in order to talk in chat...")) - return + if (not exceeded_rate_limit(player:get_player_name())) and shout_priv_check(player) then + minetest.chat_send_all(minetest.format_chat_message(player:get_player_name(), fields.chatmessage)) end + return + end - if exceeded_rate_limit(player:get_player_name()) then - minetest.chat_send_player(player:get_player_name(),S("You exceeded the maximum number of messages per 10 seconds!") .. " (" .. tostring(message_rate_limit) .. ")") - return + if fields.defaultmessage then + if (not exceeded_rate_limit(player:get_player_name())) and shout_priv_check(player) then + minetest.chat_send_all(minetest.format_chat_message(player:get_player_name(), S("Hey! Would you guys mind sleeping?"))) end - - minetest.chat_send_all(minetest.format_chat_message(player:get_player_name(), fields.chatmessage)) - end + return + end if fields.quit or fields.leave then lay_down(player, nil, nil, false) diff --git a/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr b/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr index e0d00f62a..ae035f3bb 100644 --- a/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr +++ b/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr @@ -44,4 +44,5 @@ Respawn Anchor=Seelenanker Chat:=Chat: send!=senden! You are missing the 'shout' privilege! It's required in order to talk in chat...=Ihnen fehlt das 'shout' Privileg! Es wird benötigt, um im Chat reden zu können... -You exceeded the maximum number of messages per 10 seconds!=Sie haben die maximale Anzahl an Chatnachrichten pro 10 Sekunden überschritten! \ No newline at end of file +You exceeded the maximum number of messages per 10 seconds!=Sie haben die maximale Anzahl an Chatnachrichten pro 10 Sekunden überschritten! +Hey! Would you guys mind sleeping?=Hey, würdet Ihr bitte zu Bett gehen? \ No newline at end of file diff --git a/mods/ITEMS/mcl_beds/locale/template.txt b/mods/ITEMS/mcl_beds/locale/template.txt index a3b635675..7d1f378c0 100644 --- a/mods/ITEMS/mcl_beds/locale/template.txt +++ b/mods/ITEMS/mcl_beds/locale/template.txt @@ -44,4 +44,5 @@ Respawn Anchor= Chat:= send!= You are missing the 'shout' privilege! It's required in order to talk in chat...= -You exceeded the maximum number of messages per 10 seconds!= \ No newline at end of file +You exceeded the maximum number of messages per 10 seconds!= +Hey! Would you guys mind sleeping? \ No newline at end of file From 0719d6038c17366c832a3ba04f9a2b3c49e13c14 Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Sun, 9 Apr 2023 19:53:28 +0200 Subject: [PATCH 050/155] add missing '=' to the translation template --- mods/ITEMS/mcl_beds/locale/template.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_beds/locale/template.txt b/mods/ITEMS/mcl_beds/locale/template.txt index 7d1f378c0..dd58d74e8 100644 --- a/mods/ITEMS/mcl_beds/locale/template.txt +++ b/mods/ITEMS/mcl_beds/locale/template.txt @@ -45,4 +45,4 @@ Chat:= send!= You are missing the 'shout' privilege! It's required in order to talk in chat...= You exceeded the maximum number of messages per 10 seconds!= -Hey! Would you guys mind sleeping? \ No newline at end of file +Hey! Would you guys mind sleeping?= \ No newline at end of file From 5165730da805bf9e99ddf342f9a1537ab77f3106 Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Tue, 4 Apr 2023 10:58:52 -0600 Subject: [PATCH 051/155] Make shield block sounds not play across infinite distance --- mods/ITEMS/mcl_shields/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_shields/init.lua b/mods/ITEMS/mcl_shields/init.lua index 3ad2ada51..639cf3585 100644 --- a/mods/ITEMS/mcl_shields/init.lua +++ b/mods/ITEMS/mcl_shields/init.lua @@ -164,7 +164,7 @@ mcl_damage.register_modifier(function(obj, damage, reason) mcl_inventory.update_inventory_formspec(obj) end end - minetest.sound_play({name = "mcl_block"}) + minetest.sound_play({name = "mcl_block"}, {max_hear_distance = 16}) return 0 end) From f8d338d7319140dd4c51c170d6293e32db81cd71 Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Mon, 10 Apr 2023 21:10:54 -0600 Subject: [PATCH 052/155] Add position to shield sound --- mods/ITEMS/mcl_shields/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_shields/init.lua b/mods/ITEMS/mcl_shields/init.lua index 639cf3585..fa7714366 100644 --- a/mods/ITEMS/mcl_shields/init.lua +++ b/mods/ITEMS/mcl_shields/init.lua @@ -164,7 +164,7 @@ mcl_damage.register_modifier(function(obj, damage, reason) mcl_inventory.update_inventory_formspec(obj) end end - minetest.sound_play({name = "mcl_block"}, {max_hear_distance = 16}) + minetest.sound_play({name = "mcl_block"}, {pos = obj:get_pos(), max_hear_distance = 16}) return 0 end) From 3ed3f167021c18ee111f89dd6274c2275e173d46 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Sat, 15 Apr 2023 12:25:17 +0100 Subject: [PATCH 053/155] Pre-release update credits and set version 0.83.0 --- CONTRIBUTING.md | 2 +- CREDITS.md | 8 +++----- RELEASE.md | 10 +++++----- game.conf | 2 +- mods/HUD/mcl_credits/people.lua | 17 ++++++++++++----- 5 files changed, 22 insertions(+), 17 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dc8c4a5ee..b5a11ee1e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -76,7 +76,7 @@ in singleplayer, post a screenshot of the message that Minetest showed when the crash happened (or copy the message into your issue). If you are a server admin, you can find error messages in the log file of the server. -* Tell us which MineClone2 and Minetest versions you are using. +* Tell us which MineClone2 and Minetest versions you are using (from Minetest 5.7 type /ver, for previous versions, check the game.conf or README.md file). * Tell us how to reproduce the problem: What you were doing to trigger the bug, e.g. before the crash happened or what causes the faulty behavior. diff --git a/CREDITS.md b/CREDITS.md index c1307a3bc..7296e52a7 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -36,7 +36,8 @@ * MrRar * talamh * Faerraven / Michieal -* FossFanatic +* FossFanatic +* SmokeyDope ## Contributors * Laurent Rocher @@ -81,15 +82,12 @@ * aldum * Dieter44 * Pepebotella -* MrRar * Lazerbeak12345 * mrminer * Thunder1035 * opfromthestart * snowyu * FaceDeer -* Faerraven / Michieal -* FossFanatic * Herbert West * GuyLiner * 3raven @@ -101,8 +99,8 @@ * b3nderman * CyberMango * gldrk -* SmokeyDope * atomdmac +* emptyshore ## MineClone5 * kay27 diff --git a/RELEASE.md b/RELEASE.md index 144e1729a..4d82ab9e3 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -13,15 +13,15 @@ git add game.conf #git add RELEASE.md -git commit -m "Pre-release update credits and set version 0.82.0" +git commit -m "Pre-release update credits and set version 0.83.0" -git tag 0.82.0 +git tag 0.83.0 -git push origin 0.82.0 +git push origin 0.83.0 -#Update version in game.conf to -SNAPSHOT +#Update version in game.conf to the next version with -SNAPSHOT suffix -git commit -m "Post-release set version 0.82.0-SNAPSHOT" +git commit -m "Post-release set version 0.84.0-SNAPSHOT" ### Hotfix Release diff --git a/game.conf b/game.conf index b364f026f..023ac5747 100644 --- a/game.conf +++ b/game.conf @@ -1,4 +1,4 @@ title = MineClone 2 description = A survival sandbox game. Survive, gather, hunt, build, explore, and do much more. disallowed_mapgens = v6 -version=0.82.0-SNAPSHOT \ No newline at end of file +version=0.83.0 \ No newline at end of file diff --git a/mods/HUD/mcl_credits/people.lua b/mods/HUD/mcl_credits/people.lua index d9ee02742..26b80927d 100644 --- a/mods/HUD/mcl_credits/people.lua +++ b/mods/HUD/mcl_credits/people.lua @@ -37,7 +37,8 @@ return { "MrRar", "talamh", "Faerraven / Michieal", - "FossFanatic", + "FossFanatic ", + "SmokeyDope", }}, {S("Contributors"), 0x52FF00, { "Laurent Rocher", @@ -82,15 +83,12 @@ return { "aldum", "Dieter44", "Pepebotella", - "MrRar", "Lazerbeak12345", "mrminer", "Thunder1035", "opfromthestart", "snowyu", "FaceDeer", - "Faerraven / Michieal", - "FossFanatic", "Herbert West", "GuyLiner", "3raven", @@ -100,6 +98,10 @@ return { "Gregor Parzefall", "Wbjitscool", "b3nderman", + "CyberMango", + "gldrk", + "atomdmac", + "emptyshore", }}, {S("MineClone5"), 0xA60014, { "kay27", @@ -187,6 +189,8 @@ return { "snowyu", "3raven", "SakuraRiu", + "anarquimico", + "syl", }}, {S("Funders"), 0xF7FF00, { "40W", @@ -199,6 +203,9 @@ return { "wsor for working tirelessly in the shadows for the good of all of us, particularly helping with solving contentDB and copyright issues.", "The workaholics who spent way too much time writing for the Minecraft Wiki. It's an invaluable resource for creating this game", "Notch and Jeb for being the major forces behind Minecraft", - "Dark Reaven Music (https://soundcloud.com/dark-reaven-music) for the main menu theme (Calmed Cube), which is licensed under https://creativecommons.org/licenses/by-sa/3.0/", + "Dark Reaven Music (https://soundcloud.com/dark-reaven-music) for the main menu theme (Calmed Cube) and Traitor (horizonchris96), which is licensed under https://creativecommons.org/licenses/by-sa/3.0/", + "Jester for helping to finely tune MineClone2 (https://www.youtube.com/@Jester-8-bit). Songs: Hailing Forest, Gift, 0dd BL0ck, Flock of One (License CC BY-SA 4.0)", + "Exhale & Tim Unwin for some wonderful MineClone2 tracks (https://www.youtube.com/channel/UClFo_JDWoG4NGrPQY0JPD_g). Songs: Valley of Ghosts, Lonely Blossom, Farmer (License CC BY-SA 4.0)", + "Diminixed for 3 fantastic tracks and remastering and leveling volumes. Songs: Afternoon Lullaby (pianowtune02), Spooled (ambientwip02), Never Grow Up (License CC BY-SA 4.0)", }}, } From 0de9685914677b611a7cf75380eaab04c8cc94b3 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Sat, 15 Apr 2023 12:28:27 +0100 Subject: [PATCH 054/155] Post-release set version 0.84.0-SNAPSHOT --- game.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game.conf b/game.conf index 023ac5747..a7716f284 100644 --- a/game.conf +++ b/game.conf @@ -1,4 +1,4 @@ title = MineClone 2 description = A survival sandbox game. Survive, gather, hunt, build, explore, and do much more. disallowed_mapgens = v6 -version=0.83.0 \ No newline at end of file +version=0.84.0-SNAPSHOT \ No newline at end of file From d53ea65da83de14efcf827b3b14c1b6cd47b0eaa Mon Sep 17 00:00:00 2001 From: FossFanatic Date: Mon, 3 Apr 2023 14:32:02 +0000 Subject: [PATCH 055/155] Remove some code Some code has been moved to `mcl_mapgen_core` for consistency. --- mods/ITEMS/mcl_ocean/seagrass.lua | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/mods/ITEMS/mcl_ocean/seagrass.lua b/mods/ITEMS/mcl_ocean/seagrass.lua index 26640aa3a..328328993 100644 --- a/mods/ITEMS/mcl_ocean/seagrass.lua +++ b/mods/ITEMS/mcl_ocean/seagrass.lua @@ -149,28 +149,3 @@ end if mod_doc then doc.add_entry_alias("nodes", "mcl_ocean:seagrass_dirt", "craftitems", "mcl_ocean:seagrass") end - -minetest.register_lbm({ - label = "Fix incorrect seagrass", - name = "mcl_ocean:fix_incorrect_seagrass", - nodenames = {"group:seagrass"}, - run_at_every_load = false, - action = function(pos, node) - if node.param2 ~= 3 then - node.param2 = 3 - minetest.set_node(pos, node) - end - end -}) - -minetest.register_on_generated(function(minp, maxp, blockseed) - local seagrass = minetest.find_nodes_in_area(minp, maxp, {"group:seagrass"}) - for _, sgpos in pairs(seagrass) do - local sgnode = minetest.get_node(sgpos) - if sgnode.param2 ~= 3 then - sgnode.param2 = 3 - minetest.set_node(sgpos, sgnode) - end - end -end -) From 76bf98b26c29f2a68163d9b04c8482007ef43379 Mon Sep 17 00:00:00 2001 From: FossFanatic Date: Mon, 3 Apr 2023 14:35:24 +0000 Subject: [PATCH 056/155] Use voxelmanip to set the correct param2 for nodes Voxelmanip is now used to set the correct `param2` for the nodes which use biome colouring or, in the case of seagrass, the correct meshoption. --- mods/MAPGEN/mcl_mapgen_core/init.lua | 154 ++++++++++++++++++--------- 1 file changed, 106 insertions(+), 48 deletions(-) diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index 9e401a4ff..13aeb1841 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -290,6 +290,60 @@ local function set_grass_palette(minp,maxp,data2,area,biomemap,nodes) return lvm_used end +local function set_foliage_palette(minp,maxp,data2,area,biomemap,nodes) + -- Flat area at y=0 to read biome 3 times faster than 5.3.0.get_biome_data(pos).biome: 43us vs 125us per iteration: + if not biomemap then return end + local aream = VoxelArea:new({MinEdge={x=minp.x, y=0, z=minp.z}, MaxEdge={x=maxp.x, y=0, z=maxp.z}}) + local nodes = minetest.find_nodes_in_area(minp, maxp, nodes) + for n=1, #nodes do + local n = nodes[n] + local p_pos = area:index(n.x, n.y, n.z) + local b_pos = aream:index(n.x, 0, n.z) + local bn = minetest.get_biome_name(biomemap[b_pos]) + if bn then + local biome = minetest.registered_biomes[bn] + if biome and biome._mcl_biome_type and biome._mcl_foliage_palette_index then + data2[p_pos] = biome._mcl_foliage_palette_index + lvm_used = true + end + end + end + return lvm_used +end + +local function set_water_palette(minp,maxp,data2,area,biomemap,nodes) + -- Flat area at y=0 to read biome 3 times faster than 5.3.0.get_biome_data(pos).biome: 43us vs 125us per iteration: + if not biomemap then return end + local aream = VoxelArea:new({MinEdge={x=minp.x, y=0, z=minp.z}, MaxEdge={x=maxp.x, y=0, z=maxp.z}}) + local nodes = minetest.find_nodes_in_area(minp, maxp, nodes) + for n=1, #nodes do + local n = nodes[n] + local p_pos = area:index(n.x, n.y, n.z) + local b_pos = aream:index(n.x, 0, n.z) + local bn = minetest.get_biome_name(biomemap[b_pos]) + if bn then + local biome = minetest.registered_biomes[bn] + if biome and biome._mcl_biome_type and biome._mcl_water_palette_index then + data2[p_pos] = biome._mcl_water_palette_index + lvm_used = true + end + end + end + return lvm_used +end + +local function set_seagrass_param2(minp,maxp,data2,area,biomemap,nodes) + local aream = VoxelArea:new({MinEdge={x=minp.x, y=0, z=minp.z}, MaxEdge={x=maxp.x, y=0, z=maxp.z}}) + local nodes = minetest.find_nodes_in_area(minp, maxp, nodes) + for n=1, #nodes do + local n = nodes[n] + local p_pos = area:index(n.x, n.y, n.z) + data2[p_pos] = 3 + lvm_used = true + end + return lvm_used +end + -- Below the bedrock, generate air/void local function world_structure(vm, data, data2, emin, emax, area, minp, maxp, blockseed) local biomemap --ymin, ymax @@ -346,23 +400,47 @@ local function world_structure(vm, data, data2, emin, emax, area, minp, maxp, bl end local function block_fixes_grass(vm, data, data2, emin, emax, area, minp, maxp, blockseed) - if maxp.y < mcl_vars.mg_overworld_min then - --minetest.log("Exit grass fix") - return - else - --minetest.log("Grass fixes") - end - - local biomemap = minetest.get_mapgen_object("biomemap") - local lvm_used = false - - if minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min then - -- Set param2 (=color) of nodes which use the grass colour palette. - lvm_used = set_grass_palette(minp,maxp,data2,area,biomemap,{"group:grass_palette"}) - end - return lvm_used + local biomemap = minetest.get_mapgen_object("biomemap") + local lvm_used = false + local pr = PseudoRandom(blockseed) + if minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min then + -- Set param2 (=color) of nodes which use the grass colour palette. + lvm_used = set_grass_palette(minp,maxp,data2,area,biomemap,{"group:grass_palette"}) + end + return lvm_used end +local function block_fixes_foliage(vm, data, data2, emin, emax, area, minp, maxp, blockseed) + local biomemap = minetest.get_mapgen_object("biomemap") + local lvm_used = false + local pr = PseudoRandom(blockseed) + if minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min then + -- Set param2 (=color) of nodes which use the foliage colour palette. + lvm_used = set_foliage_palette(minp,maxp,data2,area,biomemap,{"group:foliage_palette"}) + end + return lvm_used +end + +local function block_fixes_water(vm, data, data2, emin, emax, area, minp, maxp, blockseed) + local biomemap = minetest.get_mapgen_object("biomemap") + local lvm_used = false + local pr = PseudoRandom(blockseed) + if minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min then + -- Set param2 (=color) of nodes which use the water colour palette. + lvm_used = set_water_palette(minp,maxp,data2,area,biomemap,{"group:water_palette"}) + end + return lvm_used +end + +local function block_fixes_seagrass(vm, data, data2, emin, emax, area, minp, maxp, blockseed) + local lvm_used = false + local pr = PseudoRandom(blockseed) + if minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min then + -- Set param2 of seagrass to 3. + lvm_used = set_seagrass_param2(minp,maxp,data2,area,biomemap,{"group:seagrass"}) + end + return lvm_used +end -- End block fixes: local function end_basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed) @@ -391,6 +469,9 @@ end, 9999, true) if mg_name ~= "v6" and mg_name ~= "singlenode" then mcl_mapgen_core.register_generator("block_fixes_grass", block_fixes_grass, nil, 9999, true) + mcl_mapgen_core.register_generator("block_fixes_foliage", block_fixes_foliage, nil, 9999, true) + mcl_mapgen_core.register_generator("block_fixes_water", block_fixes_water, nil, 9999, true) + mcl_mapgen_core.register_generator("block_fixes_seagrass", block_fixes_seagrass, nil, 9999, true) end if mg_name == "v6" then @@ -467,28 +548,6 @@ minetest.register_lbm({ end }) -minetest.register_on_generated(function(minp, maxp, blockseed) -- Set correct palette indexes of foliage in new mapblocks. - local pos1, pos2 = vector.offset(minp, -16, -16, -16), vector.offset(maxp, 16, 16, 16) - local foliage = minetest.find_nodes_in_area(pos1, pos2, {"group:foliage_palette", "group:foliage_palette_wallmounted"}) - for _, fpos in pairs(foliage) do - local fnode = minetest.get_node(fpos) - local foliage_palette_index = mcl_util.get_palette_indexes_from_pos(fpos).foliage_palette_index - if fnode.param2 ~= foliage_palette_index and fnode.name ~= "mcl_core:vine" then - fnode.param2 = foliage_palette_index - minetest.set_node(fpos, fnode) - elseif fnode.name == "mcl_core:vine" then - local biome_param2 = foliage_palette_index - local rotation_param2 = mcl_util.get_colorwallmounted_rotation(fpos) - local final_param2 = (biome_param2 * 8) + rotation_param2 - if fnode.param2 ~= final_param2 then - fnode.param2 = final_param2 - minetest.set_node(fpos, fnode) - end - end - end -end -) - minetest.register_lbm({ label = "Fix water palette indexes", -- Set correct palette indexes of water in old mapblocks. name = "mcl_mapgen_core:fix_water_palette_indexes", @@ -503,16 +562,15 @@ minetest.register_lbm({ end }) -minetest.register_on_generated(function(minp, maxp, blockseed) -- Set correct palette indexes of water in new mapblocks. - local pos1, pos2 = vector.offset(minp, -16, -16, -16), vector.offset(maxp, 16, 16, 16) - local water = minetest.find_nodes_in_area(pos1, pos2, {"group:water_palette"}) - for _, wpos in pairs(water) do - local wnode = minetest.get_node(wpos) - local water_palette_index = mcl_util.get_palette_indexes_from_pos(wpos).water_palette_index - if wnode.param2 ~= water_palette_index then - wnode.param2 = water_palette_index - minetest.set_node(wpos, wnode) +minetest.register_lbm({ + label = "Fix incorrect seagrass", -- Set correct param2 of seagrass in old mapblocks. + name = "mcl_mapgen_core:fix_incorrect_seagrass", + nodenames = {"group:seagrass"}, + run_at_every_load = false, + action = function(pos, node) + if node.param2 ~= 3 then + node.param2 = 3 + minetest.set_node(pos, node) end end -end -) +}) From d8d83dd21cbe3eda2b73f217fe5c73e0d7f1081a Mon Sep 17 00:00:00 2001 From: FossFanatic Date: Tue, 4 Apr 2023 10:59:28 +0000 Subject: [PATCH 057/155] Make vines use voxelmanip colouring as well This commit adds some code to the `set_foliage_palette` function which checks for the `param2` of the foliage node in question to see whether or not said `param2` value is `0` upon first being generated. If it isn't, then it's safe to assume that said foliage is a vine, and therefore needs to use the other method of calculating the final `param2` value. --- mods/MAPGEN/mcl_mapgen_core/init.lua | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index 13aeb1841..401532c07 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -302,9 +302,12 @@ local function set_foliage_palette(minp,maxp,data2,area,biomemap,nodes) local bn = minetest.get_biome_name(biomemap[b_pos]) if bn then local biome = minetest.registered_biomes[bn] - if biome and biome._mcl_biome_type and biome._mcl_foliage_palette_index then + if biome and biome._mcl_biome_type and biome._mcl_foliage_palette_index and data2[p_pos] == 0 then data2[p_pos] = biome._mcl_foliage_palette_index lvm_used = true + elseif biome and biome._mcl_biome_type and biome._mcl_foliage_palette_index and data2[p_pos] ~= 0 then + data2[p_pos] = (biome._mcl_foliage_palette_index * 8) + data2[p_pos] + lvm_used = true end end end @@ -416,7 +419,7 @@ local function block_fixes_foliage(vm, data, data2, emin, emax, area, minp, maxp local pr = PseudoRandom(blockseed) if minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min then -- Set param2 (=color) of nodes which use the foliage colour palette. - lvm_used = set_foliage_palette(minp,maxp,data2,area,biomemap,{"group:foliage_palette"}) + lvm_used = set_foliage_palette(minp,maxp,data2,area,biomemap,{"group:foliage_palette", "group:foliage_palette_wallmounted"}) end return lvm_used end From aac6af4c20e8453c526725c60dcbd6403bef9652 Mon Sep 17 00:00:00 2001 From: FossFanatic Date: Fri, 7 Apr 2023 07:30:05 +0000 Subject: [PATCH 058/155] Small change to account for mangrove leaves --- mods/MAPGEN/mcl_mapgen_core/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index 401532c07..153da255b 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -305,7 +305,7 @@ local function set_foliage_palette(minp,maxp,data2,area,biomemap,nodes) if biome and biome._mcl_biome_type and biome._mcl_foliage_palette_index and data2[p_pos] == 0 then data2[p_pos] = biome._mcl_foliage_palette_index lvm_used = true - elseif biome and biome._mcl_biome_type and biome._mcl_foliage_palette_index and data2[p_pos] ~= 0 then + elseif biome and biome._mcl_biome_type and biome._mcl_foliage_palette_index and data2[p_pos] > 1 then data2[p_pos] = (biome._mcl_foliage_palette_index * 8) + data2[p_pos] lvm_used = true end From d28dcb1b10b96fd8f3ea6ea7317d7710ccd73b6d Mon Sep 17 00:00:00 2001 From: FossFanatic Date: Fri, 7 Apr 2023 07:36:01 +0000 Subject: [PATCH 059/155] Another small change to account for mangrove leaves This one should actually work as expected. --- mods/MAPGEN/mcl_mapgen_core/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index 153da255b..a6930bc2e 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -302,7 +302,7 @@ local function set_foliage_palette(minp,maxp,data2,area,biomemap,nodes) local bn = minetest.get_biome_name(biomemap[b_pos]) if bn then local biome = minetest.registered_biomes[bn] - if biome and biome._mcl_biome_type and biome._mcl_foliage_palette_index and data2[p_pos] == 0 then + if biome and biome._mcl_biome_type and biome._mcl_foliage_palette_index and data2[p_pos] <= 1 then data2[p_pos] = biome._mcl_foliage_palette_index lvm_used = true elseif biome and biome._mcl_biome_type and biome._mcl_foliage_palette_index and data2[p_pos] > 1 then From 01ac9ad685685666a87cda4cab6466dc97ef364a Mon Sep 17 00:00:00 2001 From: FossFanatic Date: Sun, 16 Apr 2023 09:55:05 +0000 Subject: [PATCH 060/155] Add old method back for foliage This commit adds back the old `set_node` method for the foliage, since the foliage is much more difficult to work with via the VoxelManip method due to them being part of schematics that could span across mapblocks in some cases. The old method will complement the new one by running after the VoxelManip has done its job, and fixes any foliage that the VoxelManip had missed. --- mods/MAPGEN/mcl_mapgen_core/init.lua | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index a6930bc2e..8154bb66b 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -577,3 +577,25 @@ minetest.register_lbm({ end end }) + +minetest.register_on_generated(function(minp, maxp, blockseed) -- Set correct palette indexes of missed foliage. + local pos1, pos2 = vector.offset(minp, -16, -16, -16), vector.offset(maxp, 16, 16, 16) + local foliage = minetest.find_nodes_in_area(pos1, pos2, {"group:foliage_palette", "group:foliage_palette_wallmounted"}) + for _, fpos in pairs(foliage) do + local fnode = minetest.get_node(fpos) + local foliage_palette_index = mcl_util.get_palette_indexes_from_pos(fpos).foliage_palette_index + if fnode.param2 ~= foliage_palette_index and fnode.name ~= "mcl_core:vine" then + fnode.param2 = foliage_palette_index + minetest.set_node(fpos, fnode) + elseif fnode.name == "mcl_core:vine" then + local biome_param2 = foliage_palette_index + local rotation_param2 = mcl_util.get_colorwallmounted_rotation(fpos) + local final_param2 = (biome_param2 * 8) + rotation_param2 + if fnode.param2 ~= final_param2 then + fnode.param2 = final_param2 + minetest.set_node(fpos, fnode) + end + end + end +end +) From 31b65bac91745cb29f0038d6ad233e9b0d82569f Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Sun, 16 Apr 2023 17:08:48 +0100 Subject: [PATCH 061/155] Move generator code to functions to aid in profiling --- mods/MAPGEN/mcl_mapgen_core/api.lua | 68 ++++++++++++++++++----------- 1 file changed, 43 insertions(+), 25 deletions(-) diff --git a/mods/MAPGEN/mcl_mapgen_core/api.lua b/mods/MAPGEN/mcl_mapgen_core/api.lua index 630270444..978fb7cda 100644 --- a/mods/MAPGEN/mcl_mapgen_core/api.lua +++ b/mods/MAPGEN/mcl_mapgen_core/api.lua @@ -11,6 +11,43 @@ local function roundN(n, d) return math.floor(n * m + 0.5) / m end +local function run_generators (p1, p2, blockseed) + if nodes > 0 then + for _, rec in ipairs(registered_generators) do + if rec.nf then + rec.nf(p1, p2, blockseed) + end + end + end +end + +local function update_data (vm, data, data2) + -- Write stuff + vm:set_data(data) + if param2 > 0 then + vm:set_param2_data(data2) + end +end + +local function post_generator_processing(vm, minp, maxp, deco_used, deco_table, ore_used, ore_table) + if deco_table then + minetest.generate_decorations(vm,vector.new(minp.x,deco_table.min,minp.z),vector.new(maxp.x,deco_table.max,maxp.z)) + elseif deco_used then + minetest.generate_decorations(vm) + end + if ore_table then + minetest.generate_ores(vm,vector.new(minp.x,ore_table.min,minp.z),vector.new(maxp.x,ore_table.max,maxp.z)) + elseif ore_used then + minetest.generate_ores(vm) + end +end + +local function post_generator_processing_2(vm, p1, p2, shadow) + vm:calc_lighting(p1, p2, shadow) + vm:write_to_map() + vm:update_liquids() +end + minetest.register_on_generated(function(minp, maxp, blockseed) local t1 = os.clock() local p1, p2 = {x=minp.x, y=minp.y, z=minp.z}, {x=maxp.x, y=maxp.y, z=maxp.z} @@ -49,34 +86,13 @@ minetest.register_on_generated(function(minp, maxp, blockseed) end if lvm_used then - -- Write stuff - vm:set_data(data) - if param2 > 0 then - vm:set_param2_data(data2) - end - if deco_table then - minetest.generate_decorations(vm,vector.new(minp.x,deco_table.min,minp.z),vector.new(maxp.x,deco_table.max,maxp.z)) - elseif deco_used then - minetest.generate_decorations(vm) - end - if ore_table then - minetest.generate_ores(vm,vector.new(minp.x,ore_table.min,minp.z),vector.new(maxp.x,ore_table.max,maxp.z)) - elseif ore_used then - minetest.generate_ores(vm) - end - vm:calc_lighting(p1, p2, shadow) - vm:write_to_map() - vm:update_liquids() + update_data (vm, data, data2) + post_generator_processing(vm, minp, maxp, deco_used, deco_table, ore_used, ore_table) + post_generator_processing_2(vm, p1, p2, shadow) end end - if nodes > 0 then - for _, rec in ipairs(registered_generators) do - if rec.nf then - rec.nf(p1, p2, blockseed) - end - end - end + run_generators (p1, p2, blockseed) mcl_vars.add_chunk(minp) if logging then @@ -84,6 +100,8 @@ minetest.register_on_generated(function(minp, maxp, blockseed) end end) + + function minetest.register_on_generated(node_function) mcl_mapgen_core.register_generator("mod_"..minetest.get_current_modname().."_"..tostring(#registered_generators+1), nil, node_function) end From 1015f5a569e2494cc9d8caaf9848b97fe416edfd Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Sun, 16 Apr 2023 17:10:17 +0100 Subject: [PATCH 062/155] Optimize folliage fixes code --- mods/MAPGEN/mcl_mapgen_core/init.lua | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index 8154bb66b..467d02134 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -578,8 +578,11 @@ minetest.register_lbm({ end }) -minetest.register_on_generated(function(minp, maxp, blockseed) -- Set correct palette indexes of missed foliage. - local pos1, pos2 = vector.offset(minp, -16, -16, -16), vector.offset(maxp, 16, 16, 16) +-- We go outside x and y for where trees are placed next to a biome that has already been generated. +-- We go above maxp.y because trees can often get placed close to the top of a generated area and folliage may not +-- be coloured correctly. +local function fix_folliage_missed (minp, maxp) + local pos1, pos2 = vector.offset(minp, -4, 0, -4), vector.offset(maxp, 4, 10, 4) local foliage = minetest.find_nodes_in_area(pos1, pos2, {"group:foliage_palette", "group:foliage_palette_wallmounted"}) for _, fpos in pairs(foliage) do local fnode = minetest.get_node(fpos) @@ -598,4 +601,10 @@ minetest.register_on_generated(function(minp, maxp, blockseed) -- Set correct pa end end end -) + +minetest.register_on_generated(function(minp, maxp, blockseed) -- Set correct palette indexes of missed foliage. + if maxp.y < 0 then + return + end + fix_folliage_missed (minp, maxp) +end) From 3b1464ecc88d73eb7d2c9c0d3276f4aeff05bd0e Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Sun, 16 Apr 2023 17:49:27 +0100 Subject: [PATCH 063/155] Tweak leaf generator numbers to catch missed jungle leaves --- mods/MAPGEN/mcl_mapgen_core/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index 467d02134..e6420f91d 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -582,7 +582,7 @@ minetest.register_lbm({ -- We go above maxp.y because trees can often get placed close to the top of a generated area and folliage may not -- be coloured correctly. local function fix_folliage_missed (minp, maxp) - local pos1, pos2 = vector.offset(minp, -4, 0, -4), vector.offset(maxp, 4, 10, 4) + local pos1, pos2 = vector.offset(minp, -6, 0, -6), vector.offset(maxp, 6, 14, 6) local foliage = minetest.find_nodes_in_area(pos1, pos2, {"group:foliage_palette", "group:foliage_palette_wallmounted"}) for _, fpos in pairs(foliage) do local fnode = minetest.get_node(fpos) From 65aa185ffa7ed5d31aaed1498cca7392ede5e1bc Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Sat, 15 Apr 2023 17:09:37 +0200 Subject: [PATCH 064/155] global 'bed button' cooldown --- mods/ITEMS/mcl_beds/functions.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index 56e4a232b..2ca620236 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -438,12 +438,14 @@ local playermessagecounter = {} It gets reset after 10 secs using a globalstep --]] +local chatbuttonused = false local globalstep_timer = 0 minetest.register_globalstep(function(dtime) globalstep_timer = globalstep_timer + dtime if globalstep_timer >= 10 then globalstep_timer = 0 playermessagecounter = {} + chatbuttonused = false end end) @@ -480,7 +482,13 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end if fields.defaultmessage then + if chatbuttonused then + minetest.chat_send_player(player:get_player_name(),S("Sorry, but you have to wait @1 seconds until you may use this button again!",tostring(math.ceil(10-globalstep_timer)))) + return + end + if (not exceeded_rate_limit(player:get_player_name())) and shout_priv_check(player) then + chatbuttonused = true minetest.chat_send_all(minetest.format_chat_message(player:get_player_name(), S("Hey! Would you guys mind sleeping?"))) end return From 326e805798d370fa16b4e483ea99972b4a8af94b Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Sat, 15 Apr 2023 17:11:47 +0200 Subject: [PATCH 065/155] update translation stuff --- mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr | 3 ++- mods/ITEMS/mcl_beds/locale/template.txt | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr b/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr index ae035f3bb..97867b44b 100644 --- a/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr +++ b/mods/ITEMS/mcl_beds/locale/mcl_beds.de.tr @@ -45,4 +45,5 @@ Chat:=Chat: send!=senden! You are missing the 'shout' privilege! It's required in order to talk in chat...=Ihnen fehlt das 'shout' Privileg! Es wird benötigt, um im Chat reden zu können... You exceeded the maximum number of messages per 10 seconds!=Sie haben die maximale Anzahl an Chatnachrichten pro 10 Sekunden überschritten! -Hey! Would you guys mind sleeping?=Hey, würdet Ihr bitte zu Bett gehen? \ No newline at end of file +Hey! Would you guys mind sleeping?=Hey, würdet Ihr bitte zu Bett gehen? +Sorry, but you have to wait @1 seconds until you may use this button again!=Sie müssen leider noch @1 Sekunden warten, bevor sie diesen Knopf erneut benutzen können! \ No newline at end of file diff --git a/mods/ITEMS/mcl_beds/locale/template.txt b/mods/ITEMS/mcl_beds/locale/template.txt index dd58d74e8..42e59509e 100644 --- a/mods/ITEMS/mcl_beds/locale/template.txt +++ b/mods/ITEMS/mcl_beds/locale/template.txt @@ -45,4 +45,5 @@ Chat:= send!= You are missing the 'shout' privilege! It's required in order to talk in chat...= You exceeded the maximum number of messages per 10 seconds!= -Hey! Would you guys mind sleeping?= \ No newline at end of file +Hey! Would you guys mind sleeping?= +Sorry, but you have to wait @1 seconds until you may use this button again!= \ No newline at end of file From b374301ebfb8a4502ae81619140b75264957c08c Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Wed, 19 Apr 2023 13:54:25 +0100 Subject: [PATCH 066/155] Throttle applies to default or custom sleep message --- mods/ITEMS/mcl_beds/functions.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index 2ca620236..59eea5f33 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -474,22 +474,22 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) return end + local custom_sleep_message if fields.chatsubmit and fields.chatmessage ~= "" then - if (not exceeded_rate_limit(player:get_player_name())) and shout_priv_check(player) then - minetest.chat_send_all(minetest.format_chat_message(player:get_player_name(), fields.chatmessage)) - end - return + custom_sleep_message = fields.chatmessage end - if fields.defaultmessage then + if custom_sleep_message or fields.defaultmessage then if chatbuttonused then - minetest.chat_send_player(player:get_player_name(),S("Sorry, but you have to wait @1 seconds until you may use this button again!",tostring(math.ceil(10-globalstep_timer)))) + local time_to_wait = math.ceil(10-globalstep_timer) + minetest.chat_send_player(player:get_player_name(),S("Sorry, but you have to wait @1 seconds until you may use this button again!", tostring(time_to_wait))) return end if (not exceeded_rate_limit(player:get_player_name())) and shout_priv_check(player) then chatbuttonused = true - minetest.chat_send_all(minetest.format_chat_message(player:get_player_name(), S("Hey! Would you guys mind sleeping?"))) + local message = custom_sleep_message or S("Hey! Would you guys mind sleeping?") + minetest.chat_send_all(minetest.format_chat_message(player:get_player_name(), message)) end return end From cdb2bc20b08b670f73448d8789b9d425ae254739 Mon Sep 17 00:00:00 2001 From: Johannes Fritz Date: Thu, 13 Apr 2023 14:16:19 -0500 Subject: [PATCH 067/155] solar panels: No crash when minetest.get_natural_light() return nil --- .../REDSTONE/mesecons_solarpanel/init.lua | 51 +------------------ 1 file changed, 2 insertions(+), 49 deletions(-) diff --git a/mods/ITEMS/REDSTONE/mesecons_solarpanel/init.lua b/mods/ITEMS/REDSTONE/mesecons_solarpanel/init.lua index 7780cbfee..f4e63b78a 100644 --- a/mods/ITEMS/REDSTONE/mesecons_solarpanel/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_solarpanel/init.lua @@ -1,55 +1,8 @@ local S = minetest.get_translator(minetest.get_current_modname()) -local function path_to_sunlight_exists(position, light_level) - local neighbours = { - { x = 0, y = 0, z =-1 }, - { x = 0, y = 0, z = 1 }, - { x = 0, y =-1, z = 0 }, - { x = 0, y = 1, z = 0 }, - { x =-1, y = 0, z = 0 }, - { x = 1, y = 0, z = 0 }, - } - for i=1, #neighbours do - local offset = neighbours[i] - local position_new = vector.add( - position, - offset - ) - local light_level_new = minetest.get_node_light( - position_new, - nil - ) - if 15 == light_level_new then - -- found the sunlight - return true - elseif light_level_new > light_level then - -- search where light is brighter - if path_to_sunlight_exists( - position_new, - light_level_new - ) then - return true - end - end - end -end - local function sunlight_visible(position) - local light_level = mcl_util.get_natural_light (position) - if light_level >= 12 then - --minetest.log("Light is greater than 12") - return true - else - local time = minetest.get_timeofday() * 24000 - -- only check light level during day - if time > 6000 and time < 18000 then - light_level = minetest.get_node_light(position, nil) - if light_level >= 12 then - return path_to_sunlight_exists(position, 12) - end - end - end - return false + local light_level = mcl_util.get_natural_light(position) + return light_level ~= nil and light_level >= 12 end local boxes = { -8/16, -8/16, -8/16, 8/16, -2/16, 8/16 } From 5db1e1876c140bdec180d18828cd8b1c002e59c6 Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Wed, 19 Apr 2023 19:32:21 +0200 Subject: [PATCH 068/155] playerbound music toggle (between 94e554aa1a and 5481f0109c) --- mods/PLAYER/mcl_music/init.lua | 118 ++++++++++++++----- mods/PLAYER/mcl_music/locale/mcl_music.de.tr | 7 ++ mods/PLAYER/mcl_music/locale/template.txt | 7 ++ 3 files changed, 105 insertions(+), 27 deletions(-) create mode 100644 mods/PLAYER/mcl_music/locale/mcl_music.de.tr create mode 100644 mods/PLAYER/mcl_music/locale/template.txt diff --git a/mods/PLAYER/mcl_music/init.lua b/mods/PLAYER/mcl_music/init.lua index 0d2f9c52e..7f8be5acf 100644 --- a/mods/PLAYER/mcl_music/init.lua +++ b/mods/PLAYER/mcl_music/init.lua @@ -1,3 +1,5 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + local modname = minetest.get_current_modname() local modpath = minetest.get_modpath(modname) @@ -46,7 +48,7 @@ local function pick_track(dimension, underground) minetest.log("action", "[mcl_music] Playing track: " .. chosen_track .. ", for context: " .. track_key) return chosen_track else - --? + -- ? end return nil @@ -102,38 +104,40 @@ local function play() local day_count = minetest.get_day_count() for _, player in pairs(minetest.get_connected_players()) do - local player_name = player:get_player_name() - local hp = player:get_hp() - local pos = player:get_pos() - local dimension = mcl_worlds.pos_to_dimension(pos) + if not player:get_meta():get("mcl_music:disable") then + local player_name = player:get_player_name() + local hp = player:get_hp() + local pos = player:get_pos() + local dimension = mcl_worlds.pos_to_dimension(pos) - local listener = listeners[player_name] - local handle = listener and listener.handle + local listener = listeners[player_name] + local handle = listener and listener.handle - --local old_hp = listener and listener.hp - --local is_hp_changed = old_hp and (math.abs(old_hp - hp) > 0.00001) or false + --local old_hp = listener and listener.hp + --local is_hp_changed = old_hp and (math.abs(old_hp - hp) > 0.00001) or false - local old_dimension = listener and listener.dimension - local is_dimension_changed = old_dimension and (old_dimension ~= dimension) or false + local old_dimension = listener and listener.dimension + local is_dimension_changed = old_dimension and (old_dimension ~= dimension) or false - --minetest.log("handle: " .. dump (handle)) - if is_dimension_changed then - stop_music_for_listener_name(player_name) - if not listeners[player_name] then - listeners[player_name] = {} - end - listeners[player_name].hp = hp - listeners[player_name].dimension = dimension - elseif not handle and (not listener or (listener.day_count ~= day_count)) then - local underground = dimension == "overworld" and pos and pos.y < 0 - local track = pick_track(dimension, underground) - if track then - play_song(track, player_name, dimension, day_count) + -- minetest.log("handle: " .. dump (handle)) + if is_dimension_changed then + stop_music_for_listener_name(player_name) + if not listeners[player_name] then + listeners[player_name] = {} + end + listeners[player_name].hp = hp + listeners[player_name].dimension = dimension + elseif not handle and (not listener or (listener.day_count ~= day_count)) then + local underground = dimension == "overworld" and pos and pos.y < 0 + local track = pick_track(dimension, underground) + if track then + play_song(track, player_name, dimension, day_count) + else + --minetest.log("no track found. weird") + end else - --minetest.log("no track found. weird") + --minetest.log("else") end - else - --minetest.log("else") end end @@ -149,6 +153,10 @@ if music_enabled then stop_music_for_listener_name(player_name) end) + minetest.register_on_leaveplayer(function(player, timed_out) + listeners[player:get_player_name()] = nil + end) + minetest.register_on_respawnplayer(function(player) local player_name = player:get_player_name() stop_music_for_listener_name(player_name) @@ -156,3 +164,59 @@ if music_enabled then else minetest.log("action", "[mcl_music] In-game music is deactivated") end + +minetest.register_chatcommand("music", { + params = "[on|off|invert []]", + description = S("Turns music for yourself or another player on or off."), + func = function(sender_name, params) + local argtable = {} + for str in string.gmatch(params, "([^%s]+)") do + table.insert(argtable, str) + end + + local action = argtable[1] + local playername = argtable[2] + + local sender = minetest.get_player_by_name(sender_name) + local target_player = nil + + if not action or action == "" then action = "invert" end + + if not playername or playername == "" or sender_name == playername then + target_player = sender + playername =sender_name + elseif not minetest.check_player_privs(sender, "debug") then -- Self-use handled above + minetest.chat_send_player(sender_name, S("You need the debug privilege in order to turn ingame music on or off for somebody else!")) + return + else -- Admin + target_player = minetest.get_player_by_name(playername) + end + + if not target_player then + minetest.chat_send_player(sender_name, S("Couldn't find player @1!", playername)) + return + end + + local meta = target_player:get_meta() + local display_new_state = "unknown" -- Should never be displayed -> no translation + + if action == "invert" then + if not meta:get("mcl_music:disable") then + meta:set_int("mcl_music:disable", 1) + display_new_state = S("off") + else + meta:set_string("mcl_music:disable", "") -- This deletes the meta value! + display_new_state = S("on") + end + elseif action == "on" then + meta:set_string("mcl_music:disable", "") -- Delete + display_new_state = S("on") + else + meta:set_int("mcl_music:disable", 1) + display_new_state = S("off") + end + + stop_music_for_listener_name(playername) + minetest.chat_send_player(sender_name, S("Set music for @1 to: @2", playername, display_new_state)) + end, +}) \ No newline at end of file diff --git a/mods/PLAYER/mcl_music/locale/mcl_music.de.tr b/mods/PLAYER/mcl_music/locale/mcl_music.de.tr new file mode 100644 index 000000000..83621545f --- /dev/null +++ b/mods/PLAYER/mcl_music/locale/mcl_music.de.tr @@ -0,0 +1,7 @@ +# textdomain: mcl_music +You need the debug privilege in order to turn ingame music on or off for somebody else!=Sie benötigen das „debug“ Privileg, um die Musik (im Spiel) für jemand anders ein oder aus zu schalten! +Couldn't find player @1!= Spieler @1 konnte nicht gefunden werden! +Set music for @1 to: @2=Musik für @1 auf @2 gesetzt +Turns music for yourself or another player on or off.=Schaltet die Musik für Sie selbst oder jemand anders ein oder aus. +on=an +off=aus \ No newline at end of file diff --git a/mods/PLAYER/mcl_music/locale/template.txt b/mods/PLAYER/mcl_music/locale/template.txt new file mode 100644 index 000000000..66d60e9f5 --- /dev/null +++ b/mods/PLAYER/mcl_music/locale/template.txt @@ -0,0 +1,7 @@ +# textdomain: mcl_music +You need the debug privilege in order to turn ingame music on or off for somebody else!= +Couldn't find player @1!= +Set music for @1 to: @2= +Turns music for yourself or another player on or off.= +on= +off= \ No newline at end of file From 198eb630e1b12f75d9524f586fa1a5cc723106c7 Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Tue, 4 Apr 2023 21:57:28 +0200 Subject: [PATCH 069/155] replace globalstep with abm --- mods/ITEMS/mcl_beacons/init.lua | 54 ++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_beacons/init.lua b/mods/ITEMS/mcl_beacons/init.lua index 4614d5ce1..f0a3a15ef 100644 --- a/mods/ITEMS/mcl_beacons/init.lua +++ b/mods/ITEMS/mcl_beacons/init.lua @@ -178,6 +178,24 @@ local function beacon_blockcheck(pos) end end +local function is_obstructed(pos) --also removes beacon beam if true + + for y=pos.y+1, pos.y+100 do + + local nodename = minetest.get_node({x=pos.x,y=y, z = pos.z}).name + if nodename ~= "mcl_core:bedrock" and nodename ~= "air" and nodename ~= "mcl_core:void" and nodename ~= "ignore" then --ignore means not loaded, let's just assume that's air + if nodename ~="mcl_beacons:beacon_beam" then + if minetest.get_item_group(nodename,"glass") == 0 and minetest.get_item_group(nodename,"material_glass") == 0 then + remove_beacon_beam(pos) + return true + end + end + end + end + + return false +end + local function effect_player(effect,pos,power_level, effect_level,player) local distance = vector.distance(player:get_pos(), pos) if distance > (power_level+1)*10 then return end @@ -192,6 +210,7 @@ local function effect_player(effect,pos,power_level, effect_level,player) end end +--[[ local function globalstep_function(pos,player) local meta = minetest.get_meta(pos) local power_level = beacon_blockcheck(pos) @@ -219,6 +238,25 @@ local function globalstep_function(pos,player) effect_player(effect_string,pos,power_level,meta:get_int("effect_level"),player) end end +--]] + +local function abm_func(pos) + local meta = minetest.get_meta(pos) + local power_level = beacon_blockcheck(pos) + local effect_string = meta:get_string("effect") + + if meta:get_int("effect_level") == 2 and power_level < 4 then --no need to run loops when beacon is in an invalid setup :Pi + return + end + + for _, obj in ipairs(minetest.get_objects_inside_radius(pos, (power_level+1)*10)) do + if obj:is_player() then + if not is_obstructed(pos) then + effect_player(effect_string,pos,power_level,meta:get_int("effect_level"),obj) + end + end + end +end minetest.register_node("mcl_beacons:beacon", { description = S"Beacon", @@ -330,7 +368,8 @@ minetest.register_node("mcl_beacons:beacon", { minetest.set_node({x=pos.x,y=y,z=pos.z},{name="mcl_beacons:beacon_beam",param2=beam_palette_index}) end end - globalstep_function(pos,sender)--call it once outside the globalstep so the player gets the effect right after selecting it + abm_func(pos) --call it once outside the globalstep so the player gets the effect right after selecting it + --globalstep_function(pos,sender)--call it once outside the globalstep so the player gets the effect right after selecting it end end end, @@ -354,6 +393,7 @@ end local timer = 0 +--[[ minetest.register_globalstep(function(dtime) timer = timer + dtime if timer >= 3 then @@ -367,6 +407,7 @@ minetest.register_globalstep(function(dtime) timer = 0 end end) +--]] minetest.register_abm{ @@ -392,6 +433,17 @@ minetest.register_abm{ end, } + +minetest.register_abm{ + label="apply beacon effects to players", + nodenames = {"mcl_beacons:beacon"}, + interval = 3, + chance = 1, + action = function(pos) + abm_func(pos) -- for some FUC**** reason I can't just say abm_func directly, so this is a dirty workaround + end, +} + minetest.register_craft({ output = "mcl_beacons:beacon", recipe = { From 181cb73e45a3e8ddb404656cb58749ebf7330edb Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Tue, 4 Apr 2023 21:58:33 +0200 Subject: [PATCH 070/155] remove commented out code --- mods/ITEMS/mcl_beacons/init.lua | 49 +-------------------------------- 1 file changed, 1 insertion(+), 48 deletions(-) diff --git a/mods/ITEMS/mcl_beacons/init.lua b/mods/ITEMS/mcl_beacons/init.lua index f0a3a15ef..12c483d4b 100644 --- a/mods/ITEMS/mcl_beacons/init.lua +++ b/mods/ITEMS/mcl_beacons/init.lua @@ -210,36 +210,6 @@ local function effect_player(effect,pos,power_level, effect_level,player) end end ---[[ -local function globalstep_function(pos,player) - local meta = minetest.get_meta(pos) - local power_level = beacon_blockcheck(pos) - local effect_string = meta:get_string("effect") - if meta:get_int("effect_level") == 2 and power_level < 4 then - return - else - local obstructed = false - for y=pos.y+1, pos.y+100 do - - local nodename = minetest.get_node({x=pos.x,y=y, z = pos.z}).name - if nodename ~= "mcl_core:bedrock" and nodename ~= "air" and nodename ~= "mcl_core:void" and nodename ~= "ignore" then --ignore means not loaded, let's just assume that's air - if nodename ~="mcl_beacons:beacon_beam" then - if minetest.get_item_group(nodename,"glass") == 0 and minetest.get_item_group(nodename,"material_glass") == 0 then - obstructed = true - remove_beacon_beam(pos) - return - end - end - end - end - if obstructed then - return - end - effect_player(effect_string,pos,power_level,meta:get_int("effect_level"),player) - end -end ---]] - local function abm_func(pos) local meta = minetest.get_meta(pos) local power_level = beacon_blockcheck(pos) @@ -368,9 +338,7 @@ minetest.register_node("mcl_beacons:beacon", { minetest.set_node({x=pos.x,y=y,z=pos.z},{name="mcl_beacons:beacon_beam",param2=beam_palette_index}) end end - abm_func(pos) --call it once outside the globalstep so the player gets the effect right after selecting it - --globalstep_function(pos,sender)--call it once outside the globalstep so the player gets the effect right after selecting it - end + abm_func(pos) --call it once outside the globalstep so the player gets the effect right after selecting it end end end, light_source = 14, @@ -393,21 +361,6 @@ end local timer = 0 ---[[ -minetest.register_globalstep(function(dtime) - timer = timer + dtime - if timer >= 3 then - for _, player in ipairs(minetest.get_connected_players()) do - local player_pos = player:get_pos() - local pos_list = minetest.find_nodes_in_area({x=player_pos.x-50, y=player_pos.y-50, z=player_pos.z-50}, {x=player_pos.x+50, y=player_pos.y+50, z=player_pos.z+50},"mcl_beacons:beacon") - for _, pos in ipairs(pos_list) do - globalstep_function(pos,player) - end - end - timer = 0 - end -end) ---]] minetest.register_abm{ From 80cde37e6517591715c466c8c5f5eb82ff531ded Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Tue, 4 Apr 2023 21:59:50 +0200 Subject: [PATCH 071/155] remove empty lines and unneeded code --- mods/ITEMS/mcl_beacons/init.lua | 7 ------- 1 file changed, 7 deletions(-) diff --git a/mods/ITEMS/mcl_beacons/init.lua b/mods/ITEMS/mcl_beacons/init.lua index 12c483d4b..ee9c5a67b 100644 --- a/mods/ITEMS/mcl_beacons/init.lua +++ b/mods/ITEMS/mcl_beacons/init.lua @@ -179,9 +179,7 @@ local function beacon_blockcheck(pos) end local function is_obstructed(pos) --also removes beacon beam if true - for y=pos.y+1, pos.y+100 do - local nodename = minetest.get_node({x=pos.x,y=y, z = pos.z}).name if nodename ~= "mcl_core:bedrock" and nodename ~= "air" and nodename ~= "mcl_core:void" and nodename ~= "ignore" then --ignore means not loaded, let's just assume that's air if nodename ~="mcl_beacons:beacon_beam" then @@ -359,10 +357,6 @@ function register_beaconfuel(itemstring) table.insert(beacon_fuellist, itemstring) end -local timer = 0 - - - minetest.register_abm{ label="update beacon beam", nodenames = {"mcl_beacons:beacon_beam"}, @@ -386,7 +380,6 @@ minetest.register_abm{ end, } - minetest.register_abm{ label="apply beacon effects to players", nodenames = {"mcl_beacons:beacon"}, From 1a1473e8c0adfdf7697b7e9e944328958b3e2f56 Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Tue, 4 Apr 2023 22:03:29 +0200 Subject: [PATCH 072/155] insert missing end --- mods/ITEMS/mcl_beacons/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ITEMS/mcl_beacons/init.lua b/mods/ITEMS/mcl_beacons/init.lua index ee9c5a67b..0a13c87be 100644 --- a/mods/ITEMS/mcl_beacons/init.lua +++ b/mods/ITEMS/mcl_beacons/init.lua @@ -337,6 +337,7 @@ minetest.register_node("mcl_beacons:beacon", { end end abm_func(pos) --call it once outside the globalstep so the player gets the effect right after selecting it end + end end end, light_source = 14, From a8c989edd85dabc8878a594e4fafe61705aef604 Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Wed, 19 Apr 2023 16:27:35 +0200 Subject: [PATCH 073/155] don't get all objects in radius --- mods/ITEMS/mcl_beacons/init.lua | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/mods/ITEMS/mcl_beacons/init.lua b/mods/ITEMS/mcl_beacons/init.lua index 0a13c87be..e738aeec2 100644 --- a/mods/ITEMS/mcl_beacons/init.lua +++ b/mods/ITEMS/mcl_beacons/init.lua @@ -213,16 +213,15 @@ local function abm_func(pos) local power_level = beacon_blockcheck(pos) local effect_string = meta:get_string("effect") - if meta:get_int("effect_level") == 2 and power_level < 4 then --no need to run loops when beacon is in an invalid setup :Pi + if meta:get_int("effect_level") == 2 and power_level < 4 then --no need to run loops when beacon is in an invalid setup :P return end - for _, obj in ipairs(minetest.get_objects_inside_radius(pos, (power_level+1)*10)) do - if obj:is_player() then - if not is_obstructed(pos) then - effect_player(effect_string,pos,power_level,meta:get_int("effect_level"),obj) - end - end + for _, obj in pairs(minetest.get_connected_players()) do + if vector.distance(pos,obj:get_pos()) > (power_level+1)*10 then return end --I used Pythagoras at first, and ignored this method lol + if not is_obstructed(pos) then + effect_player(effect_string,pos,power_level,meta:get_int("effect_level"),obj) + end end end From b15482012edc6187b2d8a46cc53655bc294e30f7 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Thu, 27 Apr 2023 19:04:36 +0100 Subject: [PATCH 074/155] Implement review feedback. --- mods/ITEMS/mcl_beacons/init.lua | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/mods/ITEMS/mcl_beacons/init.lua b/mods/ITEMS/mcl_beacons/init.lua index e738aeec2..30a80bc32 100644 --- a/mods/ITEMS/mcl_beacons/init.lua +++ b/mods/ITEMS/mcl_beacons/init.lua @@ -178,7 +178,7 @@ local function beacon_blockcheck(pos) end end -local function is_obstructed(pos) --also removes beacon beam if true +local function clear_obstructed_beam(pos) for y=pos.y+1, pos.y+100 do local nodename = minetest.get_node({x=pos.x,y=y, z = pos.z}).name if nodename ~= "mcl_core:bedrock" and nodename ~= "air" and nodename ~= "mcl_core:void" and nodename ~= "ignore" then --ignore means not loaded, let's just assume that's air @@ -208,20 +208,25 @@ local function effect_player(effect,pos,power_level, effect_level,player) end end -local function abm_func(pos) - local meta = minetest.get_meta(pos) - local power_level = beacon_blockcheck(pos) +local function apply_effects_to_all_players(pos) + local meta = minetest.get_meta(pos) local effect_string = meta:get_string("effect") + local effect_level = meta:get_int("effect_level") - if meta:get_int("effect_level") == 2 and power_level < 4 then --no need to run loops when beacon is in an invalid setup :P + local power_level = beacon_blockcheck(pos) + + if effect_level == 2 and power_level < 4 then --no need to run loops when beacon is in an invalid setup :P return end - for _, obj in pairs(minetest.get_connected_players()) do - if vector.distance(pos,obj:get_pos()) > (power_level+1)*10 then return end --I used Pythagoras at first, and ignored this method lol - if not is_obstructed(pos) then - effect_player(effect_string,pos,power_level,meta:get_int("effect_level"),obj) - end + local beacon_distance = (power_level + 1) * 10 + + for _, player in pairs(minetest.get_connected_players()) do + if vector.distance(pos, player:get_pos()) <= beacon_distance then + if not clear_obstructed_beam(pos) then + effect_player(effect_string, pos, power_level, effect_level, player) + end + end end end @@ -335,7 +340,7 @@ minetest.register_node("mcl_beacons:beacon", { minetest.set_node({x=pos.x,y=y,z=pos.z},{name="mcl_beacons:beacon_beam",param2=beam_palette_index}) end end - abm_func(pos) --call it once outside the globalstep so the player gets the effect right after selecting it end + apply_effects_to_all_players(pos) --call it once outside the globalstep so the player gets the effect right after selecting it end end end, @@ -386,7 +391,7 @@ minetest.register_abm{ interval = 3, chance = 1, action = function(pos) - abm_func(pos) -- for some FUC**** reason I can't just say abm_func directly, so this is a dirty workaround + apply_effects_to_all_players(pos) end, } From 7dc09e3ebdfa830a96b301d4a9da031582d9523b Mon Sep 17 00:00:00 2001 From: megustanlosfrijoles Date: Thu, 27 Apr 2023 19:50:10 +0000 Subject: [PATCH 075/155] Add spanish translations (#3659) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I just added some translations to Spanish that were missing Co-authored-by: José Muñoz Reviewed-on: https://git.minetest.land/MineClone2/MineClone2/pulls/3659 Reviewed-by: ancientmarinerdev Co-authored-by: megustanlosfrijoles Co-committed-by: megustanlosfrijoles --- .../ENTITIES/mcl_boats/locale/mcl_boats.es.tr | 3 + .../mcl_paintings/locale/mcl_paintings.es.tr | 2 + .../locale/mcl_achievements.es.tr | 65 +++++++++++++++++++ mods/PLAYER/mcl_skins/locale/mcl_skins.es.tr | 14 ++++ 4 files changed, 84 insertions(+) create mode 100644 mods/ENTITIES/mcl_paintings/locale/mcl_paintings.es.tr create mode 100644 mods/PLAYER/mcl_skins/locale/mcl_skins.es.tr diff --git a/mods/ENTITIES/mcl_boats/locale/mcl_boats.es.tr b/mods/ENTITIES/mcl_boats/locale/mcl_boats.es.tr index 644efdb6b..d3596e056 100644 --- a/mods/ENTITIES/mcl_boats/locale/mcl_boats.es.tr +++ b/mods/ENTITIES/mcl_boats/locale/mcl_boats.es.tr @@ -8,3 +8,6 @@ Jungle Boat=Barca de la selva Oak Boat=Barca de roble 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.=Haga clic derecho en una fuente de agua para colocar el barco. Haga clic derecho en el barco para entrar. Utilice [Izquierda] y [Derecha] para dirigir, [Adelante] para acelerar y [Atrás] para reducir la velocidad o retroceder. Haga clic derecho en el barco nuevamente para dejarlo, golpee el barco para que se caiga como un artículo. Spruce Boat=Barca de abeto +Water vehicle=Vehículo acuático +Sneak to dismount=Agáchate para bajar +Obsidian Boat=Barca de obsidiana diff --git a/mods/ENTITIES/mcl_paintings/locale/mcl_paintings.es.tr b/mods/ENTITIES/mcl_paintings/locale/mcl_paintings.es.tr new file mode 100644 index 000000000..d1e4d3f24 --- /dev/null +++ b/mods/ENTITIES/mcl_paintings/locale/mcl_paintings.es.tr @@ -0,0 +1,2 @@ +# textdomain:mcl_paintings +Painting=Cuadro diff --git a/mods/HUD/mcl_achievements/locale/mcl_achievements.es.tr b/mods/HUD/mcl_achievements/locale/mcl_achievements.es.tr index 2044e8261..c398bb14c 100644 --- a/mods/HUD/mcl_achievements/locale/mcl_achievements.es.tr +++ b/mods/HUD/mcl_achievements/locale/mcl_achievements.es.tr @@ -47,3 +47,68 @@ Use a crafting table to craft a wooden hoe from wooden planks and sticks.=Usa un Use a crafting table to craft a wooden pickaxe from wooden planks and sticks.=Usa una mesa de trabajo para hacer un pico de madera con tablas de madera procesada y palos de madera. Use obsidian and a fire starter to construct a Nether portal.=Usa obsidiana y un iniciador de fuego para construir un portal abisal. Use wheat to craft a bread.=Usa trigo para elaborar pan. +Who is Cutting Onions?=¿Quién esta cortando cebollas? +Pick up a crying obsidian from the floor.=Recoge una obsidiana llorosa del suelo +Hidden in the Depths=Oculto en las profundidades +Pick up an Ancient Debris from the floor.=Recoge un Escombro Ancestral del suelo +The Nether=El Nether +Bring summer clothes.@nHint: Enter the Nether.=Tráete ropa de verano.@nSugerencia: Entra al Nether +Isn't It Iron Pick=¿No es hierrónico? +Craft a iron pickaxe using sticks and iron.=Crea un pico de hierro usando palos y hierro. +Postmortal=Post mortem +Use a Totem of Undying to cheat death.=Usa un tótem de inmortalidad para engañar a la muerte +Sweet Dreams=Dulces sueños +Sleep in a bed to change your respawn point.=Duerme en una cama para cambiar tu punto de reaparición. +Not Quite "Nine" Lives=No "siete" vidas exactamente +Charge a Respawn Anchor to the maximum.=Carga un nexo de reaparición al máximo. +What A Deal!=¡Qué buen trato! +Successfully trade with a Villager.=Comercia con un aldeano. +Withering Heights=Dr. Witherstein +Summon the wither from the dead.=Invoca al wither desde los muertos. +The Cutest Predator=El depredador más lindo +Catch an Axolotl with a bucket!=Atrapa a un ajolote en un cubo +Fishy Business=Un asuno escamoso +Catch a fish.@nHint: Catch a fish, salmon, clownfish, or pufferfish.=Atrapa un pez.@nSugerencia: Atrapa un pez, salmón, pez payaso, o pez globo. +Country Lode, Take Me Home=Magnetita llévame a casita +Use a compass on a Lodestone.=Usa una brújula sobre una magnetita +Serious Dedication=Dedicación seria +Use a Netherite Ingot to upgrade a hoe, and then completely reevaluate your life choices.=Usa un lingote de netherita para mejorar una azada, y luego revalúa lo que estás haciendo con tu vida. +Local Brewery=Destilería local +Brew a Potion.@nHint: Take a potion or glass bottle out of the brewing stand.=Prepara una poción.@nSugerencia: Saca una poción o botella de vidrio de la destiladora +Enchanter=Aprendiz de mago +Enchant an item using an Enchantment Table.=Encanta un objeto usando la mesa de encantamientos +Bring Home the Beacon=Hágase la luz +Use a beacon.=Usa un faro. +Beaconator=Faroneitor +Use a fully powered beacon.=Utiliza un faro a máxima potencia. +The Next Generation=La nueva generación +Hold the Dragon Egg.@nHint: Pick up the egg from the ground and have it in your inventory.=Consigue el huevo de dragón.@nSugerencia: Recoge el huevo del suelo, y colócalo en tu inventario. +The End... Again...=El fin... de nuevo... +Respawn the Ender Dragon.=Vuelve a invocar al Enderdragón. +Sky's the Limit=El cielo es el límite +Find the elytra and prepare to fly above and beyond!=¿Encuentra los élitros y prepárate para volar al infinito y más allá! +Free the End=Libera el End +Kill the ender dragon. Good Luck!=Mata al Enderdragón. Buena suerte! +Bee Our Guest=Abelante, esta es tu casa +Use a campfire to collect a bottle of honey from a beehive without aggrivating the bees inside.=Usa una fogata y una botella para obtener miel de una colmena sin enojar a las abejas. +Total Beelocation=Abejémonos de aquí +Move a bee nest, with 3 bees inside, using a silk touch enchanted tool.=Mueve una colmena que tenga 3 abejas usando una herramienta con toque de seda. +Wax On=Encerando ando +Apply honeycomb to a copper block to protect it from the elements.=Encera un bloque de cobre con un panal de abejas para protegerlo de los elementos. +Wax Off=Pulir cera +Scrape wax off of a copper block.=Quita la cera de un bloque de cobre +The End?=¿El End? +Or the beginning?@nHint: Enter an end portal.=¿O el principio?@nSugerencia: Entra al portal del End +Stone Age=La edad de piedra +Mine a stone with new pickaxe.=Mina piedra con tu nuevo pico. +Ice Bucket Challenge=Mente fría +Obtain an obsidian block.=Consigue un bloque de obsidiana. +Hot Stuff=¡La cosa está que arde! +Put lava in a bucket.=Pon lava en un cubo. +Hero of the Village=Héroe de la aldea +Successfully defend a village from a raid=Defiende una aldea de una invasión +Voluntary Exile=Exilio voluntario +Kill a raid captain. Maybe consider staying away from the local villages for the time being...=Mata al capitán de una invasión. +Sería mejor alejarte de las aldeas por un tiempo... +Tactical Fishing=Pesca táctica +Catch a fish... without a fishing rod!=Atrapa a un pez... ¡sin una caña de pescar! diff --git a/mods/PLAYER/mcl_skins/locale/mcl_skins.es.tr b/mods/PLAYER/mcl_skins/locale/mcl_skins.es.tr new file mode 100644 index 000000000..840d1a520 --- /dev/null +++ b/mods/PLAYER/mcl_skins/locale/mcl_skins.es.tr @@ -0,0 +1,14 @@ +# textdomain: mcl_skins +Skins=Aspectos +Templates=Plantillas +Arm size=Tamaño de los brazos +Bases=Bases +Footwears=Calzado +Eyes=Ojos +Mouths=Bocas +Bottoms=Parte inferior +Tops=Parte superior +Hairs=Cabellos +Headwears=Accesorios para la cabeza +Open skin configuration screen.=Abrir pantalla de configuración de aspectos +Select=Seleccionar From ec5b0903be5eb5abce822a2c7b87eef918452228 Mon Sep 17 00:00:00 2001 From: MrRar Date: Tue, 4 Apr 2023 14:05:15 -0600 Subject: [PATCH 076/155] Make enchanted elytra usable --- mods/PLAYER/mcl_playerplus/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/PLAYER/mcl_playerplus/init.lua b/mods/PLAYER/mcl_playerplus/init.lua index 8ace0a9a9..782ac039e 100644 --- a/mods/PLAYER/mcl_playerplus/init.lua +++ b/mods/PLAYER/mcl_playerplus/init.lua @@ -239,7 +239,7 @@ minetest.register_globalstep(function(dtime) elytra.speed = 1 - (direction.y/2 + 0.5) end - elytra.active = player:get_inventory():get_stack("armor", 3):get_name() == "mcl_armor:elytra" + elytra.active = player:get_inventory():get_stack("armor", 3):get_name():find("mcl_armor:elytra") and not parent and (elytra.active or (is_just_jumped and player_velocity.y < -0)) and ((not minetest.registered_nodes[fly_node].walkable) or fly_node == "ignore") From 1a7f9fe8eccb69bda023de67a55897b73625d325 Mon Sep 17 00:00:00 2001 From: FlamingRCCars Date: Tue, 4 Apr 2023 14:06:41 -0600 Subject: [PATCH 077/155] Make elytra enchantable --- mods/ITEMS/mcl_armor/register.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_armor/register.lua b/mods/ITEMS/mcl_armor/register.lua index 89ff5ca9f..29a53003b 100644 --- a/mods/ITEMS/mcl_armor/register.lua +++ b/mods/ITEMS/mcl_armor/register.lua @@ -219,7 +219,7 @@ minetest.register_tool("mcl_armor:elytra", { _doc_items_longdesc = mcl_armor.longdesc, _doc_items_usagehelp = mcl_armor.usage, inventory_image = "mcl_armor_inv_elytra.png", - groups = {armor = 1, non_combat_armor = 1, armor_torso = 1, non_combat_torso = 1, mcl_armor_uses = 10}, + groups = {armor = 1, non_combat_armor = 1, armor_torso = 1, non_combat_torso = 1, mcl_armor_uses = 10, enchantability = 1}, sounds = { _mcl_armor_equip = "mcl_armor_equip_leather", _mcl_armor_unequip = "mcl_armor_unequip_leather", From b001e4e06f6de1c61d9a8a2f36a2f445fe330f33 Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Thu, 27 Apr 2023 13:16:15 -0600 Subject: [PATCH 078/155] Make elytra active checks use groups instead So that modders can easily add their own varients of elytra that work --- mods/ITEMS/mcl_armor/register.lua | 2 +- mods/PLAYER/mcl_playerplus/init.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_armor/register.lua b/mods/ITEMS/mcl_armor/register.lua index 29a53003b..c7fa91475 100644 --- a/mods/ITEMS/mcl_armor/register.lua +++ b/mods/ITEMS/mcl_armor/register.lua @@ -219,7 +219,7 @@ minetest.register_tool("mcl_armor:elytra", { _doc_items_longdesc = mcl_armor.longdesc, _doc_items_usagehelp = mcl_armor.usage, inventory_image = "mcl_armor_inv_elytra.png", - groups = {armor = 1, non_combat_armor = 1, armor_torso = 1, non_combat_torso = 1, mcl_armor_uses = 10, enchantability = 1}, + groups = {armor = 1, non_combat_armor = 1, armor_torso = 1, non_combat_torso = 1, mcl_armor_uses = 10, enchantability = 1, elytra = 1}, sounds = { _mcl_armor_equip = "mcl_armor_equip_leather", _mcl_armor_unequip = "mcl_armor_unequip_leather", diff --git a/mods/PLAYER/mcl_playerplus/init.lua b/mods/PLAYER/mcl_playerplus/init.lua index 782ac039e..1de839456 100644 --- a/mods/PLAYER/mcl_playerplus/init.lua +++ b/mods/PLAYER/mcl_playerplus/init.lua @@ -239,7 +239,7 @@ minetest.register_globalstep(function(dtime) elytra.speed = 1 - (direction.y/2 + 0.5) end - elytra.active = player:get_inventory():get_stack("armor", 3):get_name():find("mcl_armor:elytra") + elytra.active = minetest.get_item_group(player:get_inventory():get_stack("armor", 3):get_name(), "elytra") ~= 0 and not parent and (elytra.active or (is_just_jumped and player_velocity.y < -0)) and ((not minetest.registered_nodes[fly_node].walkable) or fly_node == "ignore") From 13df9ec46c64b77a8ae70a4cd0a2a659b6eadc9a Mon Sep 17 00:00:00 2001 From: cora Date: Thu, 27 Apr 2023 14:43:33 -0600 Subject: [PATCH 079/155] Fix crash when using a named spawn egg --- mods/ENTITIES/mcl_mobs/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_mobs/init.lua b/mods/ENTITIES/mcl_mobs/init.lua index c32fca820..bdc062470 100644 --- a/mods/ENTITIES/mcl_mobs/init.lua +++ b/mods/ENTITIES/mcl_mobs/init.lua @@ -556,7 +556,7 @@ function mcl_mobs.register_egg(mob, desc, background_color, overlay_color, addeg nametag = string.sub(nametag, 1, MAX_MOB_NAME_LENGTH) end ent.nametag = nametag - update_tag(ent) + ent:update_tag() end -- if not in creative then take item From 52e64a6f757bad4ff14126970657c9caec06f5dc Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Wed, 26 Apr 2023 15:24:35 +0100 Subject: [PATCH 080/155] Fix issue with drops turning black due to clipping into walls and floors --- mods/ENTITIES/mcl_item_entity/init.lua | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index 3103a1104..b9c56d6c7 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -621,13 +621,17 @@ minetest.register_entity(":__builtin:item", { if speed ~= nil then self.random_velocity = speed end local vel = self.object:get_velocity() + + -- There is perhaps a cleverer way of making this physical so it bounces off the wall like swords. + local max_vel = 6.5 -- Faster than this and it throws it into the wall / floor and turns black because of clipping. + if vel and vel.x == 0 and vel.z == 0 and self.random_velocity > 0 then local v = self.random_velocity - local x = math.random(5, 10) / 10 * v + local x = math.random(5, max_vel) / 10 * v if math.random(0, 10) < 5 then x = -x end - local z = math.random(5, 10) / 10 * v + local z = math.random(5, max_vel) / 10 * v if math.random(0, 10) < 5 then z = -z end - local y = math.random(2, 4) + local y = math.random(1, 2) self.object:set_velocity(vector.new(x, y, z)) end self.random_velocity = 0 From c48510244e7a3fc7ca76fcba744fe85db5b52e17 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Wed, 26 Apr 2023 20:36:23 +0100 Subject: [PATCH 081/155] Before merging same stacks, move to middle to show merging occurs. --- mods/ENTITIES/mcl_item_entity/init.lua | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index b9c56d6c7..ffecb80d5 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -808,11 +808,17 @@ minetest.register_entity(":__builtin:item", { if total_count > max_count then return false end - -- Merge the remote stack into this one - -- local pos = object:get_pos() - -- pos.y = pos.y + ((total_count - count) / max_count) * 0.15 - -- self.object:move_to(pos) + -- Merge the remote stack into this one + local self_pos = self.object:get_pos() + local pos = object:get_pos() + + --local y = pos.y + ((total_count - count) / max_count) * 0.15 + local x_diff = (self_pos.x - pos.x) / 2 + local z_diff = (self_pos.z - pos.z) / 2 + + local new_pos = vector.offset(pos, x_diff, 0, z_diff) + self.object:move_to(new_pos) self.age = 0 -- Handle as new entity own_stack:set_count(total_count) @@ -833,6 +839,7 @@ minetest.register_entity(":__builtin:item", { self.object:set_acceleration(vector.zero()) return end + self.age = self.age + dtime if self._collector_timer then self._collector_timer = self._collector_timer + dtime @@ -862,6 +869,9 @@ minetest.register_entity(":__builtin:item", { return end + + + if self.is_clock then self.object:set_properties({ textures = { "mcl_clock:clock_" .. (mcl_worlds.clock_works(p) and mcl_clock.old_time or mcl_clock.random_frame) } @@ -911,14 +921,13 @@ minetest.register_entity(":__builtin:item", { local is_on_floor = def and (def.walkable and not def.groups.slippery and v.y == 0) - if not minetest.registered_nodes[nn] - or is_floating or is_on_floor then + if not minetest.registered_nodes[nn] or is_floating or is_on_floor then + local own_stack = ItemStack(self.object:get_luaentity().itemstring) -- Merge with close entities of the same item for _, object in pairs(minetest.get_objects_inside_radius(p, 0.8)) do local obj = object:get_luaentity() - if obj and obj.name == "__builtin:item" - and obj.physical_state == false then + if obj and obj.name == "__builtin:item" and obj.physical_state == false then if self:try_merge_with(own_stack, object, obj) then return end From 938ee7a832c61a64611b997811034e2b4f060a35 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Wed, 26 Apr 2023 22:21:38 +0100 Subject: [PATCH 082/155] Pick highest y and kick it up a little for visual spice and to fix occassional drop falling into floor --- mods/ENTITIES/mcl_item_entity/init.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index ffecb80d5..149b5ed93 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -818,6 +818,8 @@ minetest.register_entity(":__builtin:item", { local z_diff = (self_pos.z - pos.z) / 2 local new_pos = vector.offset(pos, x_diff, 0, z_diff) + new_pos.y = math.max(self_pos.y, pos.y) + 0.1 + self.object:move_to(new_pos) self.age = 0 -- Handle as new entity From 1448a5e0986ae9e0c81eb21ac5a350f4d8fef03d Mon Sep 17 00:00:00 2001 From: SmokeyDope Date: Wed, 19 Apr 2023 02:27:38 +0000 Subject: [PATCH 083/155] Add new sweet berry textures --- textures/mcl_farming_sweet_berry.png | Bin 369 -> 302 bytes textures/mcl_farming_sweet_berry_bush_0.png | Bin 272 -> 174 bytes textures/mcl_farming_sweet_berry_bush_1.png | Bin 759 -> 282 bytes textures/mcl_farming_sweet_berry_bush_2.png | Bin 800 -> 326 bytes textures/mcl_farming_sweet_berry_bush_3.png | Bin 858 -> 261 bytes 5 files changed, 0 insertions(+), 0 deletions(-) diff --git a/textures/mcl_farming_sweet_berry.png b/textures/mcl_farming_sweet_berry.png index bb6a3bdeff19a6d6bdbfb1cc543dc7e9285ea576..f6a4c1db60f12cac0a9d87c38f16fe62d53e53d6 100644 GIT binary patch delta 275 zcmey!w2o$PG)>>Kz{FZh&Bw+#$l1D8LSlxF&LVB?`;+=Q zCKieSP2njC@(X5QWMXDvW9Q`N6BO&Ks=Esm@Aq_Z43UszJ=mUj*no$@AYh}Y<C+_qABp#mP69Pu!b(;>}5` z>N5EcF~#dn7H<^%crVp2d#^d`s^YoXK0g%aWWTyOe|09`?EnOg{qer=p*Xg}a264eI~Y7& L{an^LB{Ts5+XID| diff --git a/textures/mcl_farming_sweet_berry_bush_0.png b/textures/mcl_farming_sweet_berry_bush_0.png index d8eb23d9dc9e830b0ca46f103c33ac728bdb5bf2..2d9a7eed8d258701e61c39131a3df906fe85cbdd 100644 GIT binary patch delta 158 zcmbQhw2pCtL_G^L0|Ud`yN`l^6n}tEh%1m*a#PUoQ#MW0w=6JOmlbIO6k;q1@(X5g zcy=QV$no`baSY**oqCX)_kaSA!@=upjIk>j64=B_m>K$96fUHx3v IIVCg!00itba{vGU delta 256 zcmZ3-IDu(`L_G&H0|SGGE`KnPVo7)Ob!1@J*w6hZkrl}2EbxddW?P?+ntjkMwB62h9ORjAykkdSBAl#m%*Qp zAzbLyyZb3Xy}~6ye!&dk6DCw{+jbrZ?%%)v>f^_szkjnQX*~nVGbVYvyDNrGH;Ak%V7~ijMz6(*J9o?$7^Qay>%Cr(=lx7c qF!1o6m9y5X_C8x!w<%cS2BX6}MzN))r}BV?F?hQAxvXqJ7g_TxX;tYF@!^w^`I>uqoYK_!*Z3n zq$dAF>9b{e3kAg&gj<{v<8yc~z}5O>_Svo%X({{$Lg4~$eI8a?oXpwPCYQs?*v!b_ zp!Tg%uxnqlqd7pb-I4FyHw&ywD^L@_wJ%J~!#km`9Z>3$k7~>n8N1vM-{seVP>&e;D z;0cEVWbvM@+7-vGIj!D=D^Ios-KZ@?W5V5L;MB zoayV1_92tX`HWOBZ|`Krom$EGP}NX&53k}OdKf|t^|Xc25VM%Gy8p4+kw@~`vT{DB zmkc7K9S;}@LrkKAW8@H}(7`T-<+Dv2)vG93J2+2}c7JKODUh{sG;gE&qP2rJF^Dv> zDWq@?Ewdv(DTEEbKOR%g#|pXF%FamteFBHgA+^?2A5g(xnLg>%Brz6MjYa2FT9Hzi zD1?bdC#Rf0Hk94gjW^N4$SI(WU#;wXs@Zwo)5S-oiycHNt(5X$TcT|=s$v^IqKXK) z)0=C;%zu{>?4K0f-OZCUmBOY{^w?)Khgd#%CCp-$fREL^5nO81M~fzw!L~@C*HJm_=-+k5@tU1 z(uJ?lOaBYFIrE$CT2Z6-j8^ZmLT;;{yo!AGo@B#jS}t?j)${M0EUci5Bseof`fZG3 z+JmDTQb8n68WLU8!{52H^R7;}?%Kr<`iV?}|Cz)RF8HHzUAucEPI{gz-$LE;=3C+< d@qOnO{0&Ay?kS3SOp5>j002ovPDHLkV1i9qXrTZA diff --git a/textures/mcl_farming_sweet_berry_bush_2.png b/textures/mcl_farming_sweet_berry_bush_2.png index 5e9a6dd1473581ec441c431004954550cc7968f9..e452fe42bfbff8512674dfdf8c0751ce730c8707 100644 GIT binary patch delta 300 zcmV+{0n`4V2F3!ABYy!6Nkl@|+Izklr#33if_$h~Q+6VZg6 z%^)Bt>$oP6Bo#W5LAeBQ2dVDagW4qts7A?MMW208qf`k!P#`BqT(?p{fJ&z#`o!7^ zwwVAb)NP#zQu?HdU?hOE6AS>9hAN=+A$gEk{sd{KX$me?dH>ibkcKFL6ZH*%6lycp y{7LdJD4_fVekBH9E){fizV^#V${yai2jK_9f0bF?j6nT=i=LGIIlf!4sEXEukh;Y%u#zzL*-bcyQTx0)gaG&D<3A|-- zbIev{Sf$=)?BFZ7fx4-=+TME1WluNAO1>8m*Ic%a7Hl5q>;Mi~5Z-Aamo00CC zgSm!4)>gIeVxcsFmzri79L3=fRop?_*rV}3MjwmaL4RIht(PF?P}`0`;>uY`IsyLz(a zFV>>;FMqS;V|uffQA8TaJ?BlS_@^37E$wv7e7l;bu_K?_kx$>#k-puzSr5WUh^x4X z1(bq)=}Y4AAHG?g$wXm%bR=F>uBJ59RBD0k-K0$NhA8^kQ+@AY3%mbD`DE&>c=)1c zANUF{W8}+1>FBGEWUg5$WiMUd89tdTl~tp>RDb+k&-8zeda$npp&xIZ(~%jHO&rso zTWx-O7t0nlx>V{b9?qY~YV(m%@Sh?j(T&4yZk!PYX;Gv6^-}%$@#pgIm|cETwN`R` z;O%Cq8o~cGF^_(~ub;A8+YmMCp6I!NlIexhqDI4a)eG=9Lq-7@2qxvS00000NkvXX It^-0~f}QYt82|tP diff --git a/textures/mcl_farming_sweet_berry_bush_3.png b/textures/mcl_farming_sweet_berry_bush_3.png index a473882f4dbfc1076b0e794db9c0cd80db295492..0748e09c89a7c5ef8719cf0dc71fe621e3e3bb3a 100644 GIT binary patch literal 261 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!O@L2`E06|)|9F9tn}UX)vT2&W zRikk~JNs@<&PS6cKj-G&JpaZNpk~IBAirP+hi5m^fShtq7sn6@N!^2;f=mViM>gml zD17&Fe>hX~6d(0tHqQ!AXBPf4ntSB&wX3>!yo#2)uJ5QkCnnB!`B@;#l(oilTdaFy zKITkp(Y<(j%M(F8j_4=ceOz2WXSHej&3|bV&9UidSlu#9j%WGY`W2s)I}Us~`B>EE b(KL1WZ<5^1yR$wugM8!Z>gTe~DWM4fsQ+)f delta 846 zcmV-U1F`&t0@?PbXFR5;6RlS^n53lxUGnPet0@usb& zj}WI8NsGltTNJt07u=14bfMW48m*T4T!?QsDzpXh!3FQ#sDI$X5(GgIufpA`;Hy4C zidv1DHm#xB+BQjNGRb7dMW?>-tk3xl=Rf~1@Vh!5YUX~zL8D>8Wg6nNw*^^Q`ET9%#7iukB+^R`CG~J!ueK`ErkqpTn(GA6 zfw_PSNN_w91I%f_EI{e|tK@R0Pw*oO3+tb1e*zFswL~`fU*Vr|6KDVmz)TL5M1|Kuna9_%OBrfeU!)`8C6f;TjSs7jo_~o(2T$3j)c{o@kOziCPt&a# z-4uvVG@N}f8lvw@MbDa(uITLv4+0YL)WX-tb~r`V^4I_eAUOdM@UIM)9RV7;dPdh< zBUy?0e&cn=E(f`9-x9VgmQ@UM(gutHNzo>WKz@Hhtqdk}?tM+cNkC}btmIl(dkY=0 zNe@0*XMc|G19N;&m=d%YD2PA~=;cW=QhjHn(b5Wz9mD#RKgM+NVz1^X(_nWFEBgOv zEfwB}zy#n1Gu0a3R^;04eR3;?R| zgZpG)5zmLC6uI5q;lE4Gz1uunmw7VVKj)-XuYU~Jre$&;rumE|fdfDW$cX@S#w_k7 z!t@O7q@nyE^NRix_iuMeCMLDB@2-Ah$byK8o|jPb>v;5Wt*wLM{FZ?g$`yKsoV*=d zidPEcik;&Q-Etr7SLH~%(#1f^k6!phb;%`Q1TX Date: Thu, 4 May 2023 21:48:07 +0000 Subject: [PATCH 084/155] add barrel sounds (#3670) This PR Adds sounds to opening and closing barrels. The sounds are properly attributed in the 'attribution.txt' file. They are published under Creative Commons 0 (CC0) and the source for them is [here](https://freesound.org/people/quantumriver/sounds/552153/) Reviewed-on: https://git.minetest.land/MineClone2/MineClone2/pulls/3670 Reviewed-by: ancientmarinerdev Co-authored-by: SmokeyDope Co-committed-by: SmokeyDope --- mods/ITEMS/mcl_barrels/init.lua | 2 ++ mods/ITEMS/mcl_barrels/sounds/attribution.txt | 2 ++ .../sounds/mcl_barrels_default_barrel_close.ogg | Bin 0 -> 25644 bytes .../sounds/mcl_barrels_default_barrel_open.ogg | Bin 0 -> 26648 bytes 4 files changed, 4 insertions(+) create mode 100644 mods/ITEMS/mcl_barrels/sounds/attribution.txt create mode 100644 mods/ITEMS/mcl_barrels/sounds/mcl_barrels_default_barrel_close.ogg create mode 100644 mods/ITEMS/mcl_barrels/sounds/mcl_barrels_default_barrel_open.ogg diff --git a/mods/ITEMS/mcl_barrels/init.lua b/mods/ITEMS/mcl_barrels/init.lua index 09b16eee3..3cde964d7 100644 --- a/mods/ITEMS/mcl_barrels/init.lua +++ b/mods/ITEMS/mcl_barrels/init.lua @@ -63,6 +63,7 @@ local function barrel_open(pos, node, clicker) minetest.swap_node(pos, { name = "mcl_barrels:barrel_open", param2 = node.param2 }) open_barrels[playername] = pos + minetest.sound_play({name="mcl_barrels_default_barrel_open", pos=node_pos, gain=0.5, max_hear_distance=16}, true) end local function close_forms(pos) @@ -80,6 +81,7 @@ local function update_after_close(pos) if not node then return end if node.name == "mcl_barrels:barrel_open" then minetest.swap_node(pos, {name = "mcl_barrels:barrel_closed", param2 = node.param2}) + minetest.sound_play({name="mcl_barrels_default_barrel_close", pos=node_pos, gain=0.5, max_hear_distance=16}, true) end end diff --git a/mods/ITEMS/mcl_barrels/sounds/attribution.txt b/mods/ITEMS/mcl_barrels/sounds/attribution.txt new file mode 100644 index 000000000..38743d3ef --- /dev/null +++ b/mods/ITEMS/mcl_barrels/sounds/attribution.txt @@ -0,0 +1,2 @@ +barrel-open.ogg and barrel-close.ogg taken from https://freesound.org/people/quantumriver/sounds/552153/ +Licence: Creative Commons 0 (CC0) diff --git a/mods/ITEMS/mcl_barrels/sounds/mcl_barrels_default_barrel_close.ogg b/mods/ITEMS/mcl_barrels/sounds/mcl_barrels_default_barrel_close.ogg new file mode 100644 index 0000000000000000000000000000000000000000..ccbb18c0ff6edebe4472574505cecf9b02201118 GIT binary patch literal 25644 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%0AjsbUrA-R{M@XrU>o}~jBVh@S4nM? z7vBrH)AATog(3S`HCAn_v)olbWLTW7+DAet*L$01+eNATdPa9@@NTgu3b0O(ld(RU zCujGEWbEyP3*LPm<#RLK~n_-5(o*4W;__1M!`5a-CVk~^!i>y9uXzC|w^wjgf?GEhy1Yph z@n%`|gL*f-95g5O!a`GlSa+z`^VIX^#lD@HcnpNyJlnJM)$UU-oN~=0Cf5R0wXWb2|9$CXBIijXWQY!xft!z-Mvb6^nj&KIK!T|VC+DC9#nwP zpIDrH3|&aQD5$R!4T&7~nL>~~fQr6Az)BKH4oFF01DF*k;K8O=d^LPcNyHMz_T;mu!kQ;Y|*+9+c3%+WAIH#Gk`w%Us;q_!`{~tqz{73z?2fT;rH$~3tor4&HSjet$||<=wbwSpI^+2sSQIB=pc}HQW}Pl~ z_}=MX6|$o}p?P-j-q6#j`Q%%O)A#-~)lzF=HHHk@Rd1e67q97raSuZRr%WWGb`CE| z=_9}I@Wsf*@JNs`m+@NbQ)i5B#HuVj{%|;hOrG19D-2hr(wN9Nb0)$#==*yqh+?PTnE$aCLQhUHlhw`?y(fXs{7BOj#)i$0**ZP0Tz)ZKH|dp; zl0!q9SXb*ij?ovtqe{H9jGbIZKDc9I4B=UiLeD1I6FEOy5?$1hkj-_DcpJ66*me;w+ST5G*eNL? zW@y~|<+dLTeZNGnbusO^>k`UMF57fcj_#Lu!j-T&z!z+oYHb_a$mc+tmC7KWr5oRu ztPesBA@5Uk7^#9*Iyx*Sd2tY)noVgaLHE{YA4V4xb@9!zw`n>u4!)+tb&Vwqdk}5; z{!Favxxj_pO=uuR_`ZKRgQQQ(=RFXR|7y9-xp6Nmu_H~87A)erI0Gkm?+r1tc!tW( zuD!fAoEUhbiJO146l;Kf*yGBx^5L4V>Va*_aR!3U?jH=20qx<{{R(hO`gU}wkzW>L zWST^N2~YPjGUf?-tD&e#=@}muJ&Vp|RCADk-|*e3eDy}=*yy_Ma4%QCuszP{9d4`y z#HQE_1N4nt){dLKTB%zw&(HpqsF)-a{)ip-eHLQ$0*{JDvW5XmEYrEYtFG?d={DJ? z)1bpmd*0}f5$KVGJiAeH-vsHk%558fz#U@;uVkoWLs1r(D$gd51;LGZ)+qp}rv*FE zMA*2bsAV}+&52W8h8*EJS`gOU4Swr765?p%W(i~Z-SP_!V9vo?VGzXcLJ-5w=E7Gu zLXz$dJJ9@DmH0k`L6X{GVL!qe)0ZFroJp46`v$v`&!_g}l}^)}`{hwMHy&en-#cCM z2DE2a_VafDC-XHN04ftJ7?5N{L0H--Pr*5rlmAk;b-g-g4V8F^?-pqDDeAyax;^mm zb?U#nFRMI1s)R=p_Un5YfB36t!;_!D>hgtm%-w83)@ze%4N`J-(3(V#8Szh6<{2d6 z^Jhv%I`I>&Kv^il6^(zUF0t`dYvaL&(-rLtqxIX<-YGIN5fM-AfwrlvuY+#U_j*uh zNlRXK$L7Jart{;&Wem4d%D(9+wgqA8JL<*4c)J-A-jI=HJTWduB4w57P(CE{zS!_r zvStMyvnlMLcJ!;gVM3KaEc)qjg>v14x9T=6ZAc}~8xpGIalMT?!98X-cJPX^me3lO z-d*Z!$g1lhS!spL&P2=0Wl{=SRrry+YCjO^*B2NaDrY>sbCkpvWF4#2iH*M)qP-Lp z6g%Q?3l+b<3p0=Mt!TZx{*3E;om7hqFW&iZUB4gK2BJTe2xh?i{iXleWPATWZg6c; z$_Q7*_V#ZhyoHv$+jSSUgTcLtvqc6Yb!Aj(jE>b|%%in{K$W^*MiaLkipI$`_p84b z7?aO$R!$$(kTc(h_mK4<h&3~{-)*0AtKP&9^B!ltd1p05T}YJB|`S|YM=C2@;nAm z?JbbQQH~8sX=%v z0ryJsSPVY9+9Tq3rI9+8n7}O7ib@1f1IHnR)47H&`05w#eOHbjTYtH0Zp%%7q~QG( z`iMBD`W%{<>Z*vD9~4}3yRSc_NB7U2h`j$gTtI|nBS29`&!yk!Kue&pu+L7yVOJyE zVHYC8pb5}eMzQ`UM3nI@IuR6TQZ*WcT7LdtTxbwvfQE#Zj3pW?%_6f|UQuVec41-L zJl6p!%WKQ&iG)5b1Ky5uGmU27VPDJOxqd)~14tBN2m$tmz1u=o0<>3J&&)1C+#&eh z6sUtimT9P{iY*iR%n7ddr>CbO4;;7aTfhCK>e^i%m}M_msC{i~)hfz-G=z!^d~}zt zZc#-2`nwpn#y>nqXE;wGr$T7nG@EWXQqZr`+0`#@YlPoIyJF?{o@$qDs_9fo$SWHOy=rmdj4hjh~oDBdmi=h{)5>Ps{5sF!{m zml4O?T6Dbo(9ISf9}*|OyUVI;lzN*D{D$@RM3Sa*f##}1-=Aqisiq>QtwI2Lr<%FK z^>zf$mndmk4|dwDQNnRlbcfh7fHx0x3s?ETv?ovoGU)p~3ZJwab!w%i$+thqFP}Ml z(17f39o%%))caOopLz9e3|*X^OM<-USdtaX02?KD*XjCTvjc2k1Yz9b0^UBy5#gLc zSvG^;vWI=<>WFZ0yqTmL#Bo@UOb7JVCcGvF!oRfkNwoURK(UE?{r4#$4~KAlGAIIY z5OTO9Knal73v;o=P=$1*8dKL?vBd+O$71ykhE&E=-uK0+rLNrH;YI<*SWcCe`vl6a zy60v3_D6Z@MH6p?g`ZjVTb3pJ925}N8=3E3+w^}^%osAq6sAS){pO~9=fU_}m73Dh zF%)mYl~$fXKxAVuBuarWUyABNcgcicv}5$v*@xRBN2ZzAw@5~0Q?BEN{4#LkF8$M> zkyEA5&UWq4rm)1E&$` zBFVbGOP9_Qehq@{h(77bE3rPu4f6@-;2E#cte{d)gid7>x8YeepH*WfB3IDT=+MPZ zl`z?1$RhI%ec$|Eks)1au--G1iG!9|{IYi2Jw;>`)`yyh6X(X)F%=zI5(mIYaC&%7 z=S;S90Kv)`(2D|nXb15DC)8sKy`^kvEf}5a9ra93zAO72A$~VidXPZkjyJ`z*jFa!9fbzvbbg_W<8e(VGi zQ~KsM#!!L8=l3x>Vr0RWcuPY(6hyWH`Ma?Y<01NE%;JfJc*4Q*h{eWkEpx$n+c{n= zzgp)A@?D$qx4Pr&$#S#rX^tH=hh3L^Xwu_d)>b{0raDNBqGF?Ih8eN5aEEj7nYq(Q zNS;Qequ1ICx{v*=$~@iO6L^Vs!|t^3u$oCuNzU$2xm^f}8T^G}6&d?`wha!8q_q|P$n{2wpA;k`F z_}`5gs4_79r=Fi}L+oc~)A@zQpY9%rb1AwZ!=)-U!gEoA( z1_Kztc19RkFpn_82Xadwe*ugP^bHo4H7%))4VCBmi>VC^lZYPx=x>J!jyAwNzy{K7 z(*=EF%H9+ek^u-Tuy8J5cOdP1z#wG!2m*eIY~#}89fAZbE0Mj=C50jq$jgh-ZgF0H zlMLVb#%Qh4h|yMzNq`V<%?;6zgASJl^+h! z{=J8srPs%yeupQGb(g`>Ls`hM!j){-@#0sG2VB zOnv=zCIQG@`|QlA@9Bmrb`Jdq+<+1+za`NK@EP;5L_qB(>ZuzUdmfH2Tl zx4g>6z_HH%em)dBN6;+*P?~(F#yP}-#-!n0OTi$EPd)j^1XA% z;ZLXleu?aD4if^vG7~wCQ}T`guzYoqN1~uexJZNMUeu1ThDFeAM2Q)|=egVDte%Xu zjOVQrTeG~$jr-EC<8bh$20PYcW;E8x!Xb-E-1gk^1s~2=BR6+fmh)A4Eu^b!ee3`3 z@8SGJER1Q7EGfh1%%|X}jO2&ahkC<=1AO`(o+5kyFgo2i_SS4)ePA{>{de`_Z0;Y4 z$n7T~hadYKzPbOJpLuCdd!M8#>&uNuDt{)~WIasl)bBrj8j@|?O@H?V2-%|Pgc|m~ zl|_Rxhy9s1E92~uY9{7+rrKJ}&KU*GL_dBrd&&j(%t=j?yJn}~D)^a%n(l+xSwl?f zCh6?Aw(WZt3(s)E;S7-TP(8h)OeQ)eNaG!)1HDI^Zy7~EI1XqDTW{{DOzsLxzs6eUYgU-C$fCpfFDSi7> z1Ug?}k+F?2^F*-$00&Fb5?ceqx2{OuC!U$?(-JxafaT?~PHQ*>63Dz#P*y})LhNI! z4~sU`+Nd@hBc=&}TDGY^V*^QY=+CTP&$JkZ(8FVpsQN?KROZ}v$%Is1|R)hlE+Wz0nTSQ zNmF}VGE>C>|A*#tLsi|UKh=@2$Ip<=zt2U%vI7IBilBxo&=URJA4k=U6T+oRao~F`L8F_q%Q@%f{#f1%*j}^ye;Ka+;{9y_Ozx`fWF`OYeut_<4toGv-RbUmr}zHZ z#Z=DFK({K{GyUX1gD@cP_W*CSD^@T7LgR*62Uyzs@Tx6}h7x8)+G5cP707-tDg-1C z=Eq~}s3AQ5u00E%hh^%Q0g&+dUM`WvGmULu6${p5aik4Y3MBOglVx}E5=HOgv8D4JNsyNUOnlDc;H2p=z&R^%AFHK;2}MM|L31h~rtykUM)C^7c2)4KUtQFLX~F!TwK$=hJ@Q°GyA@sOr^kiocIR%| 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 ZNu=C-eAEB{U~K}tKMMdcuvWf=F90Iuy9NLN literal 0 HcmV?d00001 diff --git a/mods/ITEMS/mcl_barrels/sounds/mcl_barrels_default_barrel_open.ogg b/mods/ITEMS/mcl_barrels/sounds/mcl_barrels_default_barrel_open.ogg new file mode 100644 index 0000000000000000000000000000000000000000..c2c9f1d35d85addb447e3f5676464553aa167e01 GIT binary patch literal 26648 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 Date: Mon, 24 Apr 2023 11:35:56 +0700 Subject: [PATCH 085/155] Clean-up mcl_bamboo code make it less dramatic ('Bamboo Door.') and fix inventory_image inconsistency with trapdoors --- mods/ITEMS/mcl_bamboo/bamboo_items.lua | 8 ++++---- mods/ITEMS/mcl_bamboo/locale/template.txt | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mods/ITEMS/mcl_bamboo/bamboo_items.lua b/mods/ITEMS/mcl_bamboo/bamboo_items.lua index 70a7bf35b..6ec63db31 100644 --- a/mods/ITEMS/mcl_bamboo/bamboo_items.lua +++ b/mods/ITEMS/mcl_bamboo/bamboo_items.lua @@ -62,7 +62,7 @@ if minetest.get_modpath("mcl_doors") then local name = "mcl_bamboo:bamboo_door" local def = { - description = S("Bamboo Door."), + description = S("Bamboo Door"), inventory_image = "mcl_bamboo_door_wield.png", wield_image = "mcl_bamboo_door_wield.png", groups = { handy = 1, axey = 1, material_wood = 1, flammable = -1 }, @@ -77,15 +77,15 @@ if minetest.get_modpath("mcl_doors") then name = "mcl_bamboo:bamboo_trapdoor" local trap_def = { - description = S("Bamboo Trapdoor."), - inventory_image = "mcl_bamboo_door_complete.png", + description = S("Bamboo Trapdoor"), + --inventory_image = "mcl_bamboo_door_complete.png", groups = {}, tile_front = "mcl_bamboo_trapdoor_side.png", tile_side = "mcl_bamboo_trapdoor_side.png", _doc_items_longdesc = S("Wooden trapdoors are horizontal barriers which can be opened and closed by hand or a redstone signal. They occupy the upper or lower part of a block, depending on how they have been placed. When open, they can be climbed like a ladder."), _doc_items_usagehelp = S("To open or close the trapdoor, rightclick it or send a redstone signal to it."), wield_image = "mcl_bamboo_trapdoor_side.png", - inventory_image = "mcl_bamboo_trapdoor_side.png", + --inventory_image = "mcl_bamboo_trapdoor_side.png", groups = { handy = 1, axey = 1, mesecon_effector_on = 1, material_wood = 1, flammable = -1 }, _mcl_hardness = 3, _mcl_blast_resistance = 3, diff --git a/mods/ITEMS/mcl_bamboo/locale/template.txt b/mods/ITEMS/mcl_bamboo/locale/template.txt index e099419d7..ad8e7cb5b 100644 --- a/mods/ITEMS/mcl_bamboo/locale/template.txt +++ b/mods/ITEMS/mcl_bamboo/locale/template.txt @@ -14,7 +14,7 @@ A wooden pressure plate is a redstone component which supplies its surrounding b Bamboo= Bamboo Button= -Bamboo Door.= +Bamboo Door= Bamboo Fence= Bamboo Fence Gate= Bamboo Mosaic Slab= @@ -24,7 +24,7 @@ Bamboo Plank Stair= Bamboo Pressure Plate= Bamboo Slab= Bamboo Stair= -Bamboo Trapdoor.= +Bamboo Trapdoor= Double Bamboo Mosaic Slab= Double Bamboo Plank Slab= Double Bamboo Slab= From 387b79e582555be87719df2011661e6dd8aeacb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikita=20Wi=C5=9Bniewski?= Date: Fri, 5 May 2023 07:40:02 +0700 Subject: [PATCH 086/155] Remove useless comments --- mods/ITEMS/mcl_bamboo/bamboo_items.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/mods/ITEMS/mcl_bamboo/bamboo_items.lua b/mods/ITEMS/mcl_bamboo/bamboo_items.lua index 6ec63db31..2f3b463a8 100644 --- a/mods/ITEMS/mcl_bamboo/bamboo_items.lua +++ b/mods/ITEMS/mcl_bamboo/bamboo_items.lua @@ -78,14 +78,12 @@ if minetest.get_modpath("mcl_doors") then name = "mcl_bamboo:bamboo_trapdoor" local trap_def = { description = S("Bamboo Trapdoor"), - --inventory_image = "mcl_bamboo_door_complete.png", groups = {}, tile_front = "mcl_bamboo_trapdoor_side.png", tile_side = "mcl_bamboo_trapdoor_side.png", _doc_items_longdesc = S("Wooden trapdoors are horizontal barriers which can be opened and closed by hand or a redstone signal. They occupy the upper or lower part of a block, depending on how they have been placed. When open, they can be climbed like a ladder."), _doc_items_usagehelp = S("To open or close the trapdoor, rightclick it or send a redstone signal to it."), wield_image = "mcl_bamboo_trapdoor_side.png", - --inventory_image = "mcl_bamboo_trapdoor_side.png", groups = { handy = 1, axey = 1, mesecon_effector_on = 1, material_wood = 1, flammable = -1 }, _mcl_hardness = 3, _mcl_blast_resistance = 3, From fb9a630a5bf33fbfe26b6c171ff551c72fa051e1 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Wed, 3 May 2023 17:37:53 +0100 Subject: [PATCH 087/155] Hostile mobs should lose aggro if they cannot see their target --- mods/ENTITIES/mcl_mobs/combat.lua | 75 +++++++++++++++++-------------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/combat.lua b/mods/ENTITIES/mcl_mobs/combat.lua index 5fa95db1b..872a85d46 100644 --- a/mods/ENTITIES/mcl_mobs/combat.lua +++ b/mods/ENTITIES/mcl_mobs/combat.lua @@ -10,6 +10,8 @@ local stuck_path_timeout = 10 -- how long will mob follow path before giving up local enable_pathfinding = true +local TIME_TO_FORGET_TARGET = 15 + local atann = math.atan local function atan(x) if not x or x ~= x then @@ -398,7 +400,8 @@ function mob_class:monster_attack() end -- choose closest player to attack - if dist < min_dist and not attacked_p and self:line_of_sight( sp, p, 2) == true then + local line_of_sight = self:line_of_sight( sp, p, 2) == true + if dist < min_dist and not attacked_p and line_of_sight then min_dist = dist min_player = player end @@ -810,6 +813,22 @@ function mob_class:check_aggro(dtime) self._check_aggro_timer = self._check_aggro_timer + dtime end + + +local function clear_aggro(self) + self.state = "stand" + self:set_velocity( 0) + self:set_animation( "stand") + + self.attack = nil + self._aggro = nil + + self.v_start = false + self.timer = 0 + self.blinktimer = 0 + self.path.way = nil +end + function mob_class:do_states_attack (dtime) local yaw = self.object:get_yaw() or 0 @@ -823,35 +842,33 @@ function mob_class:do_states_attack (dtime) or self.attack:get_hp() <= 0 or (self.attack:is_player() and mcl_mobs.invis[ self.attack:get_player_name() ]) then - self.state = "stand" - self:set_velocity( 0) - self:set_animation( "stand") - - self.attack = nil - self._aggro = nil - - self.v_start = false - self.timer = 0 - self.blinktimer = 0 - self.path.way = nil - + clear_aggro(self) return end + local target_line_of_sight = self:line_of_sight(s, p, 2) + if not target_line_of_sight then + if self.target_time_lost then + local time_since_seen = os.time() - self.target_time_lost + if time_since_seen > TIME_TO_FORGET_TARGET then + self.target_time_lost = nil + clear_aggro(self) + return + end + else + self.target_time_lost = os.time() + end + else + self.target_time_lost = nil + end + -- calculate distance from mob and enemy local dist = vector.distance(p, s) if self.attack_type == "explode" then - - local vec = { - x = p.x - s.x, - z = p.z - s.z - } - + local vec = { x = p.x - s.x, z = p.z - s.z } yaw = (atan(vec.z / vec.x) +math.pi/ 2) - self.rotate - if p.x > s.x then yaw = yaw +math.pi end - yaw = self:set_yaw( yaw, 0, dtime) local node_break_radius = self.explosion_radius or 1 @@ -859,20 +876,15 @@ function mob_class:do_states_attack (dtime) or (node_break_radius * 2) -- start timer when in reach and line of sight - if not self.v_start - and dist <= self.reach - and self:line_of_sight( s, p, 2) then - + if not self.v_start and dist <= self.reach and target_line_of_sight then self.v_start = true self.timer = 0 self.blinktimer = 0 self:mob_sound("fuse", nil, false) -- stop timer if out of reach or direct line of sight - elseif self.allow_fuse_reset - and self.v_start - and (dist >= self.explosiontimer_reset_radius - or not self:line_of_sight( s, p, 2)) then + elseif self.allow_fuse_reset and self.v_start + and (dist >= self.explosiontimer_reset_radius or not target_line_of_sight) then self.v_start = false self.timer = 0 self.blinktimer = 0 @@ -894,25 +906,20 @@ function mob_class:do_states_attack (dtime) end if self.v_start then - self.timer = self.timer + dtime self.blinktimer = (self.blinktimer or 0) + dtime if self.blinktimer > 0.2 then - self.blinktimer = 0 - if self.blinkstatus then self:remove_texture_mod("^[brighten") else self:add_texture_mod("^[brighten") end - self.blinkstatus = not self.blinkstatus end if self.timer > self.explosion_timer then - local pos = self.object:get_pos() if mobs_griefing and not minetest.is_protected(pos, "") then From be8d9122eee93e23b3bdb9df27fc126126362bde Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Sun, 7 May 2023 21:11:48 +0100 Subject: [PATCH 088/155] Fix crash when creeper explodes in minecart --- mods/ENTITIES/mcl_burning/api.lua | 7 ++++++- mods/ENTITIES/mcl_minecarts/init.lua | 9 +++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/mods/ENTITIES/mcl_burning/api.lua b/mods/ENTITIES/mcl_burning/api.lua index cba73b846..74c66d5f1 100644 --- a/mods/ENTITIES/mcl_burning/api.lua +++ b/mods/ENTITIES/mcl_burning/api.lua @@ -5,7 +5,12 @@ function mcl_burning.get_storage(obj) end function mcl_burning.is_burning(obj) - return mcl_burning.get_storage(obj).burn_time + local storage = mcl_burning.get_storage(obj) + if storage then + return mcl_burning.get_storage(obj).burn_time + else + return false + end end function mcl_burning.is_affected_by_rain(obj) diff --git a/mods/ENTITIES/mcl_minecarts/init.lua b/mods/ENTITIES/mcl_minecarts/init.lua index 92136c37f..2d0cd78e9 100644 --- a/mods/ENTITIES/mcl_minecarts/init.lua +++ b/mods/ENTITIES/mcl_minecarts/init.lua @@ -370,13 +370,10 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o end end end - -- Make room in the minecart after the mob dies elseif self._passenger then - if math.random(1,20) == 1 then - local dead = self._passenger:check_for_death() - if dead == true then - self._passenger = nil - end + local passenger_pos = self._passenger.object:get_pos() + if not passenger_pos then + self._passenger = nil end end From 8b45cb267269767af6c5afdafebcde95a97070b9 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Tue, 9 May 2023 14:56:51 +0100 Subject: [PATCH 089/155] Remove slimes from mushroom islands --- mods/ENTITIES/mobs_mc/slime+magma_cube.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/mods/ENTITIES/mobs_mc/slime+magma_cube.lua b/mods/ENTITIES/mobs_mc/slime+magma_cube.lua index 71a45b5ab..c07afb6b1 100644 --- a/mods/ENTITIES/mobs_mc/slime+magma_cube.lua +++ b/mods/ENTITIES/mobs_mc/slime+magma_cube.lua @@ -269,7 +269,6 @@ local cave_biomes = { "RoofedForest_underground", "Jungle_underground", "Swampland_underground", - "MushroomIsland_underground", "BirchForest_underground", "Plains_underground", "MesaPlateauF_underground", From 6f75932a4b91599c0ff71ec519c9b072e00fba51 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Sat, 6 May 2023 23:56:34 +0100 Subject: [PATCH 090/155] Fix crash when parrot sits on shoulder --- mods/ENTITIES/mcl_mobs/effects.lua | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/effects.lua b/mods/ENTITIES/mcl_mobs/effects.lua index 699993979..4a4452f7f 100644 --- a/mods/ENTITIES/mcl_mobs/effects.lua +++ b/mods/ENTITIES/mcl_mobs/effects.lua @@ -348,7 +348,7 @@ function mob_class:check_head_swivel(dtime) who_are_you_looking_at (self) - local final_rotation = vector.new(0,0,0) + local final_rotation = vector.zero() local oldp,oldr = self.object:get_bone_position(self.head_swivel) if self._locked_object and (self._locked_object:is_player() or self._locked_object:get_luaentity()) and self._locked_object:get_hp() > 0 then @@ -360,8 +360,11 @@ function mob_class:check_head_swivel(dtime) _locked_object_eye_height = self._locked_object:get_properties().eye_height end if _locked_object_eye_height then + local self_rot = self.object:get_rotation() - if self.object:get_attach() then + -- If a mob is attached, should we really be messing with what they are looking at? + -- Should this be excluded? + if self.object:get_attach() and self.object:get_attach():get_rotation() then self_rot = self.object:get_attach():get_rotation() end From ea4ea3f05e82f17c8b388a8cb4df900d2a226406 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Thu, 4 May 2023 21:14:16 +0100 Subject: [PATCH 091/155] Standardise despawn logic and add asserts. Add persistent flag for mobs that have been interacted with. --- mods/ENTITIES/mcl_mobs/api.lua | 6 ++-- mods/ENTITIES/mcl_mobs/breeding.lua | 1 + mods/ENTITIES/mcl_mobs/spawning.lua | 38 ++++++++++++++++++++--- mods/ENTITIES/mobs_mc/enderman.lua | 17 +++++----- mods/ENTITIES/mobs_mc/villager_zombie.lua | 2 +- 5 files changed, 45 insertions(+), 19 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 39d2f45a9..622366fea 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -78,11 +78,10 @@ function mob_class:get_staticdata() for _,p in pairs(minetest.get_connected_players()) do self:remove_particlespawners(p:get_player_name()) end + -- remove mob when out of range unless tamed if remove_far - and self.can_despawn - and self.remove_ok - and ((not self.nametag) or (self.nametag == "")) + and self:despawn_allowed() and self.lifetimer <= 20 then if spawn_logging then minetest.log("action", "[mcl_mobs] Mob "..tostring(self.name).." despawns at "..minetest.pos_to_string(vector.round(self.object:get_pos())) .. " - out of range") @@ -91,7 +90,6 @@ function mob_class:get_staticdata() return "remove"-- nil end - self.remove_ok = true self.attack = nil self.following = nil self.state = "stand" diff --git a/mods/ENTITIES/mcl_mobs/breeding.lua b/mods/ENTITIES/mcl_mobs/breeding.lua index a70d9cbea..c6d8f92cd 100644 --- a/mods/ENTITIES/mcl_mobs/breeding.lua +++ b/mods/ENTITIES/mcl_mobs/breeding.lua @@ -74,6 +74,7 @@ function mob_class:feed_tame(clicker, feed_count, breed, tame, notake) if self.food >= feed_count then self.food = 0 self.horny = true + self.persistent = true end end diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index be8e1028e..adff1a918 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -1071,15 +1071,43 @@ if mobs_spawn then end) end +local function despawn_allowed(self) + local nametag = self.nametag and self.nametag ~= "" + local not_busy = self.state ~= "attack" and self.following == nil + if self.can_despawn == true then + if not nametag and not_busy and not self.tamed == true and not self.persistent == true then + return true + end + end + return false +end + +function mob_class:despawn_allowed() + despawn_allowed(self) +end + + +assert(despawn_allowed({can_despawn=false}) == false, "despawn_allowed - can_despawn false failed") +assert(despawn_allowed({can_despawn=true}) == true, "despawn_allowed - can_despawn true failed") + +assert(despawn_allowed({can_despawn=true, nametag=""}) == true, "despawn_allowed - blank nametag failed") +assert(despawn_allowed({can_despawn=true, nametag=nil}) == true, "despawn_allowed - nil nametag failed") +assert(despawn_allowed({can_despawn=true, nametag="bob"}) == false, "despawn_allowed - nametag failed") + +assert(despawn_allowed({can_despawn=true, state="attack"}) == false, "despawn_allowed - attack state failed") +assert(despawn_allowed({can_despawn=true, following="blah"}) == false, "despawn_allowed - following state failed") + +assert(despawn_allowed({can_despawn=true, tamed=false}) == true, "despawn_allowed - not tamed") +assert(despawn_allowed({can_despawn=true, tamed=true}) == false, "despawn_allowed - tamed") + +assert(despawn_allowed({can_despawn=true, persistent=true}) == false, "despawn_allowed - persistent") +assert(despawn_allowed({can_despawn=true, persistent=false}) == true, "despawn_allowed - not persistent") + function mob_class:check_despawn(pos, dtime) self.lifetimer = self.lifetimer - dtime -- Despawning: when lifetimer expires, remove mob - if remove_far - and self.can_despawn == true - and ((not self.nametag) or (self.nametag == "")) - and self.state ~= "attack" - and self.following == nil then + if remove_far and despawn_allowed(self) then if self.despawn_immediately or self.lifetimer <= 0 then if logging then minetest.log("action", "[mcl_mobs] Mob "..self.name.." despawns at "..minetest.pos_to_string(pos, 1) .. " lifetimer ran out") diff --git a/mods/ENTITIES/mobs_mc/enderman.lua b/mods/ENTITIES/mobs_mc/enderman.lua index 8415084e1..a57160e4d 100644 --- a/mods/ENTITIES/mobs_mc/enderman.lua +++ b/mods/ENTITIES/mobs_mc/enderman.lua @@ -24,6 +24,12 @@ -- added rain damage. -- fixed the grass_with_dirt issue. +-- How freqeuntly to take and place blocks, in seconds +local take_frequency_min = 235 +local take_frequency_max = 245 +local place_frequency_min = 235 +local place_frequency_max = 245 + minetest.register_entity("mobs_mc:ender_eyes", { visual = "mesh", mesh = "mobs_mc_spider.b3d", @@ -60,13 +66,6 @@ end local pr = PseudoRandom(os.time()*(-334)) --- How freqeuntly to take and place blocks, in seconds -local take_frequency_min = 235 -local take_frequency_max = 245 -local place_frequency_min = 235 -local place_frequency_max = 245 - - -- Texuture overrides for enderman block. Required for cactus because it's original is a nodebox -- and the textures have tranparent pixels. local block_texture_overrides @@ -491,7 +490,7 @@ mcl_mobs.register_mob("mobs_mc:enderman", { local dug = minetest.get_node_or_nil(take_pos) if dug and dug.name == "air" then self._taken_node = node.name - self.can_despawn = false + self.persistent = true local def = minetest.registered_nodes[self._taken_node] -- Update animation and texture accordingly (adds visibly carried block) local block_type @@ -542,7 +541,7 @@ mcl_mobs.register_mob("mobs_mc:enderman", { if success then local def = minetest.registered_nodes[self._taken_node] -- Update animation accordingly (removes visible block) - self.can_despawn = true + self.persistent = false self.animation = select_enderman_animation("normal") self:set_animation(self.animation.current) if def.sounds and def.sounds.place then diff --git a/mods/ENTITIES/mobs_mc/villager_zombie.lua b/mods/ENTITIES/mobs_mc/villager_zombie.lua index 37dce5623..5af1fc879 100644 --- a/mods/ENTITIES/mobs_mc/villager_zombie.lua +++ b/mods/ENTITIES/mobs_mc/villager_zombie.lua @@ -109,7 +109,7 @@ mcl_mobs.register_mob("mobs_mc:villager_zombie", { clicker:set_wielded_item(wielditem) self._curing = math.random(3 * 60, 5 * 60) self.shaking = true - self.can_despawn = false + self.persistent = true end end end, From 3785dcda48a91475e21a2d3c62c9c772710c520e Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Tue, 9 May 2023 14:37:23 +0100 Subject: [PATCH 092/155] Beds mesecons dependency incorrectly named --- mods/ITEMS/mcl_beds/mod.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_beds/mod.conf b/mods/ITEMS/mcl_beds/mod.conf index bb1ea175e..fc6d54f1f 100644 --- a/mods/ITEMS/mcl_beds/mod.conf +++ b/mods/ITEMS/mcl_beds/mod.conf @@ -2,4 +2,4 @@ name = mcl_beds author = BlockMen description = depends = playerphysics -optional_depends = mcl_sounds, mcl_worlds, mcl_wool, mcl_dye, mcl_explosions, mcl_weather, mcl_spawn, doc, mesecon \ No newline at end of file +optional_depends = mcl_sounds, mcl_worlds, mcl_wool, mcl_dye, mcl_explosions, mcl_weather, mcl_spawn, doc, mesecons \ No newline at end of file From ff426412efc7f8e2938eab18275c1a639b1ff51b Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Sun, 7 May 2023 22:13:42 +0100 Subject: [PATCH 093/155] Fix sheep wool farm crash --- mods/ITEMS/REDSTONE/mesecons/actionqueue.lua | 2 ++ mods/ITEMS/REDSTONE/mesecons/internal.lua | 1 + 2 files changed, 3 insertions(+) diff --git a/mods/ITEMS/REDSTONE/mesecons/actionqueue.lua b/mods/ITEMS/REDSTONE/mesecons/actionqueue.lua index 489a81b4a..34202aecd 100644 --- a/mods/ITEMS/REDSTONE/mesecons/actionqueue.lua +++ b/mods/ITEMS/REDSTONE/mesecons/actionqueue.lua @@ -89,6 +89,8 @@ minetest.register_globalstep(function (dtime) end) function mesecon.queue:execute(action) + if not action.pos then return end + -- ignore if action queue function name doesn't exist, -- (e.g. in case the action queue savegame was written by an old mesecons version) if mesecon.queue.funcs[action.func] then diff --git a/mods/ITEMS/REDSTONE/mesecons/internal.lua b/mods/ITEMS/REDSTONE/mesecons/internal.lua index dbe3ebe12..06a5d08b9 100644 --- a/mods/ITEMS/REDSTONE/mesecons/internal.lua +++ b/mods/ITEMS/REDSTONE/mesecons/internal.lua @@ -521,6 +521,7 @@ end -- outputnode (receptor or conductor) at position `output` and has an output in direction `rule` function mesecon.rules_link_rule_all(output, rule) local input = vector.add(output, rule) + if not input then return {} end local inputnode = get_node_force(input) local inputrules = mesecon.get_any_inputrules(inputnode) if not inputrules then From d14c074d6c027f4bcf975556427bedd3d17d4d78 Mon Sep 17 00:00:00 2001 From: megustanlosfrijoles Date: Wed, 10 May 2023 23:12:37 +0000 Subject: [PATCH 094/155] Add spanish translations (#3678) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I'm working on adding more translations. I made this pull request to let everyone now I'm working on this. So far I've completed 1 file/mod Co-authored-by: José Muñoz Reviewed-on: https://git.minetest.land/MineClone2/MineClone2/pulls/3678 Reviewed-by: ancientmarinerdev Co-authored-by: megustanlosfrijoles Co-committed-by: megustanlosfrijoles --- mods/ENTITIES/mobs_mc/locale/mobs_mc.es.tr | 13 ++++++ mods/ITEMS/mcl_anvils/locale/mcl_anvils.es.tr | 1 + mods/ITEMS/mcl_armor/locale/mcl_armor.es.tr | 29 +++++++++++++- mods/ITEMS/mcl_bamboo/locale/mcl_bamboo.es.tr | 40 +++++++++++++++++++ .../mcl_barrels/locale/mcl_barrels.es.tr | 8 ++-- mods/ITEMS/mcl_bells/locale/mcl_bells.es.tr | 2 + mods/ITEMS/mcl_books/locale/mcl_books.es.tr | 5 ++- .../mcl_cauldrons/locale/mcl_cauldrons.es.tr | 1 + mods/ITEMS/mcl_chests/locale/mcl_chests.es.tr | 6 +++ mods/ITEMS/mcl_doors/locale/mcl_doors.es.tr | 2 + mods/ITEMS/mcl_fences/locale/mcl_fences.es.tr | 7 ++-- mods/ITEMS/mcl_honey/locale/mcl_honey.es.tr | 10 +++++ .../mcl_raw_ores/locale/mcl_raw_ores.es.tr | 9 +++++ .../mcl_shields/locale/mcl_shields.es.tr | 19 +++++++++ .../mcl_sponges/locale/mcl_sponges.es.tr | 2 + 15 files changed, 144 insertions(+), 10 deletions(-) create mode 100644 mods/ITEMS/mcl_bamboo/locale/mcl_bamboo.es.tr create mode 100644 mods/ITEMS/mcl_bells/locale/mcl_bells.es.tr create mode 100644 mods/ITEMS/mcl_honey/locale/mcl_honey.es.tr create mode 100644 mods/ITEMS/mcl_raw_ores/locale/mcl_raw_ores.es.tr create mode 100644 mods/ITEMS/mcl_shields/locale/mcl_shields.es.tr diff --git a/mods/ENTITIES/mobs_mc/locale/mobs_mc.es.tr b/mods/ENTITIES/mobs_mc/locale/mobs_mc.es.tr index 09e0335b8..0d4c94ef3 100644 --- a/mods/ENTITIES/mobs_mc/locale/mobs_mc.es.tr +++ b/mods/ENTITIES/mobs_mc/locale/mobs_mc.es.tr @@ -56,3 +56,16 @@ Husk=Zombi Momificado Zombie=Zombi Baby Zombie Pigman=Bebé Hombrecerdo Zombi Zombie Pigman=Hombrecerdo Zombi +Cartographer=Cartógrafo +Armorer=Escudero +Leatherworker=Peletero +Butcher=Carnicero +Weapon Smith=Armero +Tool Smith=Herrero +Cleric=Clérigo +Nitwit=Holgazán +Cod=Bacalao +Salmon=Salmón +Dolphin=Delfín +Pillager=Saqueador +Tropical fish=Pez tropical diff --git a/mods/ITEMS/mcl_anvils/locale/mcl_anvils.es.tr b/mods/ITEMS/mcl_anvils/locale/mcl_anvils.es.tr index 7212b92ba..218ff89cf 100644 --- a/mods/ITEMS/mcl_anvils/locale/mcl_anvils.es.tr +++ b/mods/ITEMS/mcl_anvils/locale/mcl_anvils.es.tr @@ -13,3 +13,4 @@ Armor counts as a tool. It is possible to repair and rename a tool in a single s The anvil has limited durability and 3 damage levels: undamaged, slightly damaged and very damaged. Each time you repair or rename something, there is a 12% chance the anvil gets damaged. Anvils also have a chance of being damaged when they fall by more than 1 block. If a very damaged anvil is damaged again, it is destroyed.=El yunque tiene una durabilidad limitada y 3 niveles de daño: sin daños, ligeramente dañado y muy dañado. Cada vez que reparas o cambias el nombre de algo, hay un 12% de posibilidades de que el yunque se dañe. Los yunques también tienen la posibilidad de dañarse cuando caen en más de 1 bloque. Si un yunque muy dañado se daña nuevamente, se destruye. Slightly Damaged Anvil=Yunque dañado Very Damaged Anvil=Yunque muy dañado +Repair and rename items=Reparar y renombrar objetos diff --git a/mods/ITEMS/mcl_armor/locale/mcl_armor.es.tr b/mods/ITEMS/mcl_armor/locale/mcl_armor.es.tr index e770dff0c..572139c72 100644 --- a/mods/ITEMS/mcl_armor/locale/mcl_armor.es.tr +++ b/mods/ITEMS/mcl_armor/locale/mcl_armor.es.tr @@ -1,23 +1,48 @@ # textdomain: mcl_armor -This is a piece of equippable armor which reduces the amount of damage you receive.=Dies ist ein Teil einer tragbaren Rüstung, die die Menge an Schaden, den Sie erleiden, reduziert. -To equip it, put it on the corresponding armor slot in your inventory menu.=Um es zu tragen, legen Sie es in den passenden Rüstungsplatz in ihrem Inventarmenü. +This is a piece of equippable armor which reduces the amount of damage you receive.=Esta es una pieza de armadura que se puede equipar, la cual reduce la cantidad de daño que recives. +To equip it, put it on the corresponding armor slot in your inventory menu.=Para equiparla, colocala en la ranura de armadura en el menú de tu inventario. Leather Cap=Sombrero de cuero Iron Helmet=Casco de hierro Golden Helmet=Casco de oro Diamond Helmet=Casco de diamante Chain Helmet=Casco de cota de mallas +Netherite Helmet=Casco de netherita Leather Tunic=Túnica de cuero Iron Chestplate=Peto de hierro Golden Chestplate=Peto de oro Diamond Chestplate=Peto de diamante Chain Chestplate=Peto de cota de mallas +Netherite Chestplate=Peto de netherita Leather Pants=Pantalones de cuero Iron Leggings=Grebas de hierro Golden Leggings=Grebas de oro Diamond Leggings=Grebas de diamante Chain Leggings=Grebas de cota de mallas +Netherite Leggings=Grebas de netherita Leather Boots=Botas de cuero Iron Boots=Botas de hierro Golden Boots=Botas de oro Diamond Boots=Botas de diamante Chain Boots=Botas de cota de mallas +Netherite Boots=Botas de netherita +Elytra=Élitros + +#Translations of enchantements +Increases underwater mining speed.=Aumenta la velocidad de minado bajo el agua. +Blast Protection=Protección contra explosiones +Reduces explosion damage and knockback.=Reduce el daño de explosiones y su empuje. +Curse of Binding=Maldicón de ligamiento +Item cannot be removed from armor slots except due to death, breaking or in Creative Mode.=El objeto no puede ser removido de las ranuras de inventario excepto al morir, al romperse, o en Modo Creativo. +Feather Falling=Caída de plumas +Reduces fall damage.=Reduce el daño por caída. +Fire Protection=Protección contra el fuego +Reduces fire damage.=Reduce el daño causado por fuego. +Shooting consumes no regular arrows.=Disparar no consume flechas normales. +Shoot 3 arrows at the cost of one.=Dispara 3 flechas por el costo de una. +Projectile Protection=Protección contra proyectiles +Reduces projectile damage.=Reduce el daño de proyectiles. +Protection=Protección +Reduces most types of damage by 4% for each level.=Reduce la mayoría de tipos de daño por 4% por cada nivel. +Thorns=Espinas +Reflects some of the damage taken when hit, at the cost of reducing durability with each proc.=Refleja una parte del daño infligido, a costa de reducir la durabilidad con cada activación. +Aqua Affinity=Afinidad acuática diff --git a/mods/ITEMS/mcl_bamboo/locale/mcl_bamboo.es.tr b/mods/ITEMS/mcl_bamboo/locale/mcl_bamboo.es.tr new file mode 100644 index 000000000..e21beb760 --- /dev/null +++ b/mods/ITEMS/mcl_bamboo/locale/mcl_bamboo.es.tr @@ -0,0 +1,40 @@ +# textdomain: mcl_bamboo + +### bamboo_base.lua ### + +Bamboo Mosaic Plank=Madera de bambú de mosaico +Bamboo Plank=Madera de bambú +Stripped Bamboo Block=Bloque de bambú sin corteza + +### bamboo_items.lua ### + +A bamboo button is a redstone component made out of stone which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1 second.=Un botón de bambú es un componente de redstone hecho de piedra que se puede presionar para proporcionar energía de redstone. Cuando se empuja, alimenta los componentes adyacentes de redstone durante 1 segundo. + +A wooden pressure plate is a redstone component which supplies its surrounding blocks with redstone power while any movable object (including dropped items, players and mobs) rests on top of it.=Una placa de presión de madera es un componente de redstone que proporciona energía de redstone a sus bloques adyacentes mientras cualquier objeto movible (incluyendo objetos en el suelo, jugadores y mobs) descanse encima suya. + +Bamboo=Bambú +Bamboo Button=Botón de bambú +Bamboo Door.=Puerta de bambú +Bamboo Fence=Valla de bambú +Bamboo Fence Gate=Puerta de valla de bambú +Bamboo Mosaic Slab=Losa de mosaico de bambú +Bamboo Mosaic Stair=Escaleras de mosaico de bambú +Bamboo Plank Slab=Losa de madera de bambú +Bamboo Plank Stair=Escalera de madera de bambú +Bamboo Pressure Plate=Placa de presión de bambú +Bamboo Slab=Losa de bambú +Bamboo Stair=Escalera de bambú +Bamboo Trapdoor.=Trampilla de bambú +Double Bamboo Mosaic Slab=Losa doble de mosaico de bambú +Double Bamboo Plank Slab=Losa doble de madera de bambú +Double Bamboo Slab=Losa doble de bambú +Double Stripped Bamboo Slab=Losa doble de bambú sin corteza +Scaffolding=Andamio +Scaffolding (horizontal)=Andamio (horizontal) +Scaffolding block used to climb up or out across areas.=El bloque de andamio sirve para subir o bajar entre zonas. +Stripped Bamboo Slab=Losa de bambú sin corteza +Stripped Bamboo Stair=Escalera de bambú sin corteza + +To open or close the trapdoor, rightclick it or send a redstone signal to it.=Para abir o cerar una trampilla, haz click derecho o manda una señal de redstone hacia ella. + +Wooden trapdoors are horizontal barriers which can be opened and closed by hand or a redstone signal. They occupy the upper or lower part of a block, depending on how they have been placed. When open, they can be climbed like a ladder.=Las trampillas de madera son barreras horizontales que pueden ser abiertas y cerradas con la mano o por una señal de redstone. diff --git a/mods/ITEMS/mcl_barrels/locale/mcl_barrels.es.tr b/mods/ITEMS/mcl_barrels/locale/mcl_barrels.es.tr index e1fa1b603..33f10f77a 100644 --- a/mods/ITEMS/mcl_barrels/locale/mcl_barrels.es.tr +++ b/mods/ITEMS/mcl_barrels/locale/mcl_barrels.es.tr @@ -1,5 +1,5 @@ # textdomain: mcl_barrels -Barrel= -Barrels are containers which provide 27 inventory slots.= -To access its inventory, rightclick it. When broken, the items will drop out.= -27 inventory slots= \ No newline at end of file +Barrel=Barril +Barrels are containers which provide 27 inventory slots.=Los barriles son contenedores que proveen 27 ranuras de inventario. +To access its inventory, rightclick it. When broken, the items will drop out.=Para acceder a su inventario, haz click derecho sobre el. Al romperse, los objetos caerán al suelo. +27 inventory slots=27 ranuras de inventario diff --git a/mods/ITEMS/mcl_bells/locale/mcl_bells.es.tr b/mods/ITEMS/mcl_bells/locale/mcl_bells.es.tr new file mode 100644 index 000000000..b11750b3e --- /dev/null +++ b/mods/ITEMS/mcl_bells/locale/mcl_bells.es.tr @@ -0,0 +1,2 @@ +# textdomain: mcl_bells +Bell=Campana diff --git a/mods/ITEMS/mcl_books/locale/mcl_books.es.tr b/mods/ITEMS/mcl_books/locale/mcl_books.es.tr index d1e0d947a..880ecc16a 100644 --- a/mods/ITEMS/mcl_books/locale/mcl_books.es.tr +++ b/mods/ITEMS/mcl_books/locale/mcl_books.es.tr @@ -3,15 +3,17 @@ Book=Libro Books are used to make bookshelves and book and quills.=Los libros se usan para hacer estanterías, libros y plumas. “@1”="@1“ Copy of “@1”=Copia de "@1“ -Copy of Copy of “@1”=Kopie von Kopie von „@1“ +Copy of Copy of “@1”=Copia de la copia de "@1" Tatter ed Book=Libro andrajoso by @1=por @1 +# as in “to sign a book” Sign=Firmar Done=Hecho This item can be used to write down some notes.=Este elemento se puede usar para escribir algunas notas. Hold it in the hand, then rightclick to read the current notes and edit then. You can edit the text as often as you like. You can also sign the book which turns it into a written book which you can stack, but it can't be edited anymore.=Sosténgalo en la mano, luego haga clic derecho para leer las notas actuales y luego edite. Puede editar el texto con la frecuencia que desee. También puede firmar el libro que lo convierte en un libro escrito que puede apilar, pero ya no se puede editar. A book can hold up to 4500 characters. The title length is limited to 64 characters.=Un libro puede contener hasta 4500 caracteres. La longitud del título está limitada a 64 caracteres. Enter book title:=Inserta el título del libro: +by @1=por @1 Note: The book will no longer be editable after signing=Nota: El libro ya no será editable después de firmarlo Sign and Close=Firmar y cerrar libro Cancel=Cancelar @@ -23,3 +25,4 @@ To copy the text of the written book, place it into the crafting grid together w Bookshelf=Librería Bookshelves are used for decoration.=Las librerías se utilizan para la decoración. Book and Quill=Libro y pluma +Write down some notes=Escribe algunas notas diff --git a/mods/ITEMS/mcl_cauldrons/locale/mcl_cauldrons.es.tr b/mods/ITEMS/mcl_cauldrons/locale/mcl_cauldrons.es.tr index 16af1a5c9..8222a93a6 100644 --- a/mods/ITEMS/mcl_cauldrons/locale/mcl_cauldrons.es.tr +++ b/mods/ITEMS/mcl_cauldrons/locale/mcl_cauldrons.es.tr @@ -8,3 +8,4 @@ Cauldron (3/3 Water)=Caldera (3/3 de agua) Cauldron (1/3 River Water)=Caldera (1/3 de agua de río) Cauldron (2/3 River Water)=Caldera (2/3 de agua de río) Cauldron (3/3 River Water)=Caldera (3/3 de agua de río) +Stores water=Almacena agua diff --git a/mods/ITEMS/mcl_chests/locale/mcl_chests.es.tr b/mods/ITEMS/mcl_chests/locale/mcl_chests.es.tr index 9d44bacca..ef3e0d9e3 100644 --- a/mods/ITEMS/mcl_chests/locale/mcl_chests.es.tr +++ b/mods/ITEMS/mcl_chests/locale/mcl_chests.es.tr @@ -28,3 +28,9 @@ To access the inventory of a shulker box, place and right-click it. To take a sh Shulker Box=Caja de shulker Large Chest=Arcón Inventory=Inventario +27 inventory slots=27 ranuras de inventario +Can be carried around with its contents=Puede llevarse con sus contenidos +Can be combined to a large chest=Se puede combinar para convertirse en un cofre grande +27 interdimensional inventory slots=27 ranuras de inventario interdimensionales +Put items inside, retrieve them from any ender chest=Pon objetos dentro, recupéralos desde cualquier cofre de ender +Emits a redstone signal when opened=Emite una señal de redstone al abrirse diff --git a/mods/ITEMS/mcl_doors/locale/mcl_doors.es.tr b/mods/ITEMS/mcl_doors/locale/mcl_doors.es.tr index 1a510815b..8b22d354c 100644 --- a/mods/ITEMS/mcl_doors/locale/mcl_doors.es.tr +++ b/mods/ITEMS/mcl_doors/locale/mcl_doors.es.tr @@ -20,3 +20,5 @@ Wooden trapdoors are horizontal barriers which can be opened and closed by hand To open or close the trapdoor, rightclick it or send a redstone signal to it.=Para abrir o cerrar la trampilla, haga clic derecho o envíele una señal de redstone. Iron Trapdoor=Trampilla de hierro Iron trapdoors are horizontal barriers which can only be opened and closed by redstone signals, but not by hand. They occupy the upper or lower part of a block, depending on how they have been placed. When open, they can be climbed like a ladder.=Las trampillas de hierro son barreras horizontales que solo pueden abrirse y cerrarse mediante señales de redstone, no a mano. Ocupan la parte superior o inferior de un bloque, dependiendo de cómo se hayan colocado. Cuando están abiertos, se pueden subir como una escalera. +Openable by players and redstone power=Puede ser abierta por jugadores y señales de redstone +Openable by redstone power=Puede ser abierta por señales de redstone diff --git a/mods/ITEMS/mcl_fences/locale/mcl_fences.es.tr b/mods/ITEMS/mcl_fences/locale/mcl_fences.es.tr index 1e8c3798a..eff541f00 100644 --- a/mods/ITEMS/mcl_fences/locale/mcl_fences.es.tr +++ b/mods/ITEMS/mcl_fences/locale/mcl_fences.es.tr @@ -1,6 +1,6 @@ # textdomain: mcl_fences Fences are structures which block the way. Fences will connect to each other and solid blocks. They cannot be jumped over with a simple jump.=Las cercas son estructuras que bloquean el camino. Las cercas se conectarán entre sí y con los bloques sólidos. No se pueden saltar con un simple salto. -Fence gates can be opened or closed and can't be jumped over. Fences will connect nicely to fence gates.=Las puertas de valla se pueden abrir o cerrar y no se pueden saltar. Las cercas se conectarán muy bien a las puertas de la cerca. +Fence gates can be opened or closed and can't be jumped over. Fences will connect nicely to fence gates.=Las puertas de cerca se pueden abrir o cerrar y no se pueden saltar. Las cercas se conectarán muy bien a las puertas de la cerca. Right-click the fence gate to open or close it.=Haga clic derecho en la puerta de la cerca para abrirla o cerrarla. Oak Fence=Valla de roble Oak Fence Gate=Puerta de roble @@ -9,9 +9,10 @@ Spruce Fence Gate=Puerta de abeto Birch Fence=Valla de abedul Birch Fence Gate=Puerta de abedul Jungle Fence=Valla de la selva -Jungle Fence Gate=Puerta de valla de la selva +Jungle Fence Gate=Puerta de cerca de la selva Dark Oak Fence=Valla de roble oscuro Dark Oak Fence Gate=Puerta de roble oscuro Acacia Fence=Valla de acacia Acacia Fence Gate=Puerta de acacia -Nether Brick Fence=Valla de ladrillo abisal \ No newline at end of file +Nether Brick Fence=Valla de ladrillo abisal +Openable by players and redstone power=Puede ser abierta por jugadores y por señales de redstone diff --git a/mods/ITEMS/mcl_honey/locale/mcl_honey.es.tr b/mods/ITEMS/mcl_honey/locale/mcl_honey.es.tr new file mode 100644 index 000000000..90382020a --- /dev/null +++ b/mods/ITEMS/mcl_honey/locale/mcl_honey.es.tr @@ -0,0 +1,10 @@ +Honeycomb=Bloque de panal +Used to craft beehives and protect copper blocks from further oxidation.=Se utiliza para fabricar apiarios de avejas y para proteger bloques de cobre +Use on copper blocks to prevent further oxidation.=Usa sobre bloques de cobre para evitar mayor oxidación. +Honeycomb Block=Bloque de panal +Honeycomb Block. Used as a decoration.=Bloque de panal. Se utiliza como decoración como decoración +Honey Bottle=Botella de miel +Honey Bottle is used to craft honey blocks and to restore hunger points.=La botella de miel sirve para fabricar bloques de miel y para restaurar puntos de hambre. +Drinking will restore 6 hunger points. Can also be used to craft honey blocks.=Beberla restaurará 6 puntos de hambre. También puede ser usada para fabricar bloques de miel +Honey Block=Bloque de miel +Honey Block. Used as a decoration and in redstone. Is sticky on some sides.=Bloque de miel. Se utiliza como decoración y en redstone. Es pegajoso por algunos lados. diff --git a/mods/ITEMS/mcl_raw_ores/locale/mcl_raw_ores.es.tr b/mods/ITEMS/mcl_raw_ores/locale/mcl_raw_ores.es.tr new file mode 100644 index 000000000..c286e90ec --- /dev/null +++ b/mods/ITEMS/mcl_raw_ores/locale/mcl_raw_ores.es.tr @@ -0,0 +1,9 @@ +# textdomain: mcl_raw_ores +Raw Iron=Hierro en bruto +Raw Gold=Oro en bruto +Raw Iron. Mine an Iron ore to get it.=Hierro en bruto. Mina una mena de hierro para conseguirlo. +Raw Gold. Mine a Gold ore to get it.=Oro en bruto. Mina una mena de oro para conseguirlo. +Block of Raw Iron=Bloque de hierro en bruto +Block of Raw Gold=Bloque de oro en bruto +A block of raw Iron is mostly a decorative block but also useful as a compact storage of raw Iron.=Un bloque de hierro en bruto es sobre todo un bloque decorativo pero tambíen es útil como almacenamiento compacto de hierro en bruto. +A block of raw Gold is mostly a decorative block but also useful as a compact storage of raw Gold.=Un bloque de oro en bruto es sobre todo un bloque decorativo pero tambíen es útil como almacenamiento compacto de oro en bruto. diff --git a/mods/ITEMS/mcl_shields/locale/mcl_shields.es.tr b/mods/ITEMS/mcl_shields/locale/mcl_shields.es.tr new file mode 100644 index 000000000..be941b20a --- /dev/null +++ b/mods/ITEMS/mcl_shields/locale/mcl_shields.es.tr @@ -0,0 +1,19 @@ +# textdomain: mcl_shields +Shield=Escudo +A shield is a tool used for protecting the player against attacks.=Un escudo es una herramienta usada para proteger al jugador de ataques. +White Shield=Escudo blanco +Grey Shield=Escudo gris +Light Grey Shield=Escudo gris claro +Black Shield=Escudo negro +Red Shield=Escudo rojo +Yellow Shield=Escudo amarillo +Green Shield=Escudo verde +Cyan Shield=Escudo cian +Blue Shield=Escudo azul +Magenta Shield=Escudo magenta +Orange Shield=Escudo naranja +Purple Shield=Escudo purpura +Brown Shield=Escudo marrón +Pink Shield=Escudo rosa +Lime Shield=Escudo lima +Light Blue Shield=Escudo azul claro diff --git a/mods/ITEMS/mcl_sponges/locale/mcl_sponges.es.tr b/mods/ITEMS/mcl_sponges/locale/mcl_sponges.es.tr index 4ee44838a..2c775bec0 100644 --- a/mods/ITEMS/mcl_sponges/locale/mcl_sponges.es.tr +++ b/mods/ITEMS/mcl_sponges/locale/mcl_sponges.es.tr @@ -6,3 +6,5 @@ A waterlogged sponge can be dried in the furnace to turn it into (dry) sponge. W Riverwaterlogged Sponge=Esponja mojada con agua de rio This is a sponge soaking wet with river water. It can be dried in the furnace to turn it into (dry) sponge. When there's an empty bucket in the fuel slot of the furnace, the river water will pour into the bucket.=Esta es una esponja mojada con agua de río. Se puede secar en el horno para convertirlo en una esponja (seca). Cuando hay un balde vacío en la ranura de combustible del horno, el agua del río se vierte en el balde. A sponge becomes riverwaterlogged (instead of waterlogged) if it sucks up more river water than (normal) water.=Una esponja se inunda de río (en lugar de inundarse) si absorbe más agua de río que el agua (normal). +Removes water on contact=Remueve agua al contacto +Can be dried in furnace=Puede secarse en un horno From 8a771ebfce80dc2967147cabbbd78eaa1743fd94 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 8 May 2023 16:28:21 +0100 Subject: [PATCH 095/155] Allow adjustment of attack frequency. Reduce attack frequency of Hoglins. Move on_step and do_states functionality off of the attack timer on to their own timer. --- mods/ENTITIES/mcl_mobs/api.lua | 68 +++++++++---------------- mods/ENTITIES/mcl_mobs/api.txt | 1 + mods/ENTITIES/mcl_mobs/combat.lua | 50 +++++++----------- mods/ENTITIES/mcl_mobs/effects.lua | 15 ++++++ mods/ENTITIES/mcl_mobs/init.lua | 1 + mods/ENTITIES/mobs_mc/hoglin+zoglin.lua | 1 + 6 files changed, 62 insertions(+), 74 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 622366fea..231d23fdb 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -300,20 +300,28 @@ end function mob_class:do_states(dtime) --if self.can_open_doors then check_doors(self) end - if self.state == "stand" then - self:do_states_stand() - elseif self.state == PATHFINDING then + -- knockback timer. set in on_punch + if self.pause_timer > 0 then + self.pause_timer = self.pause_timer - dtime + return + end + + if self.state == PATHFINDING then self:check_gowp(dtime) - elseif self.state == "walk" then - self:do_states_walk() - elseif self.state == "runaway" then - -- runaway when punched - self:do_states_runaway() elseif self.state == "attack" then - -- attack routines (explode, dogfight, shoot, dogshoot) if self:do_states_attack(dtime) then return true end + else + if mcl_util.check_dtime_timer(self, dtime, "onstep_dostates", 1) then + if self.state == "stand" then + self:do_states_stand() + elseif self.state == "walk" then + self:do_states_walk() + elseif self.state == "runaway" then + self:do_states_runaway() + end + end end end @@ -323,21 +331,6 @@ local function update_timers (self, dtime) self.pause_timer = self.pause_timer - dtime return true end - - -- attack timer. Not anymore, it seems. Used for also occassionally processing mob step too! - self.timer = self.timer + dtime - - if self.state ~= "attack" and self.state ~= PATHFINDING then - if self.timer < 1 then - return true - end - self.timer = 0 - end - - -- never go over 100 - if self.timer > 100 then - self.timer = 1 - end end function mob_class:outside_limits() @@ -364,6 +357,8 @@ function mob_class:outside_limits() end end + + local function on_step_work (self, dtime) local pos = self.object:get_pos() if not pos then return end @@ -424,35 +419,22 @@ local function on_step_work (self, dtime) self:check_aggro(dtime) + self:check_particlespawners(dtime) + if self.do_custom and self.do_custom(self, dtime) == false then return end - -- In certain circumstances, we abandon processing of certain functionality - local skip_processing = false - if update_timers(self, dtime) then - skip_processing = true - end - - if not skip_processing then + if mcl_util.check_dtime_timer(self, dtime, "onstep_occassional", 1) then self:check_breeding() if player_in_active_range then self:check_item_pickup() self:set_armor_texture() - - if self.opinion_sound_cooloff > 0 then - self.opinion_sound_cooloff = self.opinion_sound_cooloff - dtime - end - -- mob plays random sound at times. Should be 120. Zombie and mob farms are ridiculous - if math.random(1, 70) == 1 then - self:mob_sound("random", true) - end + self:step_opinion_sound(dtime) end - - self:check_particlespawners(dtime) - - if self:do_states(dtime) then return end end + if self:do_states(dtime) then return end + if mobs_debug then self:update_tag() end if not self.object:get_luaentity() then diff --git a/mods/ENTITIES/mcl_mobs/api.txt b/mods/ENTITIES/mcl_mobs/api.txt index 5b5809bca..fe0da4be2 100644 --- a/mods/ENTITIES/mcl_mobs/api.txt +++ b/mods/ENTITIES/mcl_mobs/api.txt @@ -262,6 +262,7 @@ functions needed for the mob to work properly which contains the following: 'custom_visual_size' will not reset visual_size from the base class on reload 'noyaw' If true this mob will not automatically change yaw 'particlespawners' Table of particlespawners attached to the mob. This is implemented in a coord safe manner i.e. spawners are only sent to players within the player_transfer_distance (and automatically removed). This enables infinitely lived particlespawners. + 'attack_frequency' Attack frequency in seconds. If unset, this defaults to 1. Implemented for melee only atm. mobs:gopath(self,target,callback_arrived) pathfind a way to target and run callback on arrival diff --git a/mods/ENTITIES/mcl_mobs/combat.lua b/mods/ENTITIES/mcl_mobs/combat.lua index 872a85d46..0ec1044f5 100644 --- a/mods/ENTITIES/mcl_mobs/combat.lua +++ b/mods/ENTITIES/mcl_mobs/combat.lua @@ -835,6 +835,11 @@ function mob_class:do_states_attack (dtime) local s = self.object:get_pos() local p = self.attack:get_pos() or s + self.timer = self.timer + dtime + if self.timer > 100 then + self.timer = 1 + end + -- stop attacking if player invisible or out of range if not self.attack or not self.attack:get_pos() @@ -1033,54 +1038,45 @@ function mob_class:do_states_attack (dtime) -- move towards enemy if beyond mob reach if dist > self.reach then - -- path finding by rnd - if self.pathfinding -- only if mob has pathfinding enabled - and enable_pathfinding then - + if enable_pathfinding and self.pathfinding then self:smart_mobs(s, p, dist, dtime) end if self:is_at_cliff_or_danger() then - self:set_velocity( 0) self:set_animation( "stand") local yaw = self.object:get_yaw() or 0 yaw = self:set_yaw( yaw + 0.78, 8) else - if self.path.stuck then - self:set_velocity( self.walk_velocity) + self:set_velocity(self.walk_velocity) else - self:set_velocity( self.run_velocity) + self:set_velocity(self.run_velocity) end - if self.animation and self.animation.run_start then - self:set_animation( "run") + self:set_animation("run") else - self:set_animation( "walk") + self:set_animation("walk") end end - else -- rnd: if inside reach range - self.path.stuck = false self.path.stuck_timer = 0 self.path.following = false -- not stuck anymore self:set_velocity( 0) - if not self.custom_attack then + local attack_frequency = self.attack_frequency or 1 - if self.timer > 1 then + if self.timer > attack_frequency then + self.timer = 0 - self.timer = 0 - - if self.double_melee_attack - and math.random(1, 2) == 1 then - self:set_animation( "punch2") + if not self.custom_attack then + if self.double_melee_attack and math.random(1, 2) == 1 then + self:set_animation("punch2") else - self:set_animation( "punch") + self:set_animation("punch") end local p2 = p @@ -1090,8 +1086,6 @@ function mob_class:do_states_attack (dtime) s2.y = s2.y + .5 if self:line_of_sight( p2, s2) == true then - - -- play attack sound self:mob_sound("attack") -- punch player (or what player is attached to) @@ -1104,13 +1098,7 @@ function mob_class:do_states_attack (dtime) damage_groups = {fleshy = self.damage} }, nil) end - end - else -- call custom attack every second - if self.custom_attack - and self.timer > 1 then - - self.timer = 0 - + else self.custom_attack(self, p) end end @@ -1136,7 +1124,7 @@ function mob_class:do_states_attack (dtime) yaw = self:set_yaw( yaw, 0, dtime) - local stay_away_from_player = vector.new(0,0,0) + local stay_away_from_player = vector.zero() --strafe back and fourth diff --git a/mods/ENTITIES/mcl_mobs/effects.lua b/mods/ENTITIES/mcl_mobs/effects.lua index 4a4452f7f..696994d0d 100644 --- a/mods/ENTITIES/mcl_mobs/effects.lua +++ b/mods/ENTITIES/mcl_mobs/effects.lua @@ -4,6 +4,8 @@ local active_particlespawners = {} local disable_blood = minetest.settings:get_bool("mobs_disable_blood") local DEFAULT_FALL_SPEED = -9.81*1.5 +local PATHFINDING = "gowp" + local player_transfer_distance = tonumber(minetest.settings:get("player_transfer_distance")) or 128 if player_transfer_distance == 0 then player_transfer_distance = math.huge end @@ -136,6 +138,19 @@ function mob_class:mob_sound(soundname, is_opinion, fixed_pitch) end end +function mob_class:step_opinion_sound(dtime) + if self.state ~= "attack" and self.state ~= PATHFINDING then + + if self.opinion_sound_cooloff > 0 then + self.opinion_sound_cooloff = self.opinion_sound_cooloff - dtime + end + -- mob plays random sound at times. Should be 120. Zombie and mob farms are ridiculous + if math.random(1, 70) == 1 then + self:mob_sound("random", true) + end + end +end + function mob_class:add_texture_mod(mod) local full_mod = "" local already_added = false diff --git a/mods/ENTITIES/mcl_mobs/init.lua b/mods/ENTITIES/mcl_mobs/init.lua index bdc062470..6bd39b2cf 100644 --- a/mods/ENTITIES/mcl_mobs/init.lua +++ b/mods/ENTITIES/mcl_mobs/init.lua @@ -154,6 +154,7 @@ function mcl_mobs.register_mob(name, def) description = def.description, type = def.type, attack_type = def.attack_type, + attack_frequency = def.attack_frequency, fly = def.fly or false, fly_in = def.fly_in or {"air", "__airlike"}, owner = def.owner or "", diff --git a/mods/ENTITIES/mobs_mc/hoglin+zoglin.lua b/mods/ENTITIES/mobs_mc/hoglin+zoglin.lua index 8bad858a8..7154a6537 100644 --- a/mods/ENTITIES/mobs_mc/hoglin+zoglin.lua +++ b/mods/ENTITIES/mobs_mc/hoglin+zoglin.lua @@ -19,6 +19,7 @@ local hoglin = { xp_max = 9, armor = {fleshy = 90}, attack_type = "dogfight", + attack_frequency = 3; damage = 4, reach = 3, collisionbox = {-.6, -0.01, -.6, .6, 1.4, .6}, From 0787d7a988d3ceec60ffa7e024ad6a3f37c66030 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 8 May 2023 16:30:40 +0100 Subject: [PATCH 096/155] Remove duplicate code that has been moved. --- mods/ENTITIES/mcl_mobs/api.lua | 8 -------- 1 file changed, 8 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 231d23fdb..a5af89690 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -325,14 +325,6 @@ function mob_class:do_states(dtime) end end -local function update_timers (self, dtime) - -- knockback timer. set in on_punch - if self.pause_timer > 0 then - self.pause_timer = self.pause_timer - dtime - return true - end -end - function mob_class:outside_limits() local pos = self.object:get_pos() if pos then From 39872f8ef655adac5fae6274c5414e023daddc5a Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 8 May 2023 17:10:40 +0100 Subject: [PATCH 097/155] Fix hoglin reach and view_range --- mods/ENTITIES/mobs_mc/hoglin+zoglin.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/hoglin+zoglin.lua b/mods/ENTITIES/mobs_mc/hoglin+zoglin.lua index 7154a6537..2643467b6 100644 --- a/mods/ENTITIES/mobs_mc/hoglin+zoglin.lua +++ b/mods/ENTITIES/mobs_mc/hoglin+zoglin.lua @@ -21,7 +21,7 @@ local hoglin = { attack_type = "dogfight", attack_frequency = 3; damage = 4, - reach = 3, + reach = 1.9, collisionbox = {-.6, -0.01, -.6, .6, 1.4, .6}, visual = "mesh", mesh = "extra_mobs_hoglin.b3d", @@ -64,7 +64,7 @@ local hoglin = { punch_end = 32, }, fear_height = 4, - view_range = 32, + view_range = 16, floats = 0, custom_attack = function(self) if self.state == "attack" and self.reach > vector.distance(self.object:get_pos(), self.attack:get_pos()) then From d920441a015d19c58583ed643e46ab985fa0a4f6 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 8 May 2023 21:51:13 +0100 Subject: [PATCH 098/155] Reduce network activity for elytra flying rocket particles --- mods/CORE/mcl_util/init.lua | 12 +++++++++++- mods/PLAYER/mcl_playerplus/init.lua | 26 +++++++++++++++----------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/mods/CORE/mcl_util/init.lua b/mods/CORE/mcl_util/init.lua index 2b3e0918a..5872ce742 100644 --- a/mods/CORE/mcl_util/init.lua +++ b/mods/CORE/mcl_util/init.lua @@ -34,8 +34,10 @@ function mcl_util.mcl_log(message, module, bypass_default_logger) end end +local player_timers = {} + -- This is a dtime timer than can be used in on_step functions so it works every x seconds --- self - Object you want to store timer data on. E.g. mob or a minecart +-- self - Object you want to store timer data on. E.g. mob or a minecart, or player_name -- dtime - The time since last run of on_step, should be passed in to function -- timer_name - This is the name of the timer and also the key to store the data. No spaces + lowercase. -- threshold - The time before it returns successful. 0.2 if you want to run it 5 times a second. @@ -43,6 +45,14 @@ function mcl_util.check_dtime_timer(self, dtime, timer_name, threshold) if not self or not threshold or not dtime then return end if not timer_name or timer_name == "" then return end + if type(self) == "string" then + local player_name = self + if not player_timers[player_name] then + player_timers[player_name] = {} + end + self = player_timers[player_name] + end + if not self._timers then self._timers = {} end diff --git a/mods/PLAYER/mcl_playerplus/init.lua b/mods/PLAYER/mcl_playerplus/init.lua index 1de839456..d3235daa8 100644 --- a/mods/PLAYER/mcl_playerplus/init.lua +++ b/mods/PLAYER/mcl_playerplus/init.lua @@ -272,17 +272,21 @@ minetest.register_globalstep(function(dtime) if vector.length(player_velocity) < 40 then -- player:add_velocity(vector.multiply(player:get_look_dir(), 4)) speed_mult = elytra_vars.rocket_speed - add_particle({ - pos = fly_pos, - velocity = {x = 0, y = 0, z = 0}, - acceleration = {x = 0, y = 0, z = 0}, - expirationtime = math.random(0.3, 0.5), - size = math.random(1, 2), - collisiondetection = false, - vertical = false, - texture = "mcl_particles_bonemeal.png^[colorize:#bc7a57:127", - glow = 5, - }) + + if mcl_util.check_dtime_timer(name, dtime, "ely_rocket_particle_spawn", 0.3) then + minetest.log("pspawn") + add_particle({ + pos = fly_pos, + velocity = vector.zero(), + acceleration = vector.zero(), + expirationtime = math.random(0.3, 0.5), + size = math.random(1, 2), + collisiondetection = false, + vertical = false, + texture = "mcl_particles_bonemeal.png^[colorize:#bc7a57:127", + glow = 5, + }) + end end end From 7726e576f0ae9e426d4dba3dee875f300974e169 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 8 May 2023 21:59:20 +0100 Subject: [PATCH 099/155] Remove oopsie --- mods/PLAYER/mcl_playerplus/init.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/mods/PLAYER/mcl_playerplus/init.lua b/mods/PLAYER/mcl_playerplus/init.lua index d3235daa8..d4a21508e 100644 --- a/mods/PLAYER/mcl_playerplus/init.lua +++ b/mods/PLAYER/mcl_playerplus/init.lua @@ -274,7 +274,6 @@ minetest.register_globalstep(function(dtime) speed_mult = elytra_vars.rocket_speed if mcl_util.check_dtime_timer(name, dtime, "ely_rocket_particle_spawn", 0.3) then - minetest.log("pspawn") add_particle({ pos = fly_pos, velocity = vector.zero(), From 8092fd573c91cbdd1f7b6ca6f42a3ad929a4291a Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 8 May 2023 23:16:04 +0100 Subject: [PATCH 100/155] Cleanup self.acc code and convert to new style vectors --- mods/ENTITIES/mcl_mobs/combat.lua | 20 ++++++++++++++------ mods/ENTITIES/mcl_mobs/physics.lua | 15 +++++++-------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/combat.lua b/mods/ENTITIES/mcl_mobs/combat.lua index 0ec1044f5..3b53e0d1a 100644 --- a/mods/ENTITIES/mcl_mobs/combat.lua +++ b/mods/ENTITIES/mcl_mobs/combat.lua @@ -830,16 +830,18 @@ local function clear_aggro(self) end function mob_class:do_states_attack (dtime) - local yaw = self.object:get_yaw() or 0 - - local s = self.object:get_pos() - local p = self.attack:get_pos() or s - self.timer = self.timer + dtime if self.timer > 100 then self.timer = 1 end + local s = self.object:get_pos() + if not s then return end + + local p = self.attack:get_pos() or s + + local yaw = self.object:get_yaw() or 0 + -- stop attacking if player invisible or out of range if not self.attack or not self.attack:get_pos() @@ -1141,7 +1143,13 @@ function mob_class:do_states_attack (dtime) if math.random(40) == 1 then self.strafe_direction = self.strafe_direction*-1 end - self.acc = vector.add(vector.multiply(vector.rotate_around_axis(vector.direction(s, p), vector.new(0,1,0), self.strafe_direction), 0.3*self.walk_velocity), stay_away_from_player) + + local dir = vector.rotate_around_axis(vector.direction(s, p), vector.new(0,1,0), self.strafe_direction) + local dir2 = vector.multiply(dir, 0.3 * self.walk_velocity) + + if dir2 and stay_away_from_player then + self.acc = vector.add(dir2, stay_away_from_player) + end else self:set_velocity( 0) end diff --git a/mods/ENTITIES/mcl_mobs/physics.lua b/mods/ENTITIES/mcl_mobs/physics.lua index 4ef72eed7..2859cfe98 100644 --- a/mods/ENTITIES/mcl_mobs/physics.lua +++ b/mods/ENTITIES/mcl_mobs/physics.lua @@ -198,6 +198,8 @@ end -- move mob in facing direction function mob_class:set_velocity(v) + if not v then return end + local c_x, c_y = 0, 0 -- can mob be pushed, if so calculate direction @@ -207,18 +209,15 @@ function mob_class:set_velocity(v) -- halt mob if it has been ordered to stay if self.order == "stand" or self.order == "sit" then - self.acc=vector.new(0,0,0) - return + self.acc = vector.zero() + return end local yaw = (self.object:get_yaw() or 0) + self.rotate local vv = self.object:get_velocity() - if vv then - self.acc={ - x = ((math.sin(yaw) * -v) + c_x)*.27, - y = 0, - z = ((math.cos(yaw) * v) + c_y)*.27, - } + + if vv and yaw then + self.acc = vector.new(((math.sin(yaw) * -v) + c_x) * .27, 0, ((math.cos(yaw) * v) + c_y) * .27) end end From 31e6e3801336bd4a6a6855db1ed543e353f27221 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 8 May 2023 23:33:58 +0100 Subject: [PATCH 101/155] Clean up is_as_cliff code and convert to new style vector --- mods/ENTITIES/mcl_mobs/movement.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/movement.lua b/mods/ENTITIES/mcl_mobs/movement.lua index 9dedd7e2c..d97584b58 100644 --- a/mods/ENTITIES/mcl_mobs/movement.lua +++ b/mods/ENTITIES/mcl_mobs/movement.lua @@ -262,8 +262,9 @@ function mob_class:is_at_water_danger(can_jump_cliff) local ypos = pos.y + self.collisionbox[2] -- just above floor local free_fall, blocker = minetest.line_of_sight( - {x = pos.x + dir_x, y = ypos, z = pos.z + dir_z}, - {x = pos.x + dir_x, y = ypos - 3, z = pos.z + dir_z}) + vector.new(pos.x + dir_x, ypos, pos.z + dir_z), + vector.new(pos.x + dir_x, ypos - 3, pos.z + dir_z)) + if free_fall then return true else From 09619a62eeae1887c3b4b5c662598d68198ae13d Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 8 May 2023 23:34:45 +0100 Subject: [PATCH 102/155] Clean up is_as_cliff code and convert to new style vector part 2 --- mods/ENTITIES/mcl_mobs/movement.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/movement.lua b/mods/ENTITIES/mcl_mobs/movement.lua index d97584b58..469ac9e85 100644 --- a/mods/ENTITIES/mcl_mobs/movement.lua +++ b/mods/ENTITIES/mcl_mobs/movement.lua @@ -219,8 +219,9 @@ function mob_class:is_at_cliff_or_danger(can_jump_cliff) local ypos = pos.y + self.collisionbox[2] -- just above floor local free_fall, blocker = minetest.line_of_sight( - {x = pos.x + dir_x, y = ypos, z = pos.z + dir_z}, - {x = pos.x + dir_x, y = ypos - self.fear_height, z = pos.z + dir_z}) + vector.new(pos.x + dir_x, ypos, pos.z + dir_z), + vector.new(pos.x + dir_x, ypos - self.fear_height, pos.z + dir_z)) + if free_fall then return true else From 9518d47662d306aa46e68f90659ea073a4300970 Mon Sep 17 00:00:00 2001 From: 3raven <3raven@noreply.git.minetest.land> Date: Thu, 11 May 2023 22:39:49 +0000 Subject: [PATCH 103/155] (french) translation enhancements (#3643) - Add missing translation - Fix broken translations - Fix unacurate description - Correct/improve/change for cohesion french translation Translations templates have been updated,other translations must be updated. Tell us about your pull request! Reference related issues, if necessary ### Testing Tell us how to test your changes! Co-authored-by: 3raven Reviewed-on: https://git.minetest.land/MineClone2/MineClone2/pulls/3643 Reviewed-by: AFCMS Co-authored-by: 3raven <3raven@noreply.git.minetest.land> Co-committed-by: 3raven <3raven@noreply.git.minetest.land> --- .../locale/mcl_explosions.fr.tr | 2 + mods/CORE/mcl_explosions/locale/template.txt | 2 + .../ENTITIES/mcl_boats/locale/mcl_boats.fr.tr | 8 +++ mods/ENTITIES/mcl_boats/locale/template.txt | 10 ++- .../locale/mcl_falling_nodes.fr.tr | 3 + .../mcl_falling_nodes/locale/template.txt | 3 + mods/ENTITIES/mcl_mobs/locale/mcl_mobs.fr.tr | 2 + mods/ENTITIES/mobs_mc/locale/mobs_mc.fr.tr | 6 +- mods/ENTITIES/mobs_mc/locale/template.txt | 5 +- mods/HELP/mcl_doc/locale/mcl_doc.fr.tr | 1 + mods/HELP/mcl_doc/locale/template.txt | 1 + .../locale/mcl_doc_basics.fr.tr | 2 +- .../locale/mcl_achievements.fr.tr | 36 +++++++++- mods/HUD/mcl_achievements/locale/template.txt | 18 ++++- mods/HUD/mcl_experience/bottle.lua | 2 +- .../locale/mlc_experience.fr.tr | 1 + mods/HUD/mcl_experience/locale/template.txt | 1 + .../mcl_inventory/locale/mcl_inventory.fr.tr | 1 + mods/HUD/mcl_inventory/locale/template.txt | 1 + .../mcl_ver_info/locale/mcl_ver_info.fr.tr | 2 + .../locale/mcl_dispensers.fr.tr | 2 +- .../locale/mesecons_button.fr.tr | 5 ++ .../mesecons_button/locale/template.txt | 3 + .../locale/mesecons_noteblock.fr.tr | 32 ++++----- .../locale/mesecons_pressureplates.fr.tr | 5 ++ .../locale/template.txt | 3 + mods/ITEMS/mcl_armor/locale/mcl_armor.fr.tr | 8 +-- .../locale/mcl_armor_stand.fr.tr | 2 +- mods/ITEMS/mcl_bamboo/bamboo_base.lua | 4 +- mods/ITEMS/mcl_bamboo/locale/mcl_bamboo.fr.tr | 45 ++++++++++++ mods/ITEMS/mcl_bamboo/locale/template.txt | 5 ++ .../mcl_banners/locale/mcl_banners.fr.tr | 1 + mods/ITEMS/mcl_banners/locale/template.txt | 1 + .../mcl_beehives/locale/mcl_beehives.fr.tr | 5 ++ .../mcl_beehives/locale/mcl_beehives.ja.tr | 3 +- mods/ITEMS/mcl_beehives/locale/template.txt | 3 +- .../locale/mcl_blackstone.fr.tr | 1 + mods/ITEMS/mcl_blackstone/locale/template.txt | 3 +- mods/ITEMS/mcl_blast_furnace/init.lua | 12 ++-- .../locale/mcl_blast_furnace.fr.tr | 9 ++- .../mcl_blast_furnace/locale/template.txt | 11 +-- .../mcl_buckets/locale/mcl_buckets.fr.tr | 5 +- mods/ITEMS/mcl_cauldrons/init.lua | 4 +- .../mcl_compass/locale/mcl_compass.fr.tr | 6 +- mods/ITEMS/mcl_compass/locale/template.txt | 4 ++ .../locale/mcl_composters.fr.tr | 2 +- mods/ITEMS/mcl_composters/locale/template.txt | 2 +- mods/ITEMS/mcl_copper/locale/mcl_copper.fr.tr | 20 ++++++ mods/ITEMS/mcl_core/locale/mcl_core.fr.tr | 68 +++++++++---------- .../mcl_crimson/locale/mcl_crimson.fr.tr | 30 ++++++-- mods/ITEMS/mcl_crimson/locale/template.txt | 30 ++++++-- .../mcl_deepslate/locale/mcl_deepslate.fr.tr | 4 +- mods/ITEMS/mcl_deepslate/locale/template.txt | 4 +- .../locale/mcl_enchanting.fr.tr | 10 +-- .../mcl_farming/locale/mcl_farming.fr.tr | 12 +++- mods/ITEMS/mcl_farming/locale/template.txt | 12 +++- mods/ITEMS/mcl_farming/wheat.lua | 18 ++--- mods/ITEMS/mcl_fences/locale/mcl_fences.fr.tr | 16 ++--- mods/ITEMS/mcl_fire/locale/mcl_fire.fr.tr | 8 +-- .../mcl_flowers/locale/mcl_flowers.fr.tr | 3 + mods/ITEMS/mcl_furnaces/init.lua | 10 ++- .../mcl_furnaces/locale/mcl_furnaces.fr.tr | 5 +- mods/ITEMS/mcl_furnaces/locale/template.txt | 5 +- mods/ITEMS/mcl_honey/locale/mcl_honey.fr.tr | 11 +++ mods/ITEMS/mcl_honey/locale/mcl_honey.ja.tr | 1 + mods/ITEMS/mcl_honey/locale/template.txt | 1 + .../mcl_hoppers/locale/mcl_hoppers.fr.tr | 8 +-- mods/ITEMS/mcl_itemframes/init.lua | 8 +-- mods/ITEMS/mcl_itemframes/item_frames_API.lua | 2 +- .../locale/mcl_itemframes.fr.tr | 8 ++- mods/ITEMS/mcl_itemframes/locale/template.txt | 10 +-- .../mcl_lectern/locale/mcl_lectern.fr.tr | 4 ++ mods/ITEMS/mcl_lectern/locale/template.txt | 4 ++ .../mcl_mangrove/locale/mcl_mangrove.fr.tr | 2 +- mods/ITEMS/mcl_mobitems/init.lua | 2 +- .../mcl_mobitems/locale/mcl_mobitems.fr.tr | 15 +++- mods/ITEMS/mcl_mobitems/locale/template.txt | 9 +++ mods/ITEMS/mcl_monster_eggs/init.lua | 5 +- mods/ITEMS/mcl_nether/locale/mcl_nether.fr.tr | 9 +-- mods/ITEMS/mcl_nether/locale/template.txt | 3 +- .../mcl_portals/locale/mcl_portals.fr.tr | 2 +- .../mcl_raw_ores/locale/mcl_raw_ores.fr.tr | 8 +-- .../mcl_raw_ores/locale/mcl_raw_ores.ja.tr | 8 +-- mods/ITEMS/mcl_raw_ores/locale/template.txt | 8 +-- mods/ITEMS/mcl_sculk/locale/mcl_sculk.fr.tr | 7 ++ mods/ITEMS/mcl_sculk/locale/template.txt | 7 ++ mods/ITEMS/mcl_signs/locale/mcl_signs.fr.tr | 13 ++-- mods/ITEMS/mcl_signs/locale/template.txt | 3 + .../locale/mcl_smithing_table.fr.tr | 2 + .../mcl_smithing_table/locale/template.txt | 2 + mods/ITEMS/mcl_smoker/init.lua | 12 ++-- mods/ITEMS/mcl_smoker/locale/mcl_smoker.fr.tr | 11 +-- mods/ITEMS/mcl_smoker/locale/template.txt | 7 +- mods/ITEMS/mcl_tools/locale/mcl_tools.fr.tr | 8 +-- .../mclx_fences/locale/mclx_fences.fr.tr | 4 +- .../mclx_stairs/locale/mclx_stairs.fr.tr | 10 +-- .../screwdriver/locale/screwdriver.fr.tr | 2 +- .../screwdriver/locale/screwdriver.ja.tr | 2 +- .../screwdriver/locale/screwdriver.pl.tr | 2 +- .../screwdriver/locale/screwdriver.ru.tr | 2 +- .../screwdriver/locale/screwdriver.zh_TW.tr | 2 +- mods/ITEMS/screwdriver/locale/template.txt | 2 +- 102 files changed, 549 insertions(+), 225 deletions(-) create mode 100644 mods/CORE/mcl_explosions/locale/mcl_explosions.fr.tr create mode 100644 mods/CORE/mcl_explosions/locale/template.txt create mode 100644 mods/ENTITIES/mcl_falling_nodes/locale/mcl_falling_nodes.fr.tr create mode 100644 mods/ENTITIES/mcl_falling_nodes/locale/template.txt create mode 100644 mods/HUD/mcl_ver_info/locale/mcl_ver_info.fr.tr create mode 100644 mods/ITEMS/mcl_bamboo/locale/mcl_bamboo.fr.tr create mode 100644 mods/ITEMS/mcl_beehives/locale/mcl_beehives.fr.tr create mode 100644 mods/ITEMS/mcl_honey/locale/mcl_honey.fr.tr create mode 100644 mods/ITEMS/mcl_lectern/locale/mcl_lectern.fr.tr create mode 100644 mods/ITEMS/mcl_lectern/locale/template.txt create mode 100644 mods/ITEMS/mcl_sculk/locale/mcl_sculk.fr.tr create mode 100644 mods/ITEMS/mcl_sculk/locale/template.txt diff --git a/mods/CORE/mcl_explosions/locale/mcl_explosions.fr.tr b/mods/CORE/mcl_explosions/locale/mcl_explosions.fr.tr new file mode 100644 index 000000000..7804d608c --- /dev/null +++ b/mods/CORE/mcl_explosions/locale/mcl_explosions.fr.tr @@ -0,0 +1,2 @@ +# textdomain:mcl_explosions +@1 was caught in an explosion.=@1 est mort dans une explosion \ No newline at end of file diff --git a/mods/CORE/mcl_explosions/locale/template.txt b/mods/CORE/mcl_explosions/locale/template.txt new file mode 100644 index 000000000..656b444f9 --- /dev/null +++ b/mods/CORE/mcl_explosions/locale/template.txt @@ -0,0 +1,2 @@ +# textdomain:mcl_explosions +@1 was caught in an explosion.= \ No newline at end of file diff --git a/mods/ENTITIES/mcl_boats/locale/mcl_boats.fr.tr b/mods/ENTITIES/mcl_boats/locale/mcl_boats.fr.tr index 76905c1f3..e1ecd9b01 100644 --- a/mods/ENTITIES/mcl_boats/locale/mcl_boats.fr.tr +++ b/mods/ENTITIES/mcl_boats/locale/mcl_boats.fr.tr @@ -11,3 +11,11 @@ Spruce Boat=Bateau en sapin Water vehicle=Véhicule aquatique Sneak to dismount=Se baisser pour descendre Obsidian Boat=Bateau en obsidienne +Mangrove Boat=Bateau en palétuvier +Oak Chest Boat=Bateau en chêne avec coffre +Spruce Chest Boat=Bateau en sapin avec coffre +Birch Chest Boat=Bateau en bouleau avec coffre +Jungle Chest Boat=Bateau en acajou avec coffre +Acacia Chest Boat=Bateau en acacia avec coffre +Dark Oak Chest Boat=Bateau en chêne noir avec coffre +Mangrove Chest Boat=Bateau en palétuvier avec coffre diff --git a/mods/ENTITIES/mcl_boats/locale/template.txt b/mods/ENTITIES/mcl_boats/locale/template.txt index c071f3ed4..16c8b681e 100644 --- a/mods/ENTITIES/mcl_boats/locale/template.txt +++ b/mods/ENTITIES/mcl_boats/locale/template.txt @@ -10,4 +10,12 @@ Rightclick on a water source to place the boat. Rightclick the boat to enter it. Spruce Boat= Water vehicle= Sneak to dismount= -Obsidian Boat= \ No newline at end of file +Obsidian Boat= +Mangrove Boat= +Oak Chest Boat= +Spruce Chest Boat= +Birch Chest Boat= +Jungle Chest Boat= +Acacia Chest Boat= +Dark Oak Chest Boat= +Mangrove Chest Boat= diff --git a/mods/ENTITIES/mcl_falling_nodes/locale/mcl_falling_nodes.fr.tr b/mods/ENTITIES/mcl_falling_nodes/locale/mcl_falling_nodes.fr.tr new file mode 100644 index 000000000..5d311d3e2 --- /dev/null +++ b/mods/ENTITIES/mcl_falling_nodes/locale/mcl_falling_nodes.fr.tr @@ -0,0 +1,3 @@ +# textdomain: mcl_falling_nodes +@1 was smashed by a falling anvil.=@1 a été écrasé par une enclume +@1 was smashed by a falling block.=@1 a été écrasé par un bloc diff --git a/mods/ENTITIES/mcl_falling_nodes/locale/template.txt b/mods/ENTITIES/mcl_falling_nodes/locale/template.txt new file mode 100644 index 000000000..4adabaf01 --- /dev/null +++ b/mods/ENTITIES/mcl_falling_nodes/locale/template.txt @@ -0,0 +1,3 @@ +# textdomain: mcl_falling_nodes +@1 was smashed by a falling anvil.= +@1 was smashed by a falling block.= diff --git a/mods/ENTITIES/mcl_mobs/locale/mcl_mobs.fr.tr b/mods/ENTITIES/mcl_mobs/locale/mcl_mobs.fr.tr index 96ac6a817..58fcaa51d 100644 --- a/mods/ENTITIES/mcl_mobs/locale/mcl_mobs.fr.tr +++ b/mods/ENTITIES/mcl_mobs/locale/mcl_mobs.fr.tr @@ -9,3 +9,5 @@ Before you use the name tag, you need to set a name at an anvil. Then you can us Only peaceful mobs allowed!=Seuls les mobs pacifiques sont autorisées! Give names to mobs=Donne des noms aux mobs Set name at anvil=Définir le nom sur l'enclume +Removes specified mobs except nametagged and tamed ones. For the second parameter, use nametagged/tamed to select only nametagged/tamed mobs, or a range to specify a maximum distance from the player.=Enlève les mobs spécifiés sauf ceux qui sont nommés et apprivoisés. Pour le deuxième paramètre, utiliser nametagged/tamed pour ne sélectionner que les mobs nommés/apprivoisés, ou une distance pour spécifier la distance maximale par rapport au joueur. +Default usage. Clearing hostile mobs. For more options please type: /help clearmobs=Usage par défaut. Enlève les mobs hostiles. Pour plus d'options saisir : /help clearmobs diff --git a/mods/ENTITIES/mobs_mc/locale/mobs_mc.fr.tr b/mods/ENTITIES/mobs_mc/locale/mobs_mc.fr.tr index 06c97945e..c4440a727 100644 --- a/mods/ENTITIES/mobs_mc/locale/mobs_mc.fr.tr +++ b/mods/ENTITIES/mobs_mc/locale/mobs_mc.fr.tr @@ -1,5 +1,6 @@ # textdomain: mobs_mc Agent=Agent +Axolotl=Axolotl Bat=Chauve-souris Blaze=Blaze Chicken=Poulet @@ -66,4 +67,7 @@ Cod=Morue Salmon=Saumon Dolphin=Dauphin Pillager=Pilleur -Tropical fish=Poisson tropical \ No newline at end of file +Tropical fish=Poisson tropical +Hoglin=Hoglin +Strider=Arpenteur +Glow Squid=Poulpe Brillant \ No newline at end of file diff --git a/mods/ENTITIES/mobs_mc/locale/template.txt b/mods/ENTITIES/mobs_mc/locale/template.txt index 38c6111b5..9c1ee5cd7 100644 --- a/mods/ENTITIES/mobs_mc/locale/template.txt +++ b/mods/ENTITIES/mobs_mc/locale/template.txt @@ -67,4 +67,7 @@ Cod= Salmon= Dolphin= Pillager= -Tropical fish= \ No newline at end of file +Tropical fish= +Hoglin= +Strider= +Glow Squid= \ No newline at end of file diff --git a/mods/HELP/mcl_doc/locale/mcl_doc.fr.tr b/mods/HELP/mcl_doc/locale/mcl_doc.fr.tr index a3fd6c983..529615821 100644 --- a/mods/HELP/mcl_doc/locale/mcl_doc.fr.tr +++ b/mods/HELP/mcl_doc/locale/mcl_doc.fr.tr @@ -2,6 +2,7 @@ Water can flow into this block and cause it to drop as an item.=L'eau peut s'écouler dans ce bloc et provoquer sa chute en tant qu'élément. This block can be turned into dirt with a hoe.=Ce bloc peut être transformé en terre avec une houe. This block can be turned into farmland with a hoe.=Ce bloc peut être transformé en terres agricoles avec une houe. +This block can be turned into grass path with a shovel.=Ce bloc peut être transformé en chemin d'herbe avec une pelle. This block acts as a soil for all saplings.=Ce bloc agit comme un sol pour tous les pousses arbres. This block acts as a soil for some saplings.=Ce bloc agit comme un sol pour certains pousses arbres. Sugar canes will grow on this block.=Les cannes à sucre pousseront sur ce bloc. diff --git a/mods/HELP/mcl_doc/locale/template.txt b/mods/HELP/mcl_doc/locale/template.txt index de652f05e..ec825644c 100644 --- a/mods/HELP/mcl_doc/locale/template.txt +++ b/mods/HELP/mcl_doc/locale/template.txt @@ -2,6 +2,7 @@ Water can flow into this block and cause it to drop as an item.= This block can be turned into dirt with a hoe.= This block can be turned into farmland with a hoe.= +This block can be turned into grass path with a shovel.= This block acts as a soil for all saplings.= This block acts as a soil for some saplings.= Sugar canes will grow on this block.= diff --git a/mods/HELP/mcl_doc_basics/locale/mcl_doc_basics.fr.tr b/mods/HELP/mcl_doc_basics/locale/mcl_doc_basics.fr.tr index 28f2593fa..6825e4191 100644 --- a/mods/HELP/mcl_doc_basics/locale/mcl_doc_basics.fr.tr +++ b/mods/HELP/mcl_doc_basics/locale/mcl_doc_basics.fr.tr @@ -435,7 +435,7 @@ Note that “transparency” here only means that the block is able to carry bri Coordinates=Coordonnées The world is a large cube. And because of this, a position in the world can be easily expressed with Cartesian coordinates. That is, for each position in the world, there are 3 values X, Y and Z.=Le monde est un grand cube. Et pour cette raison, une position dans le monde peut être facilement exprimée avec des coordonnées cartésiennes. Autrement dit, pour chaque position dans le monde, il existe 3 valeurs X, Y et Z. Like this: (5, 45, -12)=Comme ceci : (5, 45, -12) -This refers to the position where X@=5, Y@=45 and Z@=-12. The 3 letters are called “axes” : Y is for the height. X and Z are for the horizontal position.=Cela fait référence à la position où X@=5, Y@=45 et Z@=-12. Les 3 lettres sont appelées "axes" : Y est pour la hauteur. X et Z sont pour la position horizontale. +This refers to the position where X@=5, Y@=45 and Z@=-12. The 3 letters are called “axes”: Y is for the height. X and Z are for the horizontal position.=Cela fait référence à la position où X@=5, Y@=45 et Z@=-12. Les 3 lettres sont appelées “axes” : Y est pour la hauteur. X et Z sont pour la position horizontale. The values for X, Y and Z work like this:=Les valeurs pour X, Y et Z fonctionnent comme ceci: • If you go up, Y increases=• Si vous montez, Y augmente • If you go down, Y decreases=• Si vous descendez, Y diminue diff --git a/mods/HUD/mcl_achievements/locale/mcl_achievements.fr.tr b/mods/HUD/mcl_achievements/locale/mcl_achievements.fr.tr index d9ad699d4..c3fe0fb00 100644 --- a/mods/HUD/mcl_achievements/locale/mcl_achievements.fr.tr +++ b/mods/HUD/mcl_achievements/locale/mcl_achievements.fr.tr @@ -54,9 +54,9 @@ Pick up an Ancient Debris from the floor.=Ramassez un Ancien Débris par terre. The Nether=Le Nether Bring summer clothes.@nHint: Enter the Nether.=Apportez des vêtements d'été.@nAstuce : Entrez dans le Nether Isn't It Iron Pick=Bonne Pioche ! -Craft a iron pickaxe using sticks and iron.=Fabriquez une pioche de fer avec des batons et du fer. +Craft a iron pickaxe using sticks and iron.=Fabriquez une pioche de fer avec des bâtons et du fer. Postmortal=Aux frontières de la mort -Use a Totem of Undying to cheat death.=Utilisez un Totem d'imortalité pour tromper la mort. +Use a Totem of Undying to cheat death.=Utilisez un Totem d’immortalité pour tromper la mort. Sweet Dreams=Bonne nuit les petits Sleep in a bed to change your respawn point.=Dormez dans un lit pour changer votre point de réapparition. Not Quite "Nine" Lives=Presque "neuf" vies @@ -65,6 +65,8 @@ What A Deal!=Adjugé, Vendu ! Successfully trade with a Villager.=Commercez avec succès avec un villageois. Withering Heights=Les Witherables Summon the wither from the dead.=Invoquez le Wither d'entre les morts. +The Cutest Predator=Le plus mignon des prédateurs +Catch an Axolotl with a bucket!=Attrapez un Axolotl avec un seau ! Fishy Business=Merci pour le poisson Catch a fish.@nHint: Catch a fish, salmon, clownfish, or pufferfish.=Attrapez un poisson.@nAstuce : attrapez un poisson, saumon, poisson-clown, ou poisson-globe. Country Lode, Take Me Home=Petit Poucet @@ -79,3 +81,33 @@ Bring Home the Beacon=Fais ta balise Use a beacon.=Utilisez une balise. Beaconator=Phare allumé Use a fully powered beacon.=Utilisez une balise à pleine puissance. +The Next Generation=La nouvelle génération +Hold the Dragon Egg.@nHint: Pick up the egg from the ground and have it in your inventory.=Tenez l'oeuf de dragon.@nAstuce: Ramassez l’œuf sur le sol pour l'avoir dans votre inventaire. +The End... Again...=Un air de déjà vu... +Respawn the Ender Dragon.=Faites réapparaître l'Ender Dragon. +Sky's the Limit=Vers l'infini et au-delà +Find the elytra and prepare to fly above and beyond!=Trouvez des élytres et préparez vous à vous envoler ! +Free the End=Libérez l'End +Kill the ender dragon. Good Luck!=Tuez l'Ender Dragon. Bonne chance ! +Bee Our Guest=J'irai butinez chez vous +Use a campfire to collect a bottle of honey from a beehive without aggrivating the bees inside.=Utilisez un feu de camp pour remplir une bouteille de miel sans provoquez les abeilles. +Total Beelocation=Dé-miel-nagement +Move a bee nest, with 3 bees inside, using a silk touch enchanted tool.=Déplacez une ruche, avec 3 abeilles à l'intérieur en utilisant un outil enchanté avec toucher de soie. +Wax On=Lustrer +Apply honeycomb to a copper block to protect it from the elements.=Étalez de la cire sur un bloc de cuivre pour le protéger des éléments. +Wax Off=Frotter +Scrape wax off of a copper block.=Retirer la cire d'un bloc de cuivre. +The End?=Fin ? +Or the beginning?@nHint: Enter an end portal.=Ou le commencement ?@nAstuce : Entrer dans un portail de l'End. +Stone Age=L'âge de pierre +Mine a stone with new pickaxe.=Minez de la roche avec votre pioche. +Ice Bucket Challenge=Ice Bucket Challenge +Obtain an obsidian block.=Obtenez un bloc d'obsidienne. +Hot Stuff=Chaud devant ! +Put lava in a bucket.=Remplir un seau de lave. +Hero of the Village=Héros du village +Successfully defend a village from a raid=Protégez le village d'un raid +Voluntary Exile=Exil volontaire +Kill a raid captain. Maybe consider staying away from the local villages for the time being...=Tuez un capitaine de pillards. Mieux vaut rester loin des villages pour l'instant... +Tactical Fishing=Pêche tactique +Catch a fish... without a fishing rod!=Attrapez un poisson... sans canne à pêche ! diff --git a/mods/HUD/mcl_achievements/locale/template.txt b/mods/HUD/mcl_achievements/locale/template.txt index 218288ed5..522b7fd09 100644 --- a/mods/HUD/mcl_achievements/locale/template.txt +++ b/mods/HUD/mcl_achievements/locale/template.txt @@ -66,7 +66,7 @@ Successfully trade with a Villager.= Withering Heights= Summon the wither from the dead.= The Cutest Predator= -Catch an Axolotl with a bucket! +Catch an Axolotl with a bucket!= Fishy Business= Catch a fish.@nHint: Catch a fish, salmon, clownfish, or pufferfish.= Country Lode, Take Me Home= @@ -85,7 +85,7 @@ The Next Generation= Hold the Dragon Egg.@nHint: Pick up the egg from the ground and have it in your inventory.= The End... Again...= Respawn the Ender Dragon.= -Sky's The Limit= +Sky's the Limit= Find the elytra and prepare to fly above and beyond!= Free the End= Kill the ender dragon. Good Luck!= @@ -97,3 +97,17 @@ Wax On= Apply honeycomb to a copper block to protect it from the elements.= Wax Off= Scrape wax off of a copper block.= +The End?= +Or the beginning?@nHint: Enter an end portal.= +Stone Age= +Mine a stone with new pickaxe.= +Ice Bucket Challenge= +Obtain an obsidian block.= +Hot Stuff= +Put lava in a bucket.= +Hero of the Village= +Successfully defend a village from a raid= +Voluntary Exile= +Kill a raid captain. Maybe consider staying away from the local villages for the time being...= +Tactical Fishing= +Catch a fish... without a fishing rod!= diff --git a/mods/HUD/mcl_experience/bottle.lua b/mods/HUD/mcl_experience/bottle.lua index 17a70054d..62a3fb9ca 100644 --- a/mods/HUD/mcl_experience/bottle.lua +++ b/mods/HUD/mcl_experience/bottle.lua @@ -50,7 +50,7 @@ local function throw_xp_bottle(pos, dir, velocity) end minetest.register_craftitem("mcl_experience:bottle", { - description = "Bottle o' Enchanting", + description = S("Bottle o' Enchanting"), inventory_image = "mcl_experience_bottle.png", wield_image = "mcl_experience_bottle.png", stack_max = 64, diff --git a/mods/HUD/mcl_experience/locale/mlc_experience.fr.tr b/mods/HUD/mcl_experience/locale/mlc_experience.fr.tr index 0644e2596..faadca410 100644 --- a/mods/HUD/mcl_experience/locale/mlc_experience.fr.tr +++ b/mods/HUD/mcl_experience/locale/mlc_experience.fr.tr @@ -5,3 +5,4 @@ Error: Too many parameters!=Erreur: Trop de paramètres! Error: Incorrect value of XP=Erreur: Valeur incorrecte de XP Error: Player not found=Erreur: Joueur introuvable Added @1 XP to @2, total: @3, experience level: @4=Ajout de @1 XP à @2, total: @3, niveau d'expérience: @4 +Bottle o' Enchanting=Fiole d'expérience diff --git a/mods/HUD/mcl_experience/locale/template.txt b/mods/HUD/mcl_experience/locale/template.txt index a355cbbac..b2a4c04d2 100644 --- a/mods/HUD/mcl_experience/locale/template.txt +++ b/mods/HUD/mcl_experience/locale/template.txt @@ -5,3 +5,4 @@ Error: Too many parameters!= Error: Incorrect value of XP= Error: Player not found= Added @1 XP to @2, total: @3, experience level: @4= +Bottle o' Enchanting= diff --git a/mods/HUD/mcl_inventory/locale/mcl_inventory.fr.tr b/mods/HUD/mcl_inventory/locale/mcl_inventory.fr.tr index afb7dc268..986636f03 100644 --- a/mods/HUD/mcl_inventory/locale/mcl_inventory.fr.tr +++ b/mods/HUD/mcl_inventory/locale/mcl_inventory.fr.tr @@ -19,3 +19,4 @@ Survival Inventory=Inventaire de survie Crafting=Artisanat Inventory=Inventaire @1/@2=@1/@2 +Switch stack size=Changer la quantité maximale par pile diff --git a/mods/HUD/mcl_inventory/locale/template.txt b/mods/HUD/mcl_inventory/locale/template.txt index fcbe68580..9cc687e3f 100644 --- a/mods/HUD/mcl_inventory/locale/template.txt +++ b/mods/HUD/mcl_inventory/locale/template.txt @@ -19,3 +19,4 @@ Survival Inventory= Crafting= Inventory= @1/@2= +Switch stack size= diff --git a/mods/HUD/mcl_ver_info/locale/mcl_ver_info.fr.tr b/mods/HUD/mcl_ver_info/locale/mcl_ver_info.fr.tr new file mode 100644 index 000000000..3e6c9af6d --- /dev/null +++ b/mods/HUD/mcl_ver_info/locale/mcl_ver_info.fr.tr @@ -0,0 +1,2 @@ +# textdomain: mcl_ver_info +Sorry, but your version of Minetest doesn't support the latest API. Please upgrade your minetest.=Désolé, mais votre version de Minetest ne supporte la dernière API. Veuillez mettre à jour minetest. diff --git a/mods/ITEMS/REDSTONE/mcl_dispensers/locale/mcl_dispensers.fr.tr b/mods/ITEMS/REDSTONE/mcl_dispensers/locale/mcl_dispensers.fr.tr index 622d0a70e..04ce1ca63 100644 --- a/mods/ITEMS/REDSTONE/mcl_dispensers/locale/mcl_dispensers.fr.tr +++ b/mods/ITEMS/REDSTONE/mcl_dispensers/locale/mcl_dispensers.fr.tr @@ -1,5 +1,5 @@ # textdomain: mcl_dispensers -Dispenser=Dispenser +Dispenser=Distributeur A dispenser is a block which acts as a redstone component which, when powered with redstone power, dispenses an item. It has a container with 9 inventory slots.=Un distributeur est un bloc qui agit comme un composant redstone qui, lorsqu'il est alimenté avec une puissance redstone, distribue un article. Il a un conteneur avec 9 emplacements d'inventaire. Place the dispenser in one of 6 possible directions. The “hole” is where items will fly out of the dispenser. Use the dispenser to access its inventory. Insert the items you wish to dispense. Supply the dispenser with redstone energy once to dispense a random item.=Placez le distributeur dans l'une des 6 directions possibles. Le "trou" est l'endroit où les articles sortiront du distributeur. Utilisez le distributeur pour accéder à son inventaire. Insérez les articles que vous souhaitez distribuer. Fournissez au distributeur de l'énergie de redstone une fois pour distribuer un objet aléatoire. The dispenser will do different things, depending on the dispensed item:=Le distributeur fera différentes choses, selon l'article distribué: diff --git a/mods/ITEMS/REDSTONE/mesecons_button/locale/mesecons_button.fr.tr b/mods/ITEMS/REDSTONE/mesecons_button/locale/mesecons_button.fr.tr index 5223b97ef..1d844bd36 100644 --- a/mods/ITEMS/REDSTONE/mesecons_button/locale/mesecons_button.fr.tr +++ b/mods/ITEMS/REDSTONE/mesecons_button/locale/mesecons_button.fr.tr @@ -2,12 +2,17 @@ Use the button to push it.=Utilisez le bouton pour le pousser. Stone Button=Bouton de pierre A stone button is a redstone component made out of stone which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1 second.=Un bouton en pierre est un composant Redstone en pierre qui peut être poussé pour fournir de la puissance Redstone. Lorsqu'il est poussé, il alimente les composants Redstone adjacents pendant 1 seconde. +Polished Blackstone Button=Bouton de pierre noire +A polished blackstone button is a redstone component made out of polished blackstone which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1 second.=Un bouton en pierre noire est un composant Redstone en pierre noire qui peut être poussé pour fournir de la puissance Redstone. Lorsqu'il est poussé, il alimente les composants Redstone adjacents pendant 1 seconde. Oak Button=Bouton en chêne Acacia Button=Bouton en acacia Birch Button=Bouton en bouleau Dark Oak Button=Bouton en chêne noir Spruce Button=Bouton en sapin Jungle Button=Bouton en acajou +Mangrove Button=Bouton en palétuvier +Crimson Button=Bouton écarlate +Warped Button=Bouton tordu A wooden button is a redstone component made out of wood which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1.5 seconds. Wooden buttons may also be pushed by arrows.=Un bouton en bois est un composant de redstone en bois qui peut être poussé pour fournir une puissance de redstone. Lorsqu'il est poussé, il alimente les composants Redstone adjacents pendant 1,5 seconde. Les boutons en bois peuvent également être poussés par des flèches. Provides redstone power when pushed=Fournit une puissance de redstone lorsqu'il est poussé Push duration: @1s=Durée de poussée : @1s diff --git a/mods/ITEMS/REDSTONE/mesecons_button/locale/template.txt b/mods/ITEMS/REDSTONE/mesecons_button/locale/template.txt index 421d02b63..4fb2bc19d 100644 --- a/mods/ITEMS/REDSTONE/mesecons_button/locale/template.txt +++ b/mods/ITEMS/REDSTONE/mesecons_button/locale/template.txt @@ -10,6 +10,9 @@ Birch Button= Dark Oak Button= Spruce Button= Jungle Button= +Mangrove Button= +Crimson Button= +Warped Button= A wooden button is a redstone component made out of wood which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1.5 seconds. Wooden buttons may also be pushed by arrows.= Provides redstone power when pushed= Push duration: @1s= diff --git a/mods/ITEMS/REDSTONE/mesecons_noteblock/locale/mesecons_noteblock.fr.tr b/mods/ITEMS/REDSTONE/mesecons_noteblock/locale/mesecons_noteblock.fr.tr index f8d8e3d75..a3ddcb242 100644 --- a/mods/ITEMS/REDSTONE/mesecons_noteblock/locale/mesecons_noteblock.fr.tr +++ b/mods/ITEMS/REDSTONE/mesecons_noteblock/locale/mesecons_noteblock.fr.tr @@ -2,21 +2,21 @@ Note Block=Bloc de notes A note block is a musical block which plays one of many musical notes and different intruments when it is punched or supplied with redstone power.=Un bloc de notes est un bloc musical qui joue l'une des nombreuses notes de musique et différents instruments lorsqu'il est frappé ou alimenté en redstone. Use the note block to choose the next musical note (there are 25 semitones, or 2 octaves). The intrument played depends on the material of the block below the note block:=Utilisez le bloc de notes pour choisir la prochaine note de musique (il y a 25 demi-tons ou 2 octaves). L'instrument joué dépend du matériau du bloc situé sous le bloc de notes: -• Glass: Sticks=• Glass: Sticks -• Wood: Bass guitar=• Bois: Guitare Basse -• Stone: Bass drum=• Pierre: Grosse caisse -• Sand or gravel: Snare drum=• Sable ou gravier: Caisse claire -• Block of Gold: Bell=• Bloc d'OR: Cloche -• Clay: Flute=• Argile: Flûte -• Packed Ice: Chime=• Glace tassée: Carillon -• Wool: Guitar=• Laine: Guitare -• Bone Block: Xylophne=• Bloc osseux: Xylophne -• Block of Iron: Iron xylophne=• Bloc de fer: Xylophone en fer -• Soul Sand: Cow bell=• Soul Sand: Cloche de vache -• Pumpkin: Didgeridoo=• Citrouille: Didgeridoo -• Block of Emerald: Square wave=• Bloc d'émeraude: Onde carrée -• Hay Bale: Banjo=• Hay Bale: Banjo -• Glowstone: Electric piano=• Glowstone: Piano Electrique -• Anything else: Piano=• Autres: Piano +• Glass: Sticks=• Verre : Baguettes +• Wood: Bass guitar=• Bois : Guitare Basse +• Stone: Bass drum=• Pierre : Grosse caisse +• Sand or gravel: Snare drum=• Sable ou gravier : Caisse claire +• Block of Gold: Bell=• Bloc d'OR : Cloche +• Clay: Flute=• Argile : Flûte +• Packed Ice: Chime=• Glace tassée : Carillon +• Wool: Guitar=• Laine : Guitare +• Bone Block: Xylophne=• Bloc osseux : Xylophne +• Block of Iron: Iron xylophne=• Bloc de fer : Xylophone en fer +• Soul Sand: Cow bell=• Soul Sand : Cloche de vache +• Pumpkin: Didgeridoo=• Citrouille : Didgeridoo +• Block of Emerald: Square wave=• Bloc d'émeraude : Onde carrée +• Hay Bale: Banjo=• Hay Bale : Banjo +• Glowstone: Electric piano=• Glowstone : Piano Electrique +• Anything else: Piano=• Autres : Piano The note block will only play a note when it is below air, otherwise, it stays silent.=Le bloc de notes ne jouera une note que lorsqu'il est sous l'air, sinon il reste silencieux. Plays a musical note when powered by redstone power=Joue une note de musique lorsqu'il est alimenté par une puissance redstone diff --git a/mods/ITEMS/REDSTONE/mesecons_pressureplates/locale/mesecons_pressureplates.fr.tr b/mods/ITEMS/REDSTONE/mesecons_pressureplates/locale/mesecons_pressureplates.fr.tr index 2007ec785..630ebdd48 100644 --- a/mods/ITEMS/REDSTONE/mesecons_pressureplates/locale/mesecons_pressureplates.fr.tr +++ b/mods/ITEMS/REDSTONE/mesecons_pressureplates/locale/mesecons_pressureplates.fr.tr @@ -6,7 +6,12 @@ Birch Pressure Plate=Plaque de pression en bouleau Dark Oak Pressure Plate=Plaque de pression en chêne noir Spruce Pressure Plate=Plaque de pression en sapin Jungle Pressure Plate=Plaque de pression en acajou +Mangrove Pressure Plate=Plaque de pression en palétuvier +Crimson Pressure Plate=Plaque de pression écarlate +Warped Pressure Plate=Plaque de pression tordue A wooden pressure plate is a redstone component which supplies its surrounding blocks with redstone power while any movable object (including dropped items, players and mobs) rests on top of it.=Une plaque de pression en bois est un composant de redstone qui alimente ses blocs environnants en puissance de redstone tandis que tout objet mobile (y compris les objets lâchés, les joueurs et les mobs) repose dessus. +Polished Blackstone Pressure Plate=Plaque de pression en pierre noire +A polished blackstone pressure plate is a redstone component which supplies its surrounding blocks with redstone power while a player or mob stands on top of it. It is not triggered by anything else.=Une plaque de pression en pierre noire est un composant de redstone qui alimente ses blocs environnants en puissance de redstone pendant qu'un joueur ou un mob se tient au-dessus. Il n'est déclenché par rien d'autre. Stone Pressure Plate=Plaque de pression en pierre A stone pressure plate is a redstone component which supplies its surrounding blocks with redstone power while a player or mob stands on top of it. It is not triggered by anything else.=Une plaque de pression en pierre est un composant de redstone qui alimente ses blocs environnants en puissance de redstone pendant qu'un joueur ou un mob se tient au-dessus. Il n'est déclenché par rien d'autre. Provides redstone power when pushed=Fournit une puissance de redstone lorsqu'il est poussé diff --git a/mods/ITEMS/REDSTONE/mesecons_pressureplates/locale/template.txt b/mods/ITEMS/REDSTONE/mesecons_pressureplates/locale/template.txt index 1239dd668..061d82410 100644 --- a/mods/ITEMS/REDSTONE/mesecons_pressureplates/locale/template.txt +++ b/mods/ITEMS/REDSTONE/mesecons_pressureplates/locale/template.txt @@ -6,6 +6,9 @@ Birch Pressure Plate= Dark Oak Pressure Plate= Spruce Pressure Plate= Jungle Pressure Plate= +Mangrove Pressure Plate= +Crimson Pressure Plate= +Warped Pressure Plate= A wooden pressure plate is a redstone component which supplies its surrounding blocks with redstone power while any movable object (including dropped items, players and mobs) rests on top of it.= Polished Blackstone Pressure Plate= A polished blackstone pressure plate is a redstone component which supplies its surrounding blocks with redstone power while a player or mob stands on top of it. It is not triggered by anything else.= diff --git a/mods/ITEMS/mcl_armor/locale/mcl_armor.fr.tr b/mods/ITEMS/mcl_armor/locale/mcl_armor.fr.tr index 7663e2b40..b3a2c6dbc 100644 --- a/mods/ITEMS/mcl_armor/locale/mcl_armor.fr.tr +++ b/mods/ITEMS/mcl_armor/locale/mcl_armor.fr.tr @@ -6,25 +6,25 @@ Iron Helmet=Casque de fer Golden Helmet=Casque d'or Diamond Helmet=Casque de diamant Chain Helmet=Casque de mailles -Netherite Helmet=Casque de Netherite +Netherite Helmet=Casque de netherite Leather Tunic=Tunique en cuir Iron Chestplate=Plastron de fer Golden Chestplate=Plastron d'or Diamond Chestplate=Plastron de diamant Chain Chestplate=Cotte de mailles -Netherite Chestplate=Plastron de Netherite +Netherite Chestplate=Plastron de netherite Leather Pants=Pantalon de cuir Iron Leggings=Jambières de fer Golden Leggings=Jambières d'or Diamond Leggings=Jambières de diamant Chain Leggings=Jambières de mailles -Netherite Leggings=Jambières de Netherite +Netherite Leggings=Jambières de netherite Leather Boots=Bottes de cuir Iron Boots=Bottes de fer Golden Boots=Bottes d'or Diamond Boots=Bottes de diamant Chain Boots=Bottes de mailles -Netherite Boots=Bottes de Netherite +Netherite Boots=Bottes de netherite Elytra=Élytres #Translations of enchantements diff --git a/mods/ITEMS/mcl_armor_stand/locale/mcl_armor_stand.fr.tr b/mods/ITEMS/mcl_armor_stand/locale/mcl_armor_stand.fr.tr index 867b3f043..b52038fe7 100644 --- a/mods/ITEMS/mcl_armor_stand/locale/mcl_armor_stand.fr.tr +++ b/mods/ITEMS/mcl_armor_stand/locale/mcl_armor_stand.fr.tr @@ -2,4 +2,4 @@ Armor Stand=Support d'armure An armor stand is a decorative object which can display different pieces of armor. Anything which players can wear as armor can also be put on an armor stand.=Un support d'armure est un objet décoratif qui peut afficher différentes pièces d'armure. Tout ce que les joueurs peuvent porter comme armure peut également être placé sur un support d'armure. Just place an armor item on the armor stand. To take the top piece of armor from the armor stand, select your hand and use the place key on the armor stand.=Placez simplement un objet d'armure sur le support d'armure. Pour prendre la pièce d'armure du support d'armure, sélectionnez votre main et utilisez la touche "Placer" sur le support d'armure. -Displays pieces of armor=Displays pieces of armor +Displays pieces of armor=Expose des pièces d'armure diff --git a/mods/ITEMS/mcl_bamboo/bamboo_base.lua b/mods/ITEMS/mcl_bamboo/bamboo_base.lua index 66ed9a5ca..b9f67fc64 100644 --- a/mods/ITEMS/mcl_bamboo/bamboo_base.lua +++ b/mods/ITEMS/mcl_bamboo/bamboo_base.lua @@ -25,7 +25,7 @@ end -- basic bamboo nodes. local bamboo_def = { - description = "Bamboo", + description = S("Bamboo"), tiles = {"mcl_bamboo_bamboo_bottom.png", "mcl_bamboo_bamboo_bottom.png", "mcl_bamboo_bamboo.png"}, drawtype = "nodebox", paramtype = "light", @@ -266,7 +266,7 @@ end minetest.register_node(BAMBOO_ENDCAP_NAME, bamboo_top) local bamboo_block_def = { - description = "Bamboo Block", + description = S("Bamboo Block"), tiles = {"mcl_bamboo_bamboo_bottom.png", "mcl_bamboo_bamboo_bottom.png", "mcl_bamboo_bamboo_block.png"}, groups = {handy = 1, building_block = 1, axey = 1, flammable = 2, material_wood = 1, bamboo_block = 1, fire_encouragement = 5, fire_flammability = 5}, sounds = node_sound, diff --git a/mods/ITEMS/mcl_bamboo/locale/mcl_bamboo.fr.tr b/mods/ITEMS/mcl_bamboo/locale/mcl_bamboo.fr.tr new file mode 100644 index 000000000..953d08811 --- /dev/null +++ b/mods/ITEMS/mcl_bamboo/locale/mcl_bamboo.fr.tr @@ -0,0 +1,45 @@ +# textdomain: mcl_bamboo + +### bamboo_base.lua ### + +Bamboo=Bambou +Bamboo Mosaic Plank=Planche mosaïque de bambou +Bamboo Plank=Planche de bambou +Stripped Bamboo Block=Bloc de bambou écorcé +Bamboo Block=Bloc de bambou + +### bamboo_items.lua ### + +A bamboo button is a redstone component made out of stone which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1 second.=Un bouton en bambou est un composant redstone fait de bamboo qui peut être poussé pour fournir un signal redstone. Lorsque poussé, il alimente les composants redstone adjacents pendant 1 seconde. + +A wooden pressure plate is a redstone component which supplies its surrounding blocks with redstone power while any movable object (including dropped items, players and mobs) rests on top of it.=Une plaque de pression en bois est un composant redstone qui envoie un signal aux blocs alentours lorsque n'importe quel objet mobile (objet jeté, joueurs et mobs) sont dessus. + +Bamboo=Bambou +Bamboo Button=Bouton en bambou +Bamboo Door=Porte de bambou +Bamboo Fence=Barrière de bambou +Bamboo Fence Gate=Portillon de bambou +Bamboo Mosaic Slab=Dalle mosaïque de bambou +Bamboo Mosaic Stair=Escalier mosaïque de bambou +Bamboo Plank Slab=Dalle de planches de bambou +Bamboo Plank Stair=Escalier de planches de bambou +Bamboo Pressure Plate=Plaque de pression de bambou +Bamboo Slab=Dalle de bambou +Bamboo Stair=Escalier de bambou +Bamboo Trapdoor=Trappe de bambou +Double Bamboo Mosaic Slab=Double dalle mosaïque de bambou +Double Bamboo Plank Slab=Double dalle de planches de bambou +Double Bamboo Slab=Double dalle de bambou +Double Stripped Bamboo Slab=Double dalle de bambou écorcée +Scaffolding=Échafaudage +Scaffolding (horizontal)=Échafaudage (horizontal) +Scaffolding block used to climb up or out across areas.=Les blocs d'échafaudage servent à escalader ou à sortir d'une zone. +Stripped Bamboo Slab=Dalle de bambou écorcée +Stripped Bamboo Stair=Escalier de bambou écorcée + +To open or close the trapdoor, rightclick it or send a redstone signal to it.=Pour ouvrir ou fermer la trappe, cliquer droit ou lui envoyer un signal redstone. + +Wooden trapdoors are horizontal barriers which can be opened and closed by hand or a redstone signal. They occupy the upper or lower part of a block, depending on how they have been placed. When open, they can be climbed like a ladder.=Les trappes de bois sont des barrières horizontales qui peuvent être ouvertes et fermées à la main ou par un signal redstone. Lorsqu'elles sont ouvertes, elles peuvent êtres escaladées comme une échelle. + +Wooden doors are 2-block high barriers which can be opened or closed by hand and by a redstone signal.=Les portes en bois sont des barrières hautes à 2 blocs qui peuvent être ouvertes ou fermées à la main et par un signal redstone. +To open or close a wooden door, rightclick it or supply its lower half with a redstone signal.=Pour ouvrir ou fermer une porte en bois, faites un clic droit dessus ou fournissez à sa moitié inférieure un signal redstone. diff --git a/mods/ITEMS/mcl_bamboo/locale/template.txt b/mods/ITEMS/mcl_bamboo/locale/template.txt index ad8e7cb5b..2d5c69383 100644 --- a/mods/ITEMS/mcl_bamboo/locale/template.txt +++ b/mods/ITEMS/mcl_bamboo/locale/template.txt @@ -2,9 +2,11 @@ ### bamboo_base.lua ### +Bamboo= Bamboo Mosaic Plank= Bamboo Plank= Stripped Bamboo Block= +Bamboo Block= ### bamboo_items.lua ### @@ -38,3 +40,6 @@ Stripped Bamboo Stair= To open or close the trapdoor, rightclick it or send a redstone signal to it.= Wooden trapdoors are horizontal barriers which can be opened and closed by hand or a redstone signal. They occupy the upper or lower part of a block, depending on how they have been placed. When open, they can be climbed like a ladder.= + +Wooden doors are 2-block high barriers which can be opened or closed by hand and by a redstone signal.= +To open or close a wooden door, rightclick it or supply its lower half with a redstone signal.= diff --git a/mods/ITEMS/mcl_banners/locale/mcl_banners.fr.tr b/mods/ITEMS/mcl_banners/locale/mcl_banners.fr.tr index 48b25f708..78095a4a7 100644 --- a/mods/ITEMS/mcl_banners/locale/mcl_banners.fr.tr +++ b/mods/ITEMS/mcl_banners/locale/mcl_banners.fr.tr @@ -31,6 +31,7 @@ Lime Banner=Bannière vert Clair Lime=Vert clair Light Blue Banner=Bannière bleue clair Light Blue=Bleu clair +Banner=Bannière Banners are tall colorful decorative blocks. They can be placed on the floor and at walls. Banners can be emblazoned with a variety of patterns using a lot of dye in crafting.=Les bannières sont de grands blocs décoratifs colorés. Ils peuvent être placés au sol et aux murs. Les bannières peuvent arborées une variété de motifs en utilisant beaucoup de colorant dans l'artisanat. Use crafting to draw a pattern on top of the banner. Emblazoned banners can be emblazoned again to combine various patterns. You can draw up to 12 layers on a banner that way. If the banner includes a gradient, only 3 layers are possible.=Utilisez l'artisanat pour dessiner un motif sur le dessus de la bannière. Les bannières blasonnées peuvent être à nouveau blasonnées pour combiner différents motifs. Vous pouvez dessiner jusqu'à 12 couches sur une bannière de cette façon. Si la bannière comprend un dégradé, seulement 3 couches sont possibles. You can copy the pattern of a banner by placing two banners of the same color in the crafting grid—one needs to be emblazoned, the other one must be clean. Finally, you can use a banner on a cauldron with water to wash off its top-most layer.=Vous pouvez copier le motif d'une bannière en plaçant deux bannières de la même couleur dans la grille de fabrication: l'une doit être décorée, l'autre doit être propre. Enfin, vous pouvez utiliser une bannière sur un chaudron avec de l'eau pour laver sa couche la plus haute. diff --git a/mods/ITEMS/mcl_banners/locale/template.txt b/mods/ITEMS/mcl_banners/locale/template.txt index cb8ec0b0c..357ff6b08 100644 --- a/mods/ITEMS/mcl_banners/locale/template.txt +++ b/mods/ITEMS/mcl_banners/locale/template.txt @@ -31,6 +31,7 @@ Lime Banner= Lime= Light Blue Banner= Light Blue= +Banner= Banners are tall colorful decorative blocks. They can be placed on the floor and at walls. Banners can be emblazoned with a variety of patterns using a lot of dye in crafting.= Use crafting to draw a pattern on top of the banner. Emblazoned banners can be emblazoned again to combine various patterns. You can draw up to 12 layers on a banner that way. If the banner includes a gradient, only 3 layers are possible.= You can copy the pattern of a banner by placing two banners of the same color in the crafting grid—one needs to be emblazoned, the other one must be clean. Finally, you can use a banner on a cauldron with water to wash off its top-most layer.= diff --git a/mods/ITEMS/mcl_beehives/locale/mcl_beehives.fr.tr b/mods/ITEMS/mcl_beehives/locale/mcl_beehives.fr.tr new file mode 100644 index 000000000..45e66fa12 --- /dev/null +++ b/mods/ITEMS/mcl_beehives/locale/mcl_beehives.fr.tr @@ -0,0 +1,5 @@ +# textdomain: mcl_beehives +Beehive=Ruche +Artificial bee nest.=Ruche artificielle. +Bee Nest=Nid d'abeilles +A naturally generating block that houses bees and a tasty treat...if you can get it.=Un bloc généré naturellement qui héberge les abeilles et une délicieuse friandise... Si vous pouvez la récupérer. diff --git a/mods/ITEMS/mcl_beehives/locale/mcl_beehives.ja.tr b/mods/ITEMS/mcl_beehives/locale/mcl_beehives.ja.tr index a07e44376..273cefae8 100644 --- a/mods/ITEMS/mcl_beehives/locale/mcl_beehives.ja.tr +++ b/mods/ITEMS/mcl_beehives/locale/mcl_beehives.ja.tr @@ -1,4 +1,5 @@ +# textdomain: mcl_beehives Beehive=養蜂箱 Artificial bee nest.=人工的なハチの巣です。 Bee Nest=ハチの巣 -A naturally generating block that houses bees and a tasty treat...if you can get it.=ミツバチの住処となっている自然生成ブロックで、美味しいおやつが収まっています…手に入れられれば。 \ No newline at end of file +A naturally generating block that houses bees and a tasty treat...if you can get it.=ミツバチの住処となっている自然生成ブロックで、美味しいおやつが収まっています…手に入れられれば。 diff --git a/mods/ITEMS/mcl_beehives/locale/template.txt b/mods/ITEMS/mcl_beehives/locale/template.txt index 135786c7c..ff4be403c 100644 --- a/mods/ITEMS/mcl_beehives/locale/template.txt +++ b/mods/ITEMS/mcl_beehives/locale/template.txt @@ -1,4 +1,5 @@ +# textdomain: mcl_beehives Beehive= Artificial bee nest.= Bee Nest= -A naturally generating block that houses bees and a tasty treat...if you can get it.= \ No newline at end of file +A naturally generating block that houses bees and a tasty treat...if you can get it.= diff --git a/mods/ITEMS/mcl_blackstone/locale/mcl_blackstone.fr.tr b/mods/ITEMS/mcl_blackstone/locale/mcl_blackstone.fr.tr index a13d5c34a..65d52d8a9 100644 --- a/mods/ITEMS/mcl_blackstone/locale/mcl_blackstone.fr.tr +++ b/mods/ITEMS/mcl_blackstone/locale/mcl_blackstone.fr.tr @@ -15,6 +15,7 @@ Chiseled Polished Blackstone Stair=Escalier de pierre noire sculptée Polished Blackstone Brick Stair=Escalier de briques de pierre noire Quartz Bricks=Briques de quartz Soul Torch=Torche des âmes +Torches are light sources which can be placed at the side or on the top of most blocks.=Les torches sont des sources lumineuses qui peuvent être placées sur le côté ou sur le dessus de la plupart des blocs. Soul Lantern=Lanterne des âmes Soul Soil=Terre des âmes Eternal Soul Fire=Feu éternel des âmes diff --git a/mods/ITEMS/mcl_blackstone/locale/template.txt b/mods/ITEMS/mcl_blackstone/locale/template.txt index ff54c9fb5..54b1be346 100644 --- a/mods/ITEMS/mcl_blackstone/locale/template.txt +++ b/mods/ITEMS/mcl_blackstone/locale/template.txt @@ -15,6 +15,7 @@ Chiseled Polished Blackstone Stair= Polished Blackstone Brick Stair= Quartz Bricks= Soul Torch= +Torches are light sources which can be placed at the side or on the top of most blocks.= Soul Lantern= Soul Soil= Eternal Soul Fire= @@ -25,4 +26,4 @@ Blackstone Wall= Double Blackstone Slab= Polished Double Blackstone Slab= Double Chiseled Polished Blackstone Slab= -Double Polished Blackstone Brick Slab= \ No newline at end of file +Double Polished Blackstone Brick Slab= diff --git a/mods/ITEMS/mcl_blast_furnace/init.lua b/mods/ITEMS/mcl_blast_furnace/init.lua index b8bbe001f..e8e6e81c8 100644 --- a/mods/ITEMS/mcl_blast_furnace/init.lua +++ b/mods/ITEMS/mcl_blast_furnace/init.lua @@ -415,14 +415,12 @@ end minetest.register_node("mcl_blast_furnace:blast_furnace", { description = S("Blast Furnace"), _tt_help = S("Smelts ores faster than furnace"), - _doc_items_longdesc = S("Blast Furnaces smelt several items, mainly ores and armor, using a furnace fuel, into something else."), + _doc_items_longdesc = S("Blast Furnaces smelt several items, mainly ores and armor, using a furnace fuel, but twice as fast as a normal furnace."), _doc_items_usagehelp = - S([[ - Use the furnace to open the furnace menu. - Place a furnace fuel in the lower slot and the source material in the upper slot. - The furnace will slowly use its fuel to smelt the item. - The result will be placed into the output slot at the right side. - ]]).."\n".. + S("Use the blast furnace to open the furnace menu.").."\n".. + S("Place a furnace fuel in the lower slot and the source material in the upper slot.").."\n".. + S("The blast furnace will slowly use its fuel to smelt the item.").."\n".. + S("The result will be placed into the output slot at the right side.").."\n".. S("Use the recipe book to see what ores you can smelt, what you can use as fuel and how long it will burn."), _doc_items_hidden = false, tiles = { diff --git a/mods/ITEMS/mcl_blast_furnace/locale/mcl_blast_furnace.fr.tr b/mods/ITEMS/mcl_blast_furnace/locale/mcl_blast_furnace.fr.tr index 2b716d27a..a6c6a8de3 100644 --- a/mods/ITEMS/mcl_blast_furnace/locale/mcl_blast_furnace.fr.tr +++ b/mods/ITEMS/mcl_blast_furnace/locale/mcl_blast_furnace.fr.tr @@ -2,7 +2,10 @@ Inventory=Inventaire Blast Furnace=Haut fourneau Smelts ores faster than furnace=Fond le minerai plus vite que le four -Use the recipe book to see what you can smelt, what you can use as fuel and how long it will burn.=Utiliser le livre de recettes pour voir ce que vous pouvez fondre, ce que vous pouvez utiliser comme combustible et combien de temps ça va brûler. -Use the furnace to open the furnace menu.\nPlace a furnace fuel in the lower slot and the source material in the upper slot.\nThe furnace will slowly use its fuel to smelt the item.\nThe result will be placed into the output slot at the right side.=Utiliser le fourneau pour ouvrir le menu.\nPlacer le combustible dans la case en bas et le matériau source dans la case du haut.\nLe fourneau utilisera son combustible pour fondre lentement l'objet.\nLe résultat sera placé dans la case de sortie à droite. -Blast Furnaces smelt several items, mainly ores and armor, using a furnace fuel, into something else.=Les hauts fourneaux fondent plusieurs objets, principalement du minerai et des pièces d'armure, en quelque chose d'autre. +Use the recipe book to see what ores you can smelt, what you can use as fuel and how long it will burn.=Utiliser le livre de recettes pour voir quels minerais vous pouvez fondre, ce que vous pouvez utiliser comme combustible et combien de temps ça va brûler. +Use the blast furnace to open the furnace menu.=Utiliser le haut fourneau pour ouvrir le menu. +Place a furnace fuel in the lower slot and the source material in the upper slot.=Placer le combustible dans la case en bas et le matériau source dans la case du haut. +The blast furnace will slowly use its fuel to smelt the item.=Le haut fourneau utilisera son combustible pour fondre lentement l'objet. +The result will be placed into the output slot at the right side.=Le résultat sera placé dans la case de sortie à droite. +Blast Furnaces smelt several items, mainly ores and armor, using a furnace fuel, but twice as fast as a normal furnace.=Les hauts fourneaux fondent plusieurs objets, principalement du minerai et des pièces d'armure, mais deux fois plus vite qu'un fourneau normal. Active Blast Furnace=Haut fourneau actif diff --git a/mods/ITEMS/mcl_blast_furnace/locale/template.txt b/mods/ITEMS/mcl_blast_furnace/locale/template.txt index 1c30844d8..46841046d 100644 --- a/mods/ITEMS/mcl_blast_furnace/locale/template.txt +++ b/mods/ITEMS/mcl_blast_furnace/locale/template.txt @@ -2,7 +2,10 @@ Inventory= Blast Furnace= Smelts ores faster than furnace= -Use the recipe book to see what you can smelt, what you can use as fuel and how long it will burn.= -Use the furnace to open the furnace menu.\nPlace a furnace fuel in the lower slot and the source material in the upper slot.\nThe furnace will slowly use its fuel to smelt the item.\nThe result will be placed into the output slot at the right side.= -Blast Furnaces smelt several items, mainly ores and armor, using a furnace fuel, into something else.= -Active Blast Furnace= \ No newline at end of file +Use the recipe book to see what ores you can smelt, what you can use as fuel and how long it will burn.= +Use the blast furnace to open the furnace menu.= +Place a furnace fuel in the lower slot and the source material in the upper slot.= +The blast furnace will slowly use its fuel to smelt the item.= +The result will be placed into the output slot at the right side.= +Blast Furnaces smelt several items, mainly ores and armor, using a furnace fuel, but twice as fast as a normal furnace.= +Active Blast Furnace= diff --git a/mods/ITEMS/mcl_buckets/locale/mcl_buckets.fr.tr b/mods/ITEMS/mcl_buckets/locale/mcl_buckets.fr.tr index 79a9d9d6d..62fdba15a 100644 --- a/mods/ITEMS/mcl_buckets/locale/mcl_buckets.fr.tr +++ b/mods/ITEMS/mcl_buckets/locale/mcl_buckets.fr.tr @@ -15,10 +15,11 @@ Collects liquids=Collecte des liquides Places a lava source=Place une source de lave Places a water source=Place une source d'eau Places a river water source=Place une source d'eau de rivière +Axolotl=Axolotl Cod=Morue Salmon=Saumon Tropical Fish=Poisson tropical Bucket of @1=Seau de @1 This bucket is filled with water and @1.=Ce seau est rempli d'eau et de @1. -Place it to empty the bucket and place a @1. Obtain by right clicking on a @2 fish with a bucket of water.=Le placer pour vider le seau et placer un @1. S'obtient en faisant un clic droit sur un poisson @2 avec un seau d'eau. -Places a water source and a @1 fish.=Placer une source d'eau et un poisson @1. +Place it to empty the bucket and place a @1. Obtain by right clicking on a @2 with a bucket of water.=Le placer pour vider le seau et placer un @1. S'obtient en faisant un clic droit sur un @2 avec un seau d'eau. +Places a water source and a @1.=Placer une source d'eau et un @1. diff --git a/mods/ITEMS/mcl_cauldrons/init.lua b/mods/ITEMS/mcl_cauldrons/init.lua index 44bbebc22..c84e3bb88 100644 --- a/mods/ITEMS/mcl_cauldrons/init.lua +++ b/mods/ITEMS/mcl_cauldrons/init.lua @@ -40,8 +40,8 @@ end minetest.register_node("mcl_cauldrons:cauldron", { description = S("Cauldron"), _tt_help = S("Stores water"), - _doc_items_longdesc = S("Cauldrons are used to store water and slowly fill up under rain."), - _doc_items_usagehelp = S("Place a water bucket into the cauldron to fill it with water. Place an empty bucket on a full cauldron to retrieve the water. Place a water bottle into the cauldron to fill the cauldron to one third with water. Place a glass bottle in a cauldron with water to retrieve one third of the water."), + _doc_items_longdesc = S("Cauldrons are used to store water and slowly fill up under rain. They can also be used to wash off banners."), + _doc_items_usagehelp = S("Place a water bucket into the cauldron to fill it with water. Place an empty bucket on a full cauldron to retrieve the water. Place a water bottle into the cauldron to fill the cauldron to one third with water. Place a glass bottle in a cauldron with water to retrieve one third of the water. Use an emblazoned banner on a cauldron with water to wash off its top layer."), wield_image = "mcl_cauldrons_cauldron.png", inventory_image = "mcl_cauldrons_cauldron.png", use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, diff --git a/mods/ITEMS/mcl_compass/locale/mcl_compass.fr.tr b/mods/ITEMS/mcl_compass/locale/mcl_compass.fr.tr index 77d249087..87dc31650 100644 --- a/mods/ITEMS/mcl_compass/locale/mcl_compass.fr.tr +++ b/mods/ITEMS/mcl_compass/locale/mcl_compass.fr.tr @@ -7,4 +7,8 @@ Lodestone Compass=Boussole magnétisée Points to a lodestone=Pointe vers une magnétite Lodestone compasses resemble regular compasses, but they point to a specific lodestone.=Les boussoles magnétisées ressemblent à des boussoles normales, mais pointent vers une magnétite spécifique. A Lodestone compass can be made from an ordinary compass by using it on a lodestone. After becoming a lodestone compass, it always points to its linked lodestone, provided that they are in the same dimension. If not in the same dimension, the lodestone compass spins randomly, similarly to a regular compass when outside the overworld. A lodestone compass can be relinked with another lodestone.=Une boussole magnétisée peut être crée à partir d'une boussole normale en l'utilisant sur une magnétite. Après être devenue une boussole magnétisée, elle pointera toujours vers sa magnétite liée, pourvu qu'elle soit dans la même dimension. Si ce n'est pas le cas, la boussole magnétisée tourne au hasard, comme une boussole normale hors de l'overworld. Une boussole magnétisée peut être liée à une autre magnétite. -Lodestone=Magnétite \ No newline at end of file +Lodestone=Magnétite +Recovery Compass=Boussole de récupération +Points to your last death location=Pointe vers le lieu de votre dernière mort +Recovery Compasses are compasses that point to your last death location=Les boussoles de récupération sont des boussoles qui pointent vers le lieu de votre dernière mort +Recovery Compasses always point to the location of your last death, in case you haven't died yet, it will just randomly spin around=Les boussoles de récupération pointent toujours vers le lieu de votre dernière mort, si vous n'êtes jamais mort, elle va juste tourner aléatoirement diff --git a/mods/ITEMS/mcl_compass/locale/template.txt b/mods/ITEMS/mcl_compass/locale/template.txt index f41485dea..e1b7ae7f9 100644 --- a/mods/ITEMS/mcl_compass/locale/template.txt +++ b/mods/ITEMS/mcl_compass/locale/template.txt @@ -8,3 +8,7 @@ Points to a lodestone= Lodestone compasses resemble regular compasses, but they point to a specific lodestone.= A Lodestone compass can be made from an ordinary compass by using it on a lodestone. After becoming a lodestone compass, it always points to its linked lodestone, provided that they are in the same dimension. If not in the same dimension, the lodestone compass spins randomly, similarly to a regular compass when outside the overworld. A lodestone compass can be relinked with another lodestone.= Lodestone= +Recovery Compass= +Points to your last death location= +Recovery Compasses are compasses that point to your last death location= +Recovery Compasses always point to the location of your last death, in case you haven't died yet, it will just randomly spin around= diff --git a/mods/ITEMS/mcl_composters/locale/mcl_composters.fr.tr b/mods/ITEMS/mcl_composters/locale/mcl_composters.fr.tr index 66a72bf38..0f4e665e6 100644 --- a/mods/ITEMS/mcl_composters/locale/mcl_composters.fr.tr +++ b/mods/ITEMS/mcl_composters/locale/mcl_composters.fr.tr @@ -1,7 +1,7 @@ # textdomain: mcl_composters Composter=Composteur Composters can convert various organic items into bonemeal.=Les composteurs peuvent convertir divers objets organiques en farine d'os. -Use organic items on the composter to fill it with layers of compost. Every time an item is put in the composter, there is a chance that the composter adds another layer of compost. Some items have a bigger chance of adding an extra layer than other items. After filling up with 7 layers of compost, the composter is full. After a delay of approximately one second the composter becomes ready and bone meal can be retrieved from it. Right-clicking the composter takes out the bone meal empties the composter."=Utiliser des objets organiques sur le composteur pour le remplir de couches de compost. Chaque fois qu'un objet est mis dans le composteur, il y a une chance d'ajouter une nouvelle couche de compost au composteur. Certains objets ont une plus grande chance que d'autres d'ajouter une couche supplémentaire. Après l'avoir rempli de 7 couches de compost, le composteur est plein. Après un délai d'approximativement une seconde, le composteur est prêt et on peut récupérer la farine d'os. Cliquer droit le composteur permet de récupérer la farine d'os et de vider le composteur. +Use organic items on the composter to fill it with layers of compost. Every time an item is put in the composter, there is a chance that the composter adds another layer of compost. Some items have a bigger chance of adding an extra layer than other items. After filling up with 7 layers of compost, the composter is full. After a delay of approximately one second the composter becomes ready and bone meal can be retrieved from it. Right-clicking the composter takes out the bone meal empties the composter.=Utiliser des objets organiques sur le composteur pour le remplir de couches de compost. Chaque fois qu'un objet est mis dans le composteur, il y a une chance d'ajouter une nouvelle couche de compost au composteur. Certains objets ont une plus grande chance que d'autres d'ajouter une couche supplémentaire. Après l'avoir rempli de 7 couches de compost, le composteur est plein. Après un délai d'approximativement une seconde, le composteur est prêt et on peut récupérer la farine d'os. Cliquer droit le composteur permet de récupérer la farine d'os et de vider le composteur. filled=rempli ready for harvest=prêt pour la récolte Converts organic items into bonemeal=Convertit les objets organiques en farine d'os. diff --git a/mods/ITEMS/mcl_composters/locale/template.txt b/mods/ITEMS/mcl_composters/locale/template.txt index c5f9bb858..f3329719a 100644 --- a/mods/ITEMS/mcl_composters/locale/template.txt +++ b/mods/ITEMS/mcl_composters/locale/template.txt @@ -1,7 +1,7 @@ # textdomain: mcl_composters Composter= Composters can convert various organic items into bonemeal.= -Use organic items on the composter to fill it with layers of compost. Every time an item is put in the composter, there is a chance that the composter adds another layer of compost. Some items have a bigger chance of adding an extra layer than other items. After filling up with 7 layers of compost, the composter is full. After a delay of approximately one second the composter becomes ready and bone meal can be retrieved from it. Right-clicking the composter takes out the bone meal empties the composter."= +Use organic items on the composter to fill it with layers of compost. Every time an item is put in the composter, there is a chance that the composter adds another layer of compost. Some items have a bigger chance of adding an extra layer than other items. After filling up with 7 layers of compost, the composter is full. After a delay of approximately one second the composter becomes ready and bone meal can be retrieved from it. Right-clicking the composter takes out the bone meal empties the composter.= filled= ready for harvest= Converts organic items into bonemeal= diff --git a/mods/ITEMS/mcl_copper/locale/mcl_copper.fr.tr b/mods/ITEMS/mcl_copper/locale/mcl_copper.fr.tr index 1efae66ee..a2fb94c36 100644 --- a/mods/ITEMS/mcl_copper/locale/mcl_copper.fr.tr +++ b/mods/ITEMS/mcl_copper/locale/mcl_copper.fr.tr @@ -2,36 +2,56 @@ A block of copper is mostly a decorative block.=Le bloc de cuivre est surtout un bloc décoratif. A block used for compact raw copper storage.=Un bloc utilisé pour le stockage compact de cuivre brut. Block of Copper=Bloc de cuivre +Waxed Block of Copper=Bloc de cuivre ciré Block of Raw Copper=Bloc de cuivre brut Copper Ingot=Lingot de cuivre Copper Ore=Minerai de cuivre Cut copper is a decorative block.=Le cuivre taillé est un bloc décoratif. Cut Copper=Cuivre taillé +Waxed Cut Copper=Cuivre taillé ciré Double Slab of Cut Copper=Double dalle de cuivre taillé Double Slab of Exposed Cut Copper=Double dalle de cuivre taillé exposé Double Slab of Oxidized Cut Copper=Double dalle de cuivre taillé oxydé Double Slab of Weathered Cut Copper=Double dalle de cuivre taillé érodé +Waxed Double Slab of Cut Copper=Double dalle de cuivre taillé ciré +Waxed Double Slab of Exposed Cut Copper=Double dalle de cuivre taillé exposé ciré +Waxed Double Slab of Oxidized Cut Copper=Double dalle de cuivre taillé oxydé ciré +Waxed Double Slab of Weathered Cut Copper=Double dalle de cuivre taillé érodé ciré Exposed copper is a decorative block.=Le cuivre exposé est un bloc décoratif. Exposed Copper=Cuivre exposé +Waxed Exposed Copper=Cuivre exposé ciré Exposed cut copper is a decorative block.=Le cuivre taillé exposé est un bloc décoratif. Exposed Cut Copper=Cuivre taillé exposé +Waxed Exposed Cut Copper=Cuivre taillé exposé ciré Molten Raw Copper. It is used to craft blocks.=Cuivre brut fondu. Utilisé pour fabriquer des blocs. Oxidized copper is a decorative block.=Le cuivre oxydé est un bloc décoratif. Oxidized Copper=Cuivre oxydé +Waxed Oxidized Copper=Cuivre oxydé ciré Oxidized cut copper is a decorative block.=Le cuivre taillé oxydé est un bloc décoratif. Oxidized Cut Copper=Cuivre taillé oxydé +Waxed Oxidized Cut Copper=Cuivre taillé oxydé ciré Raw Copper. Mine a Copper Ore to get it.=Cuivre brut. Creuser dans du minerai de cuivre pour l'obtenir. Raw Copper=Cuivre brut Slab of Cut Copper=Dalle de cuivre taillé Slab of Exposed Cut Copper=Dalle de cuivre taillé exposé Slab of Oxidized Cut Copper=Dalle de cuivre taillé oxydé Slab of Weathered Cut Copper=Dalle de cuivre taillé érodé +Waxed Slab of Cut Copper=Dalle de cuivre taillé ciré +Waxed Slab of Exposed Cut Copper=Dalle de cuivre taillé exposé ciré +Waxed Slab of Oxidized Cut Copper=Dalle de cuivre taillé oxydé ciré +Waxed Slab of Weathered Cut Copper=Dalle de cuivre taillé érodé ciré Some copper contained in stone, it is pretty common and can be found below sea level.=Un peu de cuivre se trouve dans la pierre, il est plutôt répandu et peut être trouvé sous le niveau de la mer. Stairs of Cut Copper=Escalier de cuivre taillé Stairs of Exposed Cut Copper=Escalier de cuivre taillé exposé Stairs of Oxidized Cut Copper=Escalier de cuivre taillé oxydé Stairs of Weathered Cut Copper=Escalier de cuivre taillé érodé +Waxed Stairs of Cut Copper=Escalier de cuivre taillé ciré +Waxed Stairs of Exposed Cut Copper=Escalier de cuivre taillé exposé ciré +Waxed Stairs of Oxidized Cut Copper=Escalier de cuivre taillé oxydé ciré +Waxed Stairs of Weathered Cut Copper=Escalier de cuivre taillé érodé ciré Weathered copper is a decorative block.=Le cuivre érodé est un bloc décoratif. Weathered Copper=Cuivre érodé +Waxed Weathered Copper=Cuivre érodé ciré Weathered cut copper is a decorative block.=Le cuivre taillé érodé est un bloc décoratif. Weathered Cut Copper=Cuivre taillé érodé +Waxed Weathered Cut Copper=Cuivre taillé érodé ciré diff --git a/mods/ITEMS/mcl_core/locale/mcl_core.fr.tr b/mods/ITEMS/mcl_core/locale/mcl_core.fr.tr index 9a53caa51..e66d8b115 100644 --- a/mods/ITEMS/mcl_core/locale/mcl_core.fr.tr +++ b/mods/ITEMS/mcl_core/locale/mcl_core.fr.tr @@ -10,7 +10,7 @@ A block of iron is mostly a decorative block but also useful as a compact storag A cactus can only be placed on top of another cactus or any sand.=Un cactus ne peut être placé que sur un autre cactus ou du sable. A decorative and mostly transparent block.=Un bloc décoratif et surtout transparent. A grass block is dirt with a grass cover. Grass blocks are resourceful blocks which allow the growth of all sorts of plants. They can be turned into farmland with a hoe and turned into grass paths with a shovel. In light, the grass slowly spreads onto dirt nearby. Under an opaque block or a liquid, a grass block may turn back to dirt.=Un bloc d'herbe est de la terre avec une couverture d'herbe. Les blocs d'herbe sont des blocs ingénieux qui permettent la croissance de toutes sortes de plantes. Ils peuvent être transformés en terres agricoles avec une houe et transformés en chemins d'herbe avec une pelle. À la lumière, l'herbe se propage lentement sur la terre à proximité. Sous un bloc opaque ou un liquide, un bloc d'herbe peut redevenir terre. -A lapis lazuli block is mostly a decorative block but also useful as a compact storage of lapis lazuli.=Un bloc de lapis-lazuli est principalement un bloc décoratif mais également utile comme stockage compact de lapis-lazuli. +A lapis lazuli block is mostly a decorative block but also useful as a compact storage of lapis lazuli.=Un bloc de lapis-lazuli est principalement un bloc décoratif mais également utile pour stocker du lapis-lazuli. A lava source sets fire to a couple of air blocks above when they're next to a flammable block.=Une source de lave met le feu à quelques blocs d'air au-dessus lorsqu'ils sont à côté d'un bloc inflammable. A piece of ladder which allows you to climb vertically. Ladders can only be placed on the side of solid blocks and not on glass, leaves, ice, slabs, glowstone, nor sea lanterns.=Un morceau d'échelle qui vous permet de grimper verticalement. Les échelles ne peuvent être placées que sur le côté de blocs solides et non sur du verre, des feuilles, de la glace, des dalles, des pierres incandescentes ou des lanternes marines. Acacia Bark=Bois d'acacia @@ -18,36 +18,36 @@ Acacia Leaves=Feuilles d'acacia Acacia Sapling=Pousse d'acacia Acacia Wood=Bûche d'acacia Acacia Wood Planks=Planches d'acacia -Acacia leaves are grown from acacia trees.=Les feuilles d'acacia sont cultivées à partir d'acacias. +Acacia leaves are grown from acacia trees.=Les feuilles d'acacia poussent sur des acacias. Andesite=Andésite Andesite is an igneous rock.=L'andésite est une roche ignée. Apple=Pomme Apples are food items which can be eaten.=Les pommes sont des aliments qui peuvent être consommés. Barrier=Barrière invisible -Barriers are invisible walkable blocks. They are used to create boundaries of adventure maps and the like. Monsters and animals won't appear on barriers, and fences do not connect to barriers. Other blocks can be built on barriers like on any other block.=Les barrières sont des blocs accessibles à pied. Ils sont utilisés pour créer des limites de cartes d'aventure et similaires. Les monstres et les animaux n'apparaissent pas sur les barrières, et les clôtures ne se connectent pas aux barrières. D'autres blocs peuvent être construits sur des barrières comme sur n'importe quel autre bloc. +Barriers are invisible walkable blocks. They are used to create boundaries of adventure maps and the like. Monsters and animals won't appear on barriers, and fences do not connect to barriers. Other blocks can be built on barriers like on any other block.=Les barrières sont des blocs accessibles à pied. Elles sont utilisées pour créer des limites de cartes d'aventure et autre. Les monstres et les animaux n'apparaissent pas sur les barrières, et les clôtures ne se connectent pas aux barrières. D'autres blocs peuvent être construits sur des barrières comme sur n'importe quel autre bloc. Bedrock=Bedrock -Bedrock is a very hard type of rock. It can not be broken, destroyed, collected or moved by normal means, unless in Creative Mode.=Le bedrock est un type de roche très dur. Il ne peut pas être brisé, détruit, collecté ou déplacé par des moyens normaux, sauf en mode créatif. +Bedrock is a very hard type of rock. It can not be broken, destroyed, collected or moved by normal means, unless in Creative Mode.=La bedrock est un type de roche très dure. Elle ne peut pas être brisée, détruite, collectée ou déplacée par des moyens normaux, sauf en mode créatif. Birch Bark=Bois de bouleau Birch Leaves=Feuilles de bouleau Birch Sapling=Pousse de bouleau Birch Wood=Bûche de bouleau Birch Wood Planks=Planches de bouleau -Birch leaves are grown from birch trees.=Les feuilles de bouleau sont cultivées à partir de bouleaux. +Birch leaves are grown from birch trees.=Les feuilles de bouleau poussent sur les bouleaux. Black Stained Glass=Verre noir Block of Coal=Bloc de charbon Block of Diamond=Bloc de diamant Block of Emerald=Bloc d'émeraude Block of Gold=Bloc d'or Block of Iron=Bloc de fer -Blocks of coal are useful as a compact storage of coal and very useful as a furnace fuel. A block of coal is as efficient as 10 coal.=Les blocs de charbon sont utiles comme stockage compact de charbon et très utiles comme combustible de four. Un bloc de charbon est aussi efficace que 10 charbon. +Blocks of coal are useful as a compact storage of coal and very useful as a furnace fuel. A block of coal is as efficient as 10 coal.=Les blocs de charbon sont utiles pour stocker du charbon et très utiles comme combustible de four. Un bloc de charbon est aussi efficace que 10 charbon. Blue Stained Glass=Verre bleu Bone Block=Bloc d'os -Bone blocks are decorative blocks and a compact storage of bone meal.=Les blocs d'os sont des blocs décoratifs et un stockage compact de poudre d'os. +Bone blocks are decorative blocks and a compact storage of bone meal.=Les blocs d'os sont des blocs décoratifs et servent à stocker la poudre d'os. Bowl=Bol Bowls are mainly used to hold tasty soups.=Les bols sont principalement utilisés pour contenir de délicieuses soupes. Brick=Brique Brick Block=Bloc de brique -Brick blocks are a good building material for building solid houses and can take quite a punch.=Les blocs de briques sont un bon matériau de construction pour la construction de maisons solides et peuvent resite au coup. +Brick blocks are a good building material for building solid houses and can take quite a punch.=Les blocs de briques sont un bon matériau de construction pour la construction de maisons solides et peuvent résister aux coups. Bricks are used to craft brick blocks.=Les briques sont utilisées pour fabriquer des blocs de briques. Brown Stained Glass=Verre marron Cactus=Cactus @@ -80,14 +80,14 @@ Dark Oak Leaves=Feuilles de chêne noir Dark Oak Sapling=Pousse de chêne noir Dark Oak Wood=Bûche de chêne noir Dark Oak Wood Planks=Planche de chêne noir -Dark oak leaves are grown from dark oak trees.=Les feuilles de chêne noir sont issues de chênes noirs. -Dark oak saplings can grow into dark oaks, but only in groups. A lonely dark oak sapling won't grow. A group of four dark oak saplings grows into a dark oak after some time when they are placed on soil (such as dirt) in a 2×2 square and exposed to light.=Les pousses de chêne noir peuvent devenir des chênes noirs, mais seulement en groupes. Une pousse de chêne noir solitaire ne poussera pas. Un groupe de quatre pousses de chêne noir se transforme en chêne noir après un certain temps lorsqu'ils sont placés sur le sol (comme la terre) dans un carré 2×2 et exposés à la lumière. +Dark oak leaves are grown from dark oak trees.=Les feuilles de chêne noir poussent sur les chênes noirs. +Dark oak saplings can grow into dark oaks, but only in groups. A lonely dark oak sapling won't grow. A group of four dark oak saplings grows into a dark oak after some time when they are placed on soil (such as dirt) in a 2×2 square and exposed to light.=Les pousses de chêne noir peuvent devenir des chênes noirs, mais seulement en groupes. Une pousse de chêne noir solitaire ne poussera pas. Un groupe de quatre pousses de chêne noir se transforme en chêne noir après un certain temps lorsqu'elles sont placées sur le sol (comme la terre) dans un carré 2×2 et exposés à la lumière. Dead Bush=Arbuste mort Dead bushes are unremarkable plants often found in dry areas. They can be harvested for sticks.=Les buissons morts sont des plantes inhabituelles que l'on trouve souvent dans les zones sèches. Ils peuvent être récoltés avec des bâtons. Diamond=Diamant Diamond Ore=Minerai de diamant Diamond ore is rare and can be found in clusters near the bottom of the world.=Le minerai de diamant est rare et peut être trouvé en filons près du fond du monde. -Diamonds are precious minerals and useful to create the highest tier of armor and tools.=Les diamants sont des minéraux précieux et utiles pour créer le plus haut niveau d'armure et d'outils. +Diamonds are precious minerals and useful to create the highest tier of armor and tools.=Les diamants sont des minéraux précieux et utiles pour créer des armures et outils du plus haut niveau . Diorite=Diorite Diorite is an igneous rock.=La diorite est une roche ignée. Dirt=Terre @@ -101,12 +101,12 @@ Flint is a raw material.=Le silex est une matière première. Flowing Lava=Lave qui coule Flowing Water=Eau qui coule Frosted Ice=Glace givrée -Frosted ice is a short-lived solid block. It melts into a water source within a few seconds.=La glace givrée est un bloc solide de courte durée. Il fond dans une source d'eau en quelques secondes. +Frosted ice is a short-lived solid block. It melts into a water source within a few seconds.=La glace givrée est un bloc solide de courte durée. Elle fond dans une source d'eau en quelques secondes. Glass=Verre Gold Ingot=Lingot d'or Gold Nugget=Pépite d'or Gold Ore=Minerai d'or -Gold nuggets are very small pieces of molten gold; the main purpose is to create gold ingots.=Les pépites d'or sont de très petites pièces d'or en fusion; le but principal est de créer des lingots d'or. +Gold nuggets are very small pieces of molten gold; the main purpose is to create gold ingots.=Les pépites d'or sont de très petites pièces d'or en fusion ; le but principal est de créer des lingots d'or. Golden Apple=Pomme dorée Golden apples are precious food items which can be eaten.=Les pommes dorées sont des aliments précieux qui peuvent être consommés. Granite=Granite @@ -117,18 +117,18 @@ Gravel=Gravier Green Stained Glass=Verre vert Grey Stained Glass=Verre gris Ice=Glace -Ice is a solid block usually found in cold areas. It melts near block light sources at a light level of 12 or higher. When it melts or is broken while resting on top of another block, it will turn into a water source.=La glace est un bloc solide que l'on trouve généralement dans les régions froides. Il fond près des sources de lumière de bloc à un niveau de lumière de 12 ou plus. Lorsqu'il fond ou se casse en se reposant sur un autre bloc, il se transforme en source d'eau. +Ice is a solid block usually found in cold areas. It melts near block light sources at a light level of 12 or higher. When it melts or is broken while resting on top of another block, it will turn into a water source.=La glace est un bloc solide que l'on trouve généralement dans les régions froides. Elle fond près des blocs sources de lumière à un niveau de lumière de 12 ou plus. Lorsqu'elle fond ou se casse au sommet d'un autre bloc, elle se transforme en source d'eau. In the End dimension, starting a fire on this block will create an eternal fire.=Dans la dimension End, démarrer un feu sur ce bloc créera un feu éternel. Iron Ingot=Lingot de fer Iron Nugget=Pépite de fer Iron Ore=Minerai de fer -Iron nuggets are very small pieces of molten iron; the main purpose is to create iron ingots.=Les pépites de fer sont de très petits morceaux de fer fondu; le but principal est de créer des lingots de fer. +Iron nuggets are very small pieces of molten iron; the main purpose is to create iron ingots.=Les pépites de fer sont de très petits morceaux de fer fondu ; leur principal intérêt est de fabriquer des lingots de fer. Jungle Bark=Bois d'acajou Jungle Leaves=Feuilles d'acajou Jungle Sapling=Pousse d'acajou Jungle Wood=Bûche d'acajou Jungle Wood Planks=Planches d'acajou -Jungle leaves are grown from jungle trees.=Les feuilles d'acajou sont cultivées à partir d'arbres d'acajou. +Jungle leaves are grown from jungle trees.=Les feuilles d'acajou poussent sur les acajous. Ladder=Échelle Lapis Lazuli=Lapis-lazuli Lapis Lazuli are required for enchanting items on an enchanting table.=Les lapis-lazuli sont nécessaires pour enchanter des objets sur une table d'enchantement. @@ -153,10 +153,10 @@ Oak Leaves=Feuilles de chêne Oak Sapling=Pousse de chêne Oak Wood=Bûche de chêne Oak Wood Planks=Planches de chêne -Oak leaves are grown from oak trees.=Les feuilles de chêne sont cultivées à partir de chênes. +Oak leaves are grown from oak trees.=Les feuilles de chêne poussent sur des chênes. Obsidian=Obsidienne Obsidian is an extremely hard mineral with an enourmous blast-resistance. Obsidian is formed when water meets lava.=L'obsidienne est un minéral extrêmement dur avec une énorme résistance à l'explosion. L'obsidienne se forme lorsque l'eau rencontre la lave. -One of the most common blocks in the world, almost the entire underground consists of stone. It sometimes contains ores. Stone may be created when water meets lava.=L'un des blocs les plus courants au monde, presque tout le sous-sol est en pierre. Il contient parfois des minerais. La pierre peut être créée lorsque l'eau rencontre la lave. +One of the most common blocks in the world, almost the entire underground consists of stone. It sometimes contains ores. Stone may be created when water meets lava.=L'un des blocs les plus courants au monde, presque tout le sous-sol est en pierre. Elle contient parfois des minerais. La pierre peut être créée lorsque l'eau rencontre la lave. Orange Stained Glass=Verre orange Packed Ice=Glace compactée Packed ice is a compressed form of ice. It is opaque and solid.=La glace compactée est une forme de glace comprimée. Elle est opaque et solide. @@ -186,23 +186,23 @@ Sand is found in large quantities at beaches and deserts.=Le sable se trouve en Sandstone=Grès Sandstone is compressed sand and is a rather soft kind of stone.=Le grès est du sable comprimé et est un type de pierre plutôt tendre. Slime Block=Bloc de Slime -Slime blocks are very bouncy and prevent fall damage.=Les blocs de slime sont gonflables et empêchent les dégats de chute. +Slime blocks are very bouncy and prevent fall damage.=Les blocs de slime sont gonflables et empêchent les dégâts de chute. Smooth Red Sandstone=Grès rouge lisse Smooth Sandstone=Grès lisse Smooth red sandstone is a decorative building block.=Le grès rouge lisse est un bloc de construction décoratif. Smooth sandstone is compressed sand and is a rather soft kind of stone.=Le grès lisse est du sable comprimé et est un type de pierre plutôt tendre. Snow=Neige -Some coal contained in stone, it is very common and can be found inside stone in medium to large clusters at nearly every height.=Du charbon contenu dans la pierre, il est très commun et peut être trouvé à l'intérieur de la pierre en grappes moyennes à grandes à presque toutes les hauteurs. +Some coal contained in stone, it is very common and can be found inside stone in medium to large clusters at nearly every height.=Du charbon contenu dans la pierre, il est très commun et peut être trouvé à l'intérieur de la pierre en veines moyennes à grandes à presque toutes les hauteurs. Some iron contained in stone, it is prety common and can be found below sea level.=Du fer contenu dans la pierre, il est assez courant et se trouve sous le niveau de la mer. Spruce Bark=Bois de sapin Spruce Leaves=Feuilles de sapin Spruce Sapling=Pousse de sapin Spruce Wood=Bûche de sapin Spruce Wood Planks=Planches de sapin -Spruce leaves are grown from spruce trees.=Les feuilles de sapin sont cultivées à partir de sapin. +Spruce leaves are grown from spruce trees.=Les feuilles de sapin poussent sur les sapins. Stained glass is a decorative and mostly transparent block which comes in various different colors.=Le verre est un bloc décoratif et principalement transparent qui se décline en différentes couleurs. Stick=Bâton -Sticks are a very versatile crafting material; used in countless crafting recipes.=Les bâtons sont un matériau d'artisanat très polyvalent; utilisé dans d'innombrables recettes d'artisanat. +Sticks are a very versatile crafting material; used in countless crafting recipes.=Les bâtons sont un matériau d'artisanat très polyvalent ; utilisé dans d'innombrables recettes d'artisanat. Stone=Roche Stripped Acacia Log=Bûche d'acacia écorcée Stripped Acacia Wood=Bois d'acacia écorcé @@ -240,25 +240,25 @@ The stripped wood of a dark oak tree.=Le bois écorcé d'un chêne noir. The stripped wood of a jungle tree.=Le bois écorcé d'un acajou. The stripped wood of an oak tree.=Le bois écorcé d'un chêne. The stripped wood of a spruce tree.=Le bois écorcé d'un sapin. -This block consists of a couple of loose stones and can't support itself.=Ce bloc se compose de quelques pierres lâches et ne peut pas se soutenir. +This block consists of a couple of loose stones and can't support itself.=Ce bloc se compose de quelques pierres instables et ne peut pas se soutenir. This is a decorative block surrounded by the bark of a tree trunk.=Il s'agit d'un bloc décoratif entouré par l'écorce d'un tronc d'arbre. This is a decorative block.=Il s'agit d'un bloc décoratif. This is a full block of snow. Snow of this thickness is usually found in areas of extreme cold.=Ceci est un bloc de neige complet. La neige de cette épaisseur se trouve généralement dans les zones de froid extrême. This is a piece of cactus commonly found in dry areas, especially deserts. Over time, cacti will grow up to 3 blocks high on sand or red sand. A cactus hurts living beings touching it with a damage of 1 HP every half second. When a cactus block is broken, all cactus blocks connected above it will break as well.=Il s'agit d'un morceau de cactus que l'on trouve couramment dans les zones sèches, en particulier dans les déserts. Au fil du temps, les cactus pousseront jusqu'à 3 blocs de haut sur le sable ou le sable rouge. Un cactus blesse les êtres vivants qui le touchent avec des dégâts de 1 HP toutes les demi-secondes. Lorsqu'un bloc de cactus est brisé, tous les blocs de cactus connectés au-dessus se brisent également. This stone contains pure gold, a rare metal.=Cette pierre contient de l'or pur, un métal rare. Top Snow=neige -Top snow is a layer of snow. It melts near light sources other than the sun with a light level of 12 or higher.=La neige est une couche de neige. Il fond près de sources lumineuses autres que le soleil avec un niveau de lumière de 12 ou plus. +Top snow is a layer of snow. It melts near light sources other than the sun with a light level of 12 or higher.=La neige est une couche de neige. Elle fond près de sources lumineuses autres que le soleil avec un niveau de lumière de 12 ou plus. Vines=Lianes -Vines are climbable blocks which can be placed on the sides of solid full-cube blocks. Vines slowly grow and spread.=Les lianes sont des blocs grimpants qui peuvent être placés sur les côtés de blocs pleins. Les lianes poussent et s'étendent lentement. +Vines are climbable blocks which can be placed on the sides of solid full-cube blocks. Vines slowly grow and spread.=Les lianes sont des blocs grimpables qui peuvent être placés sur les côtés de blocs pleins. Les lianes poussent et s'étendent lentement. Void=Néant Water=Eau Water Source=Source d'eau Water is abundant in oceans and also appears in a few springs in the ground. You can swim easily in water, but you need to catch your breath from time to time.=L'eau est abondante dans les océans et apparaît également dans quelques sources dans le sol. Vous pouvez nager facilement dans l'eau, mais vous devez de temps en temps reprendre votre souffle. -When placed on soil (such as dirt) and exposed to light, a birch sapling will grow into a birch after some time.=Lorsqu'il est placé sur le sol (comme la terre) et exposé à la lumière, un jeune arbre de bouleau se transforme en bouleau après un certain temps. -When placed on soil (such as dirt) and exposed to light, a jungle sapling will grow into a jungle tree after some time. When there are 4 jungle saplings in a 2×2 square, they will grow to a huge jungle tree.=Lorsqu'il est placé sur le sol (comme la terre) et exposé à la lumière, une pousse d'Acajou se transforme en arbre d'Acajou après un certain temps. Quand il y a 4 pousses d'Acajou dans un carré 2×2, ils deviendront un énorme arbre d'Acajou. -When placed on soil (such as dirt) and exposed to light, a spruce sapling will grow into a spruce after some time. When there are 4 spruce saplings in a 2×2 square, they will grow to a huge spruce.=Lorsqu'il est placé sur le sol (comme la terre) et exposé à la lumière, un pousse de sapin se transforme en sapin après un certain temps. Lorsqu'il y a 4 pousses de sapin dans un carré 2×2, elles deviendront un énorme sapin. -When placed on soil (such as dirt) and exposed to light, an acacia sapling will grow into an acacia after some time.=Lorsqu'il est placé sur le sol (comme la terre) et exposé à la lumière, un pousse d'acacia se développera en un acacia après un certain temps. -When placed on soil (such as dirt) and exposed to light, an oak sapling will grow into an oak after some time.=Lorsqu'il est placé sur le sol (comme la terre) et exposé à la lumière, une pousse de chêne se transforme en chêne après un certain temps. +When placed on soil (such as dirt) and exposed to light, a birch sapling will grow into a birch after some time.=Lorsqu'elle est placée sur le sol (par exemple de la terre) et exposée à la lumière, une jeune pousse de bouleau se transforme en bouleau après un certain temps. +When placed on soil (such as dirt) and exposed to light, a jungle sapling will grow into a jungle tree after some time. When there are 4 jungle saplings in a 2×2 square, they will grow to a huge jungle tree.=Lorsqu'elle est placée sur le sol (par exemple de la terre) et exposée à la lumière, une pousse d'Acajou se transforme en arbre d'Acajou après un certain temps. Quand il y a 4 pousses d'Acajou dans un carré 2×2, elles deviendront un énorme arbre d'Acajou. +When placed on soil (such as dirt) and exposed to light, a spruce sapling will grow into a spruce after some time. When there are 4 spruce saplings in a 2×2 square, they will grow to a huge spruce.=Lorsqu'elle est placée sur le sol (par exemple de la terre) et exposée à la lumière, une pousse de sapin se transforme en sapin après un certain temps. Lorsqu'il y a 4 pousses de sapin dans un carré 2×2, elles deviendront un énorme sapin. +When placed on soil (such as dirt) and exposed to light, an acacia sapling will grow into an acacia after some time.=Lorsqu'elle est placée sur le sol (par exemple de la terre) et exposée à la lumière, une pousse d'acacia se transforme en acacia après un certain temps. +When placed on soil (such as dirt) and exposed to light, an oak sapling will grow into an oak after some time.=Lorsqu'elle est placée sur le sol (par exemple de la terre) et exposée à la lumière, une pousse de chêne se transforme en chêne après un certain temps. When you hold a barrier in hand, you reveal all placed barriers in a short distance around you.=Lorsque vous tenez une barrière en main, vous révélez toutes les barrières placées à une courte distance autour de vous. White Stained Glass=Verre blanc Yellow Stained Glass=Verre jaune @@ -277,15 +277,15 @@ This block can only be placed on full solid blocks and on another top snow (whic Needs soil and water to grow=A besoin de terre et d'eau pour se développer Needs soil and light to grow=A besoin de terre et de lumière pour se développer Grows on sand=Pousse sur le sable -Contact damage: @1 per half second=Dégats de contact : @1 par demi-seconde +Contact damage: @1 per half second=Dégâts de contact : @1 par demi-seconde Slows down movement=Ralentit le mouvement -2×2 saplings required=2×2 pousses requis +2×2 saplings required=2×2 pousses requises 2×2 saplings @= large tree=2×2 pousses @= grand arbre Grows on sand or dirt next to water=Pousse sur le sable ou la terre près de l'eau Stackable=Empilable Crying Obsidian=Obsidienne pleureuse -Crying obsidian is a luminous obsidian that can generate as part of ruined portals.=L'obsidienne pleureuse est une obsidienne luminause qui peut être générée dans les portails en ruine. +Crying obsidian is a luminous obsidian that can generate as part of ruined portals.=L'obsidienne pleureuse est une obsidienne lumineuse qui peut être générée dans les portails en ruine. Enchanted Golden Apple=Pomme dorée enchantée Light=Lumière -Lights are invisible blocks. They are used to light up adventure maps and the like.=Les lumières sont des blocs invisibles. Ils sont utilisés pour éclairer les cartes d'aventure. +Lights are invisible blocks. They are used to light up adventure maps and the like.=Les lumières sont des blocs invisibles. Elles sont utilisées pour éclairer les cartes d'aventure. When you hold a light in hand, you reveal all placed lights in a short distance around you.=Lorsque vous tenez une lumière en main, vous révélez toutes les lumières placées à une courte distance autour de vous. diff --git a/mods/ITEMS/mcl_crimson/locale/mcl_crimson.fr.tr b/mods/ITEMS/mcl_crimson/locale/mcl_crimson.fr.tr index 4a84dd5a6..16521d6a3 100644 --- a/mods/ITEMS/mcl_crimson/locale/mcl_crimson.fr.tr +++ b/mods/ITEMS/mcl_crimson/locale/mcl_crimson.fr.tr @@ -1,29 +1,51 @@ # textdomain: mcl_crimson -Warped Fungus Mushroom=Champignon tordu +Warped Fungus=Champignon tordu +Warped fungus is a mushroom found in the nether's warped forest.=Les champignons tordus se trouvent dans la forêt tordue du nether. Twisting Vines=Liane tordue +Weeping Vines=Liane pleureuse Nether Sprouts=Racines du Nether Warped Roots=Racines tordues Warped Wart Block=Bloc de verrues tordu Shroomlight=Champilampe Warped Hyphae=Tige tordue +The stem of a warped hyphae=La tige d'un champignon géant tordu Warped Hyphae Bark=Hyphe tordue -Stripped warped hyphae=Tige tordue dénudée -Stripped warped hyphae bark=Hyphe tordue dénudée +This is a decorative block surrounded by the bark of an hyphae.=Ceci est un bloc décoratif entouré de l'écorce d'une tige +Stripped Warped Hyphae=Tige tordue dénudée +The stripped hyphae of a warped fungus=La tige dénudée d'un champignon géant tordu +Stripped Warped Hyphae Bark=Hyphe tordue dénudée +The stripped hyphae bark of a warped fungus=La tige dénudée d'un champignon géant tordu Warped Nylium=Nylium tordu Warped Checknode - only to check!=Bloc de vérification tordu - seulement pour vérifier ! Warped Hyphae Wood=Planches tordues Warped Stair=Escalier tordu Warped Slab=Dalle tordue -Crimson Fungus Mushroom=Champignon écarlate +Crimson Fungus=Champignon écarlate +Crimson fungus is a mushroom found in the nether's crimson forest.=Les champignons écarlates se trouvent dans la forêt écarlate du nether. Crimson Roots=Racines écarlates Crimson Hyphae=Tige écarlate +The stem of a crimson hyphae=La tige d'un champignon géant écarlate Crimson Hyphae Bark=Hyphe écarlate Stripped Crimson Hyphae=Tige écarlate dénudée +The stripped stem of a crimson hyphae=La tige dénudée d'un champignon géant écarlate Stripped Crimson Hyphae Bark=Hyphe écarlate dénudée +The stripped wood of a crimson hyphae=La tige dénudée d'un champignon géant écarlate Crimson Hyphae Wood=Planches écarlates Crimson Stair=Escalier écarlate Crimson Slab=Dalle écarlate Double Crimson Slab=Dalle double écarlate Crimson Nylium=Nylium écarlate +Crimson Door=Porte écarlate +Wooden doors are 2-block high barriers which can be opened or closed by hand and by a redstone signal.=Les portes en bois sont des barrières hautes à 2 blocs qui peuvent être ouvertes ou fermées à la main et par un signal redstone. +To open or close a wooden door, rightclick it or supply its lower half with a redstone signal.=Pour ouvrir ou fermer une porte en bois, faites un clic droit dessus ou fournissez à sa moitié inférieure un signal redstone. +Crimson Trapdoor=Trappe écarlate +Wooden trapdoors are horizontal barriers which can be opened and closed by hand or a redstone signal. They occupy the upper or lower part of a block, depending on how they have been placed. When open, they can be climbed like a ladder.=es trappes en bois sont des barrières horizontales qui peuvent être ouvertes et fermées à la main ou par un signal redstone. Ils occupent la partie supérieure ou inférieure d'un bloc, selon la façon dont ils ont été placés. Lorsqu'elles sont ouvertes, elles peuvent être montées comme une échelle. +To open or close the trapdoor, rightclick it or send a redstone signal to it.=Pour ouvrir ou fermer la trappe, faites un clic droit dessus ou envoyez-lui un signal redstone. +Crimson Fence=Barrière écarlate +Crimson Fence Gate=Portillon écarlate Crimson Checknode - only to check!=Bloc de vérification écarlate - seulement pour vérifier ! +Warped Door=Porte tordue +Warped Trapdoor=Trappe tordue +Warped Fence=Barrière tordue +Warped Fence Gate=Portillon tordu diff --git a/mods/ITEMS/mcl_crimson/locale/template.txt b/mods/ITEMS/mcl_crimson/locale/template.txt index 022a9a6dc..f93b85577 100644 --- a/mods/ITEMS/mcl_crimson/locale/template.txt +++ b/mods/ITEMS/mcl_crimson/locale/template.txt @@ -1,29 +1,51 @@ # textdomain: mcl_crimson -Warped Fungus Mushroom= +Warped Fungus= +Warped fungus is a mushroom found in the nether's warped forest.= Twisting Vines= +Weeping Vines= Nether Sprouts= Warped Roots= Warped Wart Block= Shroomlight= Warped Hyphae= +The stem of a warped hyphae= Warped Hyphae Bark= -Stripped warped hyphae= -Stripped warped hyphae bark= +This is a decorative block surrounded by the bark of an hyphae.= +Stripped Warped Hyphae= +The stripped hyphae of a warped fungus= +Stripped Warped Hyphae Bark= +The stripped hyphae bark of a warped fungus= Warped Nylium= Warped Checknode - only to check!= Warped Hyphae Wood= Warped Stair= Warped Slab= -Crimson Fungus Mushroom= +Crimson Fungus= +Crimson fungus is a mushroom found in the nether's crimson forest.= Crimson Roots= Crimson Hyphae= +The stem of a crimson hyphae= Crimson Hyphae Bark= Stripped Crimson Hyphae= +The stripped stem of a crimson hyphae= Stripped Crimson Hyphae Bark= +The stripped wood of a crimson hyphae= Crimson Hyphae Wood= Crimson Stair= Crimson Slab= Double Crimson Slab= Crimson Nylium= +Crimson Door= +Wooden doors are 2-block high barriers which can be opened or closed by hand and by a redstone signal.= +To open or close a wooden door, rightclick it or supply its lower half with a redstone signal.= +Crimson Trapdoor= +Wooden trapdoors are horizontal barriers which can be opened and closed by hand or a redstone signal. They occupy the upper or lower part of a block, depending on how they have been placed. When open, they can be climbed like a ladder.= +To open or close the trapdoor, rightclick it or send a redstone signal to it.= +Crimson Fence= +Crimson Fence Gate= Crimson Checknode - only to check!= +Warped Door= +Warped Trapdoor= +Warped Fence= +Warped Fence Gate= diff --git a/mods/ITEMS/mcl_deepslate/locale/mcl_deepslate.fr.tr b/mods/ITEMS/mcl_deepslate/locale/mcl_deepslate.fr.tr index d79146701..18fcc415b 100644 --- a/mods/ITEMS/mcl_deepslate/locale/mcl_deepslate.fr.tr +++ b/mods/ITEMS/mcl_deepslate/locale/mcl_deepslate.fr.tr @@ -28,7 +28,7 @@ Deepslate iron ore is a variant of iron ore that can generate in deepslate and t Deepslate Iron Ore=Minerai de fer de l'ardoise des abîmes Deepslate is a stone type found deep underground in the Overworld that functions similar to regular stone but is harder than the stone.=L'ardoise des abîmes est un type de roche présente dans les profondeurs de l'Overworld qui fonctionne de manière similaire à la roche classique mais en plus dur. Deepslate Lapis Lazuli Ore=Minerai de lapis-lazuli de l'ardoise des abîmes -Deepslate lapis ore is a variant of lapis ore that can generate in deepslate and tuff blobs.=Le minerai de lapis de l'ardoise des abîmes est une variante de minerai de lapis-lazuli qui apparaît dans l'ardoise des abîmes et les filons de tuf. +Deepslate lapis lazuli ore is a variant of lapis lazuli ore that can generate in deepslate and tuff blobs.=Le minerai de lapis-lazuli de l'ardoise des abîmes est une variante de minerai de lapis-lazuli qui apparaît dans l'ardoise des abîmes et les filons de tuf. Deepslate redstone ore is a variant of redstone ore that can generate in deepslate and tuff blobs.=Le minerai de redstone de l'ardoise des abîmes est une variante de minerai de redstone qui apparaît dans l'ardoise des abîmes et les filons de tuf. Deepslate Redstone Ore=Minerai de Redstone de l'ardoise des abîmes Deepslate tiles are a decorative variant of deepslate.=L'ardoise des abîmes carrelée est une variante décorative de l'ardoise des abîmes. @@ -50,4 +50,4 @@ Polished Deepslate Stairs=Escalier d'ardoise des abîmes Polished Deepslate Wall=Muret d'ardoise des abîmes Polished Deepslate=Ardoise des abîmes polie Tuff=Tuf -Tuff is an ornamental rock formed from volcanic ash, occurring in underground blobs below Y=16.=Le tuf est une roche ornementale formée de roche volcanique, apparraissant dans des blobs souterrains sous Y=16. +Tuff is an ornamental rock formed from volcanic ash, occurring in underground blobs below Y@=16.=Le tuf est une roche ornementale formée de roche volcanique, apparaissant dans des blobs souterrains sous Y@=16. diff --git a/mods/ITEMS/mcl_deepslate/locale/template.txt b/mods/ITEMS/mcl_deepslate/locale/template.txt index 44da92c66..781eae587 100644 --- a/mods/ITEMS/mcl_deepslate/locale/template.txt +++ b/mods/ITEMS/mcl_deepslate/locale/template.txt @@ -28,7 +28,7 @@ Deepslate iron ore is a variant of iron ore that can generate in deepslate and t Deepslate Iron Ore= Deepslate is a stone type found deep underground in the Overworld that functions similar to regular stone but is harder than the stone.= Deepslate Lapis Lazuli Ore= -Deepslate lapis ore is a variant of lapis ore that can generate in deepslate and tuff blobs.= +Deepslate lapis lazuli ore is a variant of lapis lazuli ore that can generate in deepslate and tuff blobs.= Deepslate redstone ore is a variant of redstone ore that can generate in deepslate and tuff blobs.= Deepslate Redstone Ore= Deepslate tiles are a decorative variant of deepslate.= @@ -50,4 +50,4 @@ Polished Deepslate Stairs= Polished Deepslate Wall= Polished Deepslate= Tuff= -Tuff is an ornamental rock formed from volcanic ash, occurring in underground blobs below Y=16.= +Tuff is an ornamental rock formed from volcanic ash, occurring in underground blobs below Y@=16.= diff --git a/mods/ITEMS/mcl_enchanting/locale/mcl_enchanting.fr.tr b/mods/ITEMS/mcl_enchanting/locale/mcl_enchanting.fr.tr index 58275f418..80912a711 100644 --- a/mods/ITEMS/mcl_enchanting/locale/mcl_enchanting.fr.tr +++ b/mods/ITEMS/mcl_enchanting/locale/mcl_enchanting.fr.tr @@ -23,9 +23,9 @@ Frost Walker=Semelles givrantes Impaling=Empalement Increases arrow damage.=Augmente les dégâts des flèches. Increases arrow knockback.=Augmente le recul de la flèche. -Increases certain block drops.=Multiplie les items droppés +Increases certain block drops.=Multiplie les objets droppés -Increases damage and applies Slowness IV to arthropod mobs (spiders, cave spiders, silverfish and endermites).=Augmente les dégâts et applique la lenteur IV aux mobs arthropodes (araignées, araignées des cavernes, lépismes argentés et endermites). +Increases damage and applies Slowness IV to arthropod mobs (spiders, cave spiders, silverfish and endermites).=Augmente les dégâts et applique la lenteur IV aux mobs arthropodes (araignées, araignées des cavernes, poissons d'argent et endermites). Increases damage to undead mobs.=Augmente les dégâts infligés aux monstres morts-vivants. Increases damage.=Augmente les dégâts. @@ -95,7 +95,7 @@ Enchant an item=Enchanter un objet Enchanted Book=Livre enchanté Enchanting Table=Table d'enchantement -Enchanting Tables will let you enchant armors, tools, weapons, and books with various abilities. But, at the cost of some experience, and lapis lazuli.=La table d'enchantement vous permet d'enchanter des armueres, des outils, des armes et des livres avec diverses propriétés. Mais cela coûte de l'expérience et des lapis-lazuli. +Enchanting Tables will let you enchant armors, tools, weapons, and books with various abilities. But, at the cost of some experience, and lapis lazuli.=La table d'enchantement vous permet d'enchanter des armures, des outils, des armes et des livres avec diverses propriétés. Mais cela coûte de l'expérience et des lapis-lazuli. Enchanting succeded.=L'enchantement a réussi. Forcefully enchant an item=Enchantement forcé d'un objet @@ -113,14 +113,14 @@ The number you have entered (@1) is too small, it must be at least @2.=Le nombre The selected enchantment can't be added to the target item.=L'enchantement sélectionné ne peut pas être ajouté à la cible. The target doesn't hold an item.=La cible ne contient aucun élément. The target item is not enchantable.=L'objet cible n'est pas enchantable. -There is no such enchantment '@1'.=Il n'y a pas un tel enchantement '@1'. +There is no such enchantment '@1'.=L'enchantement '@1' n'existe pas. These options are randomized, and dependent on experience level; but the enchantment strength can be increased.=Ces options sont aléatoires et dépendent du niveau d'expérience ; mais la force d'enchantement peut être augmentée. To increase the enchantment strength, place bookshelves around the enchanting table. However, you will need to keep 1 air node between the table, & the bookshelves to empower the enchanting table.=Pour augmenter la force d'enchantement, placer des bibliothèques autour de la table d'enchantement. Cependant, vous devrez garder au moins un bloc d'air entre la table et les bibliothèques pour alimenter la table d'enchantement. Usage: /enchant []=Usage: /enchant [] -Usage: /forceenchant []=Usage: /forceenchant [] +Usage: /forceenchant []=Usage: /forceenchant [] ##### not used anymore ##### diff --git a/mods/ITEMS/mcl_farming/locale/mcl_farming.fr.tr b/mods/ITEMS/mcl_farming/locale/mcl_farming.fr.tr index 5174ce2ad..5b14b109b 100644 --- a/mods/ITEMS/mcl_farming/locale/mcl_farming.fr.tr +++ b/mods/ITEMS/mcl_farming/locale/mcl_farming.fr.tr @@ -31,6 +31,7 @@ Stone Hoe=Houe en pierre Iron Hoe=Houe en fer Golden Hoe=Houe en or Diamond Hoe=Houe en diamant +Netherite Hoe=Houe en netherite Melon Seeds=Graine de pastèque Grows into a melon stem which in turn grows melons. Chickens like melon seeds.=Se développe en une tige de pastèque qui à son tour forme des pastèques. Les poulets aiment les graines de pastèque. Place the melon seeds on farmland (which can be created with a hoe) to plant a melon stem. Melon stems grow in sunlight and grow faster on hydrated farmland. When mature, the stem will attempt to grow a melon at the side. Rightclick an animal to feed it melon seeds.=Placez les graines de pastèque sur les terres agricoles (qui peuvent être créées avec une houe) pour planter une tige de pastèque. Les tiges de pastèque poussent au soleil et se développent plus rapidement sur les terres agricoles hydratées. À maturité, la tige tentera de faire pousser une pastèque sur le côté. Faites un clic droit sur un animal pour le nourrir de graines de pastèque. @@ -77,12 +78,15 @@ Hydrated Farmland=Terres agricoles hydratées Hydrated farmland is used in farming, this is where you can plant and grow some plants. It is created when farmland is under rain or near water. Without water, this block will dry out eventually. This block will turn back to dirt when a solid block appears above it or a piston arm extends above it.=Les terres agricoles hydratées sont utilisées dans l'agriculture, c'est là que vous pouvez planter et faire pousser certaines plantes. Il est créé lorsque les terres agricoles sont sous la pluie ou près de l'eau. Sans eau, ce bloc finira par se dessécher. Ce bloc redeviendra de la terre lorsqu'un bloc solide apparaît au-dessus ou qu'un bras de piston s'étend au-dessus. Wheat Seeds=Graines de blé Grows into a wheat plant. Chickens like wheat seeds.=Se transforme en blé. Les poulets aiment les graines de blé. -Place the wheat seeds on farmland (which can be created with a hoe) to plant a wheat plant. They grow in sunlight and grow faster on hydrated farmland. Rightclick an animal to feed it wheat seeds.=Placez les graines de blé sur les terres agricoles (qui peuvent être créées avec une houe) pour planter une plante de blé. Ils poussent au soleil et poussent plus vite sur les terres agricoles hydratées. Faites un clic droit sur un animal pour le nourrir de graines de blé. +Place the wheat seeds on farmland (which can be created with a hoe) to plant a wheat plant.=Placez les graines de blé sur les terres agricoles (qui peuvent être créées avec une houe) pour planter une plante de blé. +They grow in sunlight and grow faster on hydrated farmland. Rightclick an animal to feed it wheat seeds.=Ils poussent au soleil et poussent plus vite sur les terres agricoles hydratées. Faites un clic droit sur un animal pour le nourrir de graines de blé. Premature Wheat Plant=Plant de blé Prématuré -Premature wheat plants grow on farmland under sunlight in 8 stages. On hydrated farmland, they grow faster. They can be harvested at any time but will only yield a profit when mature.=Les plants de blé prématurés poussent sur les terres agricoles sous la lumière du soleil en 8 étapes. Sur les terres agricoles hydratées, ils croissent plus rapidement. Ils peuvent être récoltés à tout moment mais ne rapporteront de bénéfices qu'à maturité. +Premature wheat plants grow on farmland under sunlight in 8 stages.=Les plants de blé prématurés poussent sur les terres agricoles sous la lumière du soleil en 8 étapes. +On hydrated farmland, they grow faster. They can be harvested at any time but will only yield a profit when mature.=Sur les terres agricoles hydratées, ils croissent plus rapidement. Ils peuvent être récoltés à tout moment mais ne rapporteront de bénéfices qu'à maturité. Premature Wheat Plant (Stage @1)=Plant de blé prématuré (étape @1) Mature Wheat Plant=Plant de blé mature -Mature wheat plants are ready to be harvested for wheat and wheat seeds. They won't grow any further.=Les plants de blé matures sont prêts à être récoltés pour le blé et les graines de blé. Ils ne grandiront plus. +Mature wheat plants are ready to be harvested for wheat and wheat seeds.=Les plants de blé matures sont prêts à être récoltés pour le blé et les graines de blé. +They won't grow any further.=Ils ne grandiront plus. Wheat=Blé Wheat is used in crafting. Some animals like wheat.=Le blé est utilisé dans l'artisanat. Certains animaux aiment le blé. Cookie=Cookie @@ -97,3 +101,5 @@ Turns block into farmland=Transforme un bloc en terres agricoles Surface for crops=Surface pour les cultures Can become wet=Peut devenir humide Uses: @1=Utilisations : @1 +Sweet Berry Bush (Stage @1)=Buisson de baies sucrées (étape 1) +Sweet Berry=Baie sucrée diff --git a/mods/ITEMS/mcl_farming/locale/template.txt b/mods/ITEMS/mcl_farming/locale/template.txt index 7359fefa6..bc81acce1 100644 --- a/mods/ITEMS/mcl_farming/locale/template.txt +++ b/mods/ITEMS/mcl_farming/locale/template.txt @@ -31,6 +31,7 @@ Stone Hoe= Iron Hoe= Golden Hoe= Diamond Hoe= +Netherite Hoe= Melon Seeds= Grows into a melon stem which in turn grows melons. Chickens like melon seeds.= Place the melon seeds on farmland (which can be created with a hoe) to plant a melon stem. Melon stems grow in sunlight and grow faster on hydrated farmland. When mature, the stem will attempt to grow a melon at the side. Rightclick an animal to feed it melon seeds.= @@ -77,12 +78,15 @@ Hydrated Farmland= Hydrated farmland is used in farming, this is where you can plant and grow some plants. It is created when farmland is under rain or near water. Without water, this block will dry out eventually. This block will turn back to dirt when a solid block appears above it or a piston arm extends above it.= Wheat Seeds= Grows into a wheat plant. Chickens like wheat seeds.= -Place the wheat seeds on farmland (which can be created with a hoe) to plant a wheat plant. They grow in sunlight and grow faster on hydrated farmland. Rightclick an animal to feed it wheat seeds.= +Place the wheat seeds on farmland (which can be created with a hoe) to plant a wheat plant.= +They grow in sunlight and grow faster on hydrated farmland. Rightclick an animal to feed it wheat seeds.= Premature Wheat Plant= -Premature wheat plants grow on farmland under sunlight in 8 stages. On hydrated farmland, they grow faster. They can be harvested at any time but will only yield a profit when mature.= +Premature wheat plants grow on farmland under sunlight in 8 stages.= +On hydrated farmland, they grow faster. They can be harvested at any time but will only yield a profit when mature.= Premature Wheat Plant (Stage @1)= Mature Wheat Plant= -Mature wheat plants are ready to be harvested for wheat and wheat seeds. They won't grow any further.= +Mature wheat plants are ready to be harvested for wheat and wheat seeds.= +They won't grow any further.= Wheat= Wheat is used in crafting. Some animals like wheat.= Cookie= @@ -97,3 +101,5 @@ Turns block into farmland= Surface for crops= Can become wet= Uses: @1= +Sweet Berry Bush (Stage @1)= +Sweet Berry= diff --git a/mods/ITEMS/mcl_farming/wheat.lua b/mods/ITEMS/mcl_farming/wheat.lua index 44d82b566..15fd98e2a 100644 --- a/mods/ITEMS/mcl_farming/wheat.lua +++ b/mods/ITEMS/mcl_farming/wheat.lua @@ -5,10 +5,8 @@ minetest.register_craftitem("mcl_farming:wheat_seeds", { description = S("Wheat Seeds"), _tt_help = S("Grows on farmland"), _doc_items_longdesc = S("Grows into a wheat plant. Chickens like wheat seeds."), - _doc_items_usagehelp = S([[ - Place the wheat seeds on farmland (which can be created with a hoe) to plant a wheat plant. - They grow in sunlight and grow faster on hydrated farmland. Rightclick an animal to feed it wheat seeds. - ]]), + _doc_items_usagehelp = S("Place the wheat seeds on farmland (which can be created with a hoe) to plant a wheat plant.").."\n".. + S("They grow in sunlight and grow faster on hydrated farmland. Rightclick an animal to feed it wheat seeds."), groups = {craftitem = 1, compostability = 30}, inventory_image = "mcl_farming_wheat_seeds.png", on_place = function(itemstack, placer, pointed_thing) @@ -31,10 +29,8 @@ for i=1,7 do if i == 1 then create = true name = S("Premature Wheat Plant") - longdesc = S([[ - Premature wheat plants grow on farmland under sunlight in 8 stages. - On hydrated farmland, they grow faster. They can be harvested at any time but will only yield a profit when mature. - ]]) + longdesc = S("Premature wheat plants grow on farmland under sunlight in 8 stages.").."\n".. + S("On hydrated farmland, they grow faster. They can be harvested at any time but will only yield a profit when mature.") else create = false end @@ -69,10 +65,8 @@ end minetest.register_node("mcl_farming:wheat", { description = S("Mature Wheat Plant"), - _doc_items_longdesc = S([[ - Mature wheat plants are ready to be harvested for wheat and wheat seeds. - They won't grow any further. - ]]), + _doc_items_longdesc = S("Mature wheat plants are ready to be harvested for wheat and wheat seeds.").."\n".. + S("They won't grow any further."), sunlight_propagates = true, paramtype = "light", paramtype2 = "meshoptions", diff --git a/mods/ITEMS/mcl_fences/locale/mcl_fences.fr.tr b/mods/ITEMS/mcl_fences/locale/mcl_fences.fr.tr index ccfb86d95..1044cf148 100644 --- a/mods/ITEMS/mcl_fences/locale/mcl_fences.fr.tr +++ b/mods/ITEMS/mcl_fences/locale/mcl_fences.fr.tr @@ -1,18 +1,18 @@ # textdomain: mcl_fences Fences are structures which block the way. Fences will connect to each other and solid blocks. They cannot be jumped over with a simple jump.=Les barrières sont des structures qui bloquent le chemin. Les barrières se connecteront les unes aux autres et aux blocs solides. Ils ne peuvent pas être sautés par un simple saut. -Fence gates can be opened or closed and can't be jumped over. Fences will connect nicely to fence gates.=Les portillions peuvent être ouvertes ou fermées et ne peuvent pas être sautées. Les barrières se connecteront bien aux portillions. -Right-click the fence gate to open or close it.=Cliquez avec le bouton droit sur le portillion pour l'ouvrir ou la fermer. +Fence gates can be opened or closed and can't be jumped over. Fences will connect nicely to fence gates.=Les portillons peuvent être ouvertes ou fermées et ne peuvent pas être sautées. Les barrières se connecteront bien aux portillions. +Right-click the fence gate to open or close it.=Cliquez avec le bouton droit sur le portillon pour l'ouvrir ou la fermer. Oak Fence=Barrière en bois de Chêne -Oak Fence Gate=Portillion en bois de Chêne +Oak Fence Gate=Portillon en bois de Chêne Spruce Fence=Barrière en bois de Sapin -Spruce Fence Gate=Portillion en bois de Sapin +Spruce Fence Gate=Portillon en bois de Sapin Birch Fence=Barrière en bois de Bouleau -Birch Fence Gate=Portillion en bois de Bouleau +Birch Fence Gate=Portillon en bois de Bouleau Jungle Fence=Barrière en bois d'Acajou -Jungle Fence Gate=Portillion en bois d'Acajou +Jungle Fence Gate=Portillon en bois d'Acajou Dark Oak Fence=Barrière en bois de Chêne Noir -Dark Oak Fence Gate=Portillion en bois de Chêne Noir +Dark Oak Fence Gate=Portillon en bois de Chêne Noir Acacia Fence=Barrière en bois d'Acacia -Acacia Fence Gate=Portillion en bois d'Acacia +Acacia Fence Gate=Portillon en bois d'Acacia Nether Brick Fence=Barrière en Brique du Nether Openable by players and redstone power=Ouvrable par les joueurs et la puissance redstone diff --git a/mods/ITEMS/mcl_fire/locale/mcl_fire.fr.tr b/mods/ITEMS/mcl_fire/locale/mcl_fire.fr.tr index 6ab6d906a..f585f9e02 100644 --- a/mods/ITEMS/mcl_fire/locale/mcl_fire.fr.tr +++ b/mods/ITEMS/mcl_fire/locale/mcl_fire.fr.tr @@ -1,7 +1,7 @@ # textdomain: mcl_fire Fire Charge=Boule de feu -Fire charges are primarily projectiles which can be launched from dispensers, they will fly in a straight line and burst into a fire on impact. Alternatively, they can be used to ignite fires directly.=Les boules de feu sont principalement des projectiles qui peuvent être lancés à partir de distributeurs, ils voleront en ligne droite et éclateront en feu à l'impact. Alternativement, ils peuvent être utilisés pour allumer des incendies directement. -Put the fire charge into a dispenser and supply it with redstone power to launch it. To ignite a fire directly, simply place the fire charge on the ground, which uses it up.=Mettez la boule de feu dans un distributeur et alimentez-la en redstone pour la lancer. Pour allumer un feu directement, placez simplement la charge de feu sur le sol, et utiliser le. +Fire charges are primarily projectiles which can be launched from dispensers, they will fly in a straight line and burst into a fire on impact. Alternatively, they can be used to ignite fires directly.=Les boules de feu sont principalement des projectiles qui peuvent être lancées à partir de distributeurs, elles voleront en ligne droite et éclateront en feu à l'impact. Alternativement, elles peuvent être utilisées pour allumer des incendies directement. +Put the fire charge into a dispenser and supply it with redstone power to launch it. To ignite a fire directly, simply place the fire charge on the ground, which uses it up.=Mettez la boule de feu dans un distributeur et alimentez-la en redstone pour la lancer. Pour allumer un feu directement, placez simplement la charge de feu sur le sol, et utiliser la. Flint and Steel=Briquet Flint and steel is a tool to start fires and ignite blocks.=Le briquet est un outil pour allumer un feu ou allumer des blocs. Rightclick the surface of a block to attempt to light a fire in front of it or ignite the block. A few blocks have an unique reaction when ignited.=Cliquez avec le bouton droit sur la surface d'un bloc pour tenter d'allumer un feu devant lui ou d'allumer le bloc. Quelques blocs ont une réaction unique lorsqu'ils sont enflammés. @@ -9,8 +9,8 @@ Fire is a damaging and destructive but short-lived kind of block. It will destro Fire is a damaging but non-destructive short-lived kind of block. It will disappear when there is no flammable block around. Fire does not destroy blocks, at least not in this world. It will be extinguished by nearby water and rain. Fire can be destroyed safely by punching it, but it is hurtful if you stand directly in it. If a fire is started above netherrack or a magma block, it will immediately turn into an eternal fire.=Le feu est un type de bloc éphémère mais non destructif de courte durée. Il disparaîtra en l'absence de bloc inflammable. Le feu ne détruit pas les blocs, du moins pas dans ce monde. Il sera éteint par l'eau et la pluie à proximité. Le feu peut être détruit en toute sécurité en le frappant, mais il est blessant si vous vous tenez directement dedans. Si un feu est déclenché au-dessus d'un netherrack ou d'un bloc de magma, il se transformera immédiatement en un feu éternel. Eternal fire is a damaging block that might create more fire. It will create fire around it when flammable blocks are nearby. Eternal fire can be extinguished by punches and nearby water blocks. Other than (normal) fire, eternal fire does not get extinguished on its own and also continues to burn under rain. Punching eternal fire is safe, but it hurts if you stand inside.=Le feu éternel est un bloc endommageant qui pourrait créer plus de feu. Il créera du feu autour de lui lorsque des blocs inflammables sont à proximité. Le feu éternel peut être éteint par des coups de poing et des blocs d'eau à proximité. À part le feu (normal), le feu éternel ne s'éteint pas tout seul et continue de brûler sous la pluie. Frapper le feu éternel est sûr, mais ça fait mal si vous vous tenez à l'intérieur. Eternal fire is a damaging block. Eternal fire can be extinguished by punches and nearby water blocks. Other than (normal) fire, eternal fire does not get extinguished on its own and also continues to burn under rain. Punching eternal fire is safe, but it hurts if you stand inside.=Le feu éternel est un bloc dommageable. Le feu éternel peut être éteint par des coups de poing et des blocs d'eau à proximité. À part le feu (normal), le feu éternel ne s'éteint pas tout seul et continue de brûler sous la pluie. Frapper le feu éternel est sûr, mais ça fait mal si vous vous tenez à l'intérieur. -@1 has been cooked crisp.=@1 a été cuit croustillant. -@1 felt the burn.=@1 sent le brûler. +@1 has been cooked crisp.=@1 a été grillé comme une saucisse. +@1 felt the burn.=@1 sent le brûlé. @1 died in the flames.=@1 est mort dans les flammes. @1 died in a fire.=@1 est mort dans un incendie. Fire=Feu diff --git a/mods/ITEMS/mcl_flowers/locale/mcl_flowers.fr.tr b/mods/ITEMS/mcl_flowers/locale/mcl_flowers.fr.tr index 945a799e2..c96a585f9 100644 --- a/mods/ITEMS/mcl_flowers/locale/mcl_flowers.fr.tr +++ b/mods/ITEMS/mcl_flowers/locale/mcl_flowers.fr.tr @@ -11,6 +11,9 @@ White Tulip=Tulipe Blanche Allium=Allium Azure Bluet=Houstonie Bleue Blue Orchid=Orchidée Bleue +Wither Rose=Rose de Wither +Lily of the Valley=Muguet +Cornflower=Bleuet Tall Grass=Hautes herbes Tall grass is a small plant which often occurs on the surface of grasslands. It can be harvested for wheat seeds. By using bone meal, tall grass can be turned into double tallgrass which is two blocks high.=L'herbe haute est une petite plante qui se rencontre souvent à la surface des prairies. Il peut être récolté pour les graines de blé. En utilisant de la farine d'os, les hautes herbes peuvent être transformées en herbes hautes doubles de deux blocs de hauteur. Fern=Fougère diff --git a/mods/ITEMS/mcl_furnaces/init.lua b/mods/ITEMS/mcl_furnaces/init.lua index 59cfe7858..8cb8ad5a0 100644 --- a/mods/ITEMS/mcl_furnaces/init.lua +++ b/mods/ITEMS/mcl_furnaces/init.lua @@ -440,12 +440,10 @@ minetest.register_node("mcl_furnaces:furnace", { _tt_help = S("Uses fuel to smelt or cook items"), _doc_items_longdesc = S("Furnaces cook or smelt several items, using a furnace fuel, into something else."), _doc_items_usagehelp = - S([[ - Use the furnace to open the furnace menu. - Place a furnace fuel in the lower slot and the source material in the upper slot. - The furnace will slowly use its fuel to smelt the item. - The result will be placed into the output slot at the right side. - ]]).."\n".. + S("Use the furnace to open the furnace menu.").."\n".. + S("Place a furnace fuel in the lower slot and the source material in the upper slot.").."\n".. + S("The furnace will slowly use its fuel to smelt the item.").."\n".. + S("The result will be placed into the output slot at the right side.").."\n".. S("Use the recipe book to see what you can smelt, what you can use as fuel and how long it will burn."), _doc_items_hidden = false, tiles = { diff --git a/mods/ITEMS/mcl_furnaces/locale/mcl_furnaces.fr.tr b/mods/ITEMS/mcl_furnaces/locale/mcl_furnaces.fr.tr index deec7981c..4db2fc103 100644 --- a/mods/ITEMS/mcl_furnaces/locale/mcl_furnaces.fr.tr +++ b/mods/ITEMS/mcl_furnaces/locale/mcl_furnaces.fr.tr @@ -1,7 +1,10 @@ # textdomain: mcl_furnaces Furnace=Four Furnaces cook or smelt several items, using a furnace fuel, into something else.=Les fours cuisent ou fondent plusieurs articles, en utilisant un combustible de four, dans quelque chose d'autre. -Use the furnace to open the furnace menu. Place a furnace fuel in the lower slot and the source material in the upper slot. The furnace will slowly use its fuel to smelt the item. The result will be placed into the output slot at the right side.=Utilisez le four pour ouvrir le menu du four. Placez un combustible de four dans la fente inférieure et le matériau source dans la fente supérieure. Le four utilisera lentement son combustible pour fondre l'article. Le résultat sera placé dans la fente de sortie du côté droit. +Use the furnace to open the furnace menu.=Utilisez le four pour ouvrir le menu du four. +Place a furnace fuel in the lower slot and the source material in the upper slot.=Placez un combustible de four dans la fente inférieure et le matériau source dans la fente supérieure. +The furnace will slowly use its fuel to smelt the item.=Le four utilisera lentement son combustible pour fondre l'article. +The result will be placed into the output slot at the right side.=Le résultat sera placé dans la fente de sortie du côté droit. Use the recipe book to see what you can smelt, what you can use as fuel and how long it will burn.=Utilisez le livre de recettes pour voir ce que vous pouvez cuire, ce que vous pouvez utiliser comme carburant et combien de temps il brûlera. Burning Furnace=Four Allumé Recipe book=Livre de Recette diff --git a/mods/ITEMS/mcl_furnaces/locale/template.txt b/mods/ITEMS/mcl_furnaces/locale/template.txt index 4f88824b0..e19259437 100644 --- a/mods/ITEMS/mcl_furnaces/locale/template.txt +++ b/mods/ITEMS/mcl_furnaces/locale/template.txt @@ -1,7 +1,10 @@ # textdomain: mcl_furnaces Furnace= Furnaces cook or smelt several items, using a furnace fuel, into something else.= -Use the furnace to open the furnace menu. Place a furnace fuel in the lower slot and the source material in the upper slot. The furnace will slowly use its fuel to smelt the item. The result will be placed into the output slot at the right side.= +Use the furnace to open the furnace menu.= +Place a furnace fuel in the lower slot and the source material in the upper slot.= +The furnace will slowly use its fuel to smelt the item.= +The result will be placed into the output slot at the right side.= Use the recipe book to see what you can smelt, what you can use as fuel and how long it will burn.= Burning Furnace= Recipe book= diff --git a/mods/ITEMS/mcl_honey/locale/mcl_honey.fr.tr b/mods/ITEMS/mcl_honey/locale/mcl_honey.fr.tr new file mode 100644 index 000000000..67ef904c9 --- /dev/null +++ b/mods/ITEMS/mcl_honey/locale/mcl_honey.fr.tr @@ -0,0 +1,11 @@ +# textdomain: mcl_honey +Honeycomb=Cire +Used to craft beehives and protect copper blocks from further oxidation.=Utilisé pour fabriquer les ruches et protéger des blocs de l'oxydation. +Use on copper blocks to prevent further oxidation.=À utiliser sur les blocs de cuivre pour les protéger de l'oxydation. +Honeycomb Block=Bloc de cire +Honeycomb Block. Used as a decoration.=Bloc de cire. Utilisé en cire. +Honey Bottle=Bouteille de miel +Honey Bottle is used to craft honey blocks and to restore hunger points.=Une bouteille sert à fabriquer des bloc de miel et à restaurer des points de faim. +Drinking will restore 6 hunger points. Can also be used to craft honey blocks.=Boire ceci restaure 6 points de faim. +Honey Block=Bloc de miel +Honey Block. Used as a decoration and in redstone. Is sticky on some sides.=Bloc de miel. Utilisé comme décoration et avec la redstone. Il est collant sur certains côtés. diff --git a/mods/ITEMS/mcl_honey/locale/mcl_honey.ja.tr b/mods/ITEMS/mcl_honey/locale/mcl_honey.ja.tr index 4cb018f84..c4ef54411 100644 --- a/mods/ITEMS/mcl_honey/locale/mcl_honey.ja.tr +++ b/mods/ITEMS/mcl_honey/locale/mcl_honey.ja.tr @@ -1,3 +1,4 @@ +# textdomain: mcl_honey Honeycomb=ハニカム Used to craft beehives and protect copper blocks from further oxidation.=ハチの巣を作ったり、銅ブロックがこれ以上酸化しないように保護するために使われます。 Use on copper blocks to prevent further oxidation.=銅ブロックに使用すると、これ以上の酸化を防げます。 diff --git a/mods/ITEMS/mcl_honey/locale/template.txt b/mods/ITEMS/mcl_honey/locale/template.txt index a9814d617..3cdeec570 100644 --- a/mods/ITEMS/mcl_honey/locale/template.txt +++ b/mods/ITEMS/mcl_honey/locale/template.txt @@ -1,3 +1,4 @@ +# textdomain: mcl_honey Honeycomb= Used to craft beehives and protect copper blocks from further oxidation.= Use on copper blocks to prevent further oxidation.= diff --git a/mods/ITEMS/mcl_hoppers/locale/mcl_hoppers.fr.tr b/mods/ITEMS/mcl_hoppers/locale/mcl_hoppers.fr.tr index 1e3d4806b..7458ebfc1 100644 --- a/mods/ITEMS/mcl_hoppers/locale/mcl_hoppers.fr.tr +++ b/mods/ITEMS/mcl_hoppers/locale/mcl_hoppers.fr.tr @@ -1,12 +1,12 @@ # textdomain: mcl_hoppers Hopper=Entonnoir Hoppers are containers with 5 inventory slots. They collect dropped items from above, take items from a container above and attempt to put its items it into an adjacent container. Hoppers can go either downwards or sideways. Hoppers interact with chests, droppers, dispensers, shulker boxes, furnaces and hoppers.=Les entonnoirs sont des conteneurs avec 5 emplacements d'inventaire. Ils récupèrent les objets déposés par le haut, prennent les objets d'un conteneur au-dessus et tentent de les placer dans un conteneur adjacent. Les entonnoirs peuvent aller vers le bas ou sur le côté. Les entonnoirs interagissent avec les coffres, les compte-gouttes, les distributeurs, les boites de shulker, les fours et les entonnoirs. -Hoppers interact with containers the following way:=Les entonnoirs interagissent avec les conteneurs de la manière suivante: +Hoppers interact with containers the following way:=Les entonnoirs interagissent avec les conteneurs de la manière suivante : • Furnaces: Hoppers from above will put items into the source slot. Hoppers from below take items from the output slot. They also take items from the fuel slot when they can't be used as a fuel. Sideway hoppers that point to the furnace put items into the fuel slot=• Fours: les entonnoirs d'en haut placent les objets dans l'emplacement source. Les entonnoirs d'en bas prennent les éléments de la fente de sortie. Ils prennent également des objets de la fente de carburant lorsqu'ils ne peuvent pas être utilisés comme carburant. Des entonnoirs latérales qui pointent vers le four mettent des objets dans la fente de combustible -• Ender chests: No interaction.=• Coffres Ender: Aucune interaction. +• Ender chests: No interaction.=• Coffres Ender : Aucune interaction. • Other containers: Normal interaction.=• Autres conteneurs: interaction normale. -Hoppers can be disabled when supplied with redstone power. Disabled hoppers don't move items.=Les entonnoirs peuvent être désactivées lorsqu'elles sont alimentées en redstone. Les trémies désactivées ne déplacent pas les objets. -To place a hopper vertically, place it on the floor or a ceiling. To place it sideways, place it at the side of a block. Use the hopper to access its inventory.=Pour placer un entonnoir verticalement, placez-la au sol ou au plafond. Pour le placer sur le côté, placez-le sur le côté d'un bloc. Utilisez l'entonnoir pour accéder à son inventaire. +Hoppers can be disabled when supplied with redstone power. Disabled hoppers don't move items.=Les entonnoirs peuvent être désactivées lorsqu'ils sont alimentés en redstone. Les entonnoirs désactivés ne déplacent pas les objets. +To place a hopper vertically, place it on the floor or a ceiling. To place it sideways, place it at the side of a block. Use the hopper to access its inventory.=Pour placer un entonnoir verticalement, placez-le au sol ou au plafond. Pour le placer sur le côté, placez-le sur le côté d'un bloc. Utilisez l'entonnoir pour accéder à son inventaire. Disabled Hopper=Entonnoir désactivé Side Hopper=Entonnoir latéral Disabled Side Hopper=Entonnoir latéral désactivé diff --git a/mods/ITEMS/mcl_itemframes/init.lua b/mods/ITEMS/mcl_itemframes/init.lua index 553198c67..1f53f8250 100644 --- a/mods/ITEMS/mcl_itemframes/init.lua +++ b/mods/ITEMS/mcl_itemframes/init.lua @@ -14,11 +14,11 @@ mcl_itemframes.backwards_compatibility() -- Define the standard frames. mcl_itemframes.create_custom_frame("false", "item_frame", false, - "mcl_itemframes_item_frame.png", mcl_colors.WHITE, "Can hold an item.", - "Item Frame", "") + "mcl_itemframes_item_frame.png", mcl_colors.WHITE, S("Can hold an item."), + S("Item Frame"), "") mcl_itemframes.create_custom_frame("false", "glow_item_frame", true, - "mcl_itemframes_glow_item_frame.png", mcl_colors.WHITE, "Can hold an item and glows.", - "Glowing Item Frame", "") + "mcl_itemframes_glow_item_frame.png", mcl_colors.WHITE, S("Can hold an item and glows."), + S("Glowing Item Frame"), "") -- Register the base frame's recipes. -- was going to make it a specialized function, but minetest refuses to play nice. diff --git a/mods/ITEMS/mcl_itemframes/item_frames_API.lua b/mods/ITEMS/mcl_itemframes/item_frames_API.lua index 142de4824..999becf05 100644 --- a/mods/ITEMS/mcl_itemframes/item_frames_API.lua +++ b/mods/ITEMS/mcl_itemframes/item_frames_API.lua @@ -623,7 +623,7 @@ function mcl_itemframes.create_base_definitions() mcl_itemframes.item_frame_base = { description = S("Item Frame"), name = "mcl_itemframes:item_frame", - _tt_help = S("Can hold an item"), + _tt_help = S("Can hold an item."), _doc_items_longdesc = S("Item frames are decorative blocks in which items can be placed."), _doc_items_usagehelp = S("Just place any item on the item frame. Use the item frame again to retrieve the item."), drawtype = "mesh", diff --git a/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.fr.tr b/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.fr.tr index e847779f2..7ff510cb2 100644 --- a/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.fr.tr +++ b/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.fr.tr @@ -2,7 +2,9 @@ Item Frame=Cadre de l'article Item frames are decorative blocks in which items can be placed.=Les cadres d'objets sont des blocs décoratifs dans lesquels des objets peuvent être placés. Just place any item on the item frame. Use the item frame again to retrieve the item.=Placez simplement n'importe quel élément sur le cadre de l'élément. Utilisez à nouveau le cadre de l'objet pour récupérer l'objet. -Can hold an item.=Peut contenir un objet. +Can hold an item.=Peut contenir un objet Glowing Item Frame=Cadre d'objet lumineux -Glowing item frames are decorative blocks in which items can be placed and made to glow.=Les cadres d'objets lumineux sont des blocs décoratifs dans lesquels des objets peuvent être placés et rendus brillants. -Can hold an item and glows.=Peut contenir un objet et brille. +Glowing item frames are decorative blocks in which items can be placed.=Les cadres d'objets lumineux sont des blocs décoratifs dans lesquels des objets peuvent être placés. +Can hold an item and glows.=Peut contenir un objet et brille +Glow and Behold!=Une idée brillante ! +Craft a glow item frame.=Fabriquez un cadre brillant. diff --git a/mods/ITEMS/mcl_itemframes/locale/template.txt b/mods/ITEMS/mcl_itemframes/locale/template.txt index 87cd55c65..bd5ff6f29 100644 --- a/mods/ITEMS/mcl_itemframes/locale/template.txt +++ b/mods/ITEMS/mcl_itemframes/locale/template.txt @@ -2,7 +2,9 @@ Item Frame= Item frames are decorative blocks in which items can be placed.= Just place any item on the item frame. Use the item frame again to retrieve the item.= -Can hold an item= -Glow Item Frame= -Glow item frames are decorative blocks in which items can be placed.= -Can hold an item and glows= +Can hold an item.= +Glowing Item Frame= +Glowing item frames are decorative blocks in which items can be placed.= +Can hold an item and glows.= +Glow and Behold!= +Craft a glow item frame.= diff --git a/mods/ITEMS/mcl_lectern/locale/mcl_lectern.fr.tr b/mods/ITEMS/mcl_lectern/locale/mcl_lectern.fr.tr new file mode 100644 index 000000000..c068052e1 --- /dev/null +++ b/mods/ITEMS/mcl_lectern/locale/mcl_lectern.fr.tr @@ -0,0 +1,4 @@ +# textdomain: mcl_lectern +Lectern=Pupitre +Lecterns not only look good, but are job site blocks for Librarians.=Les pupitres ne sont pas seulement décoratifs, ils sont aussi le poste de travail des Bibliothécaires. +Place the Lectern on a solid node for best results. May attract villagers, so it's best to place outside of where you call 'home'.=Placer le Pupitre sur un bloc solide pour de meilleurs résultats. Il peut attirer les villageois, donc il vaut mieux le placer en dehors de chez vous. diff --git a/mods/ITEMS/mcl_lectern/locale/template.txt b/mods/ITEMS/mcl_lectern/locale/template.txt new file mode 100644 index 000000000..b3232a93b --- /dev/null +++ b/mods/ITEMS/mcl_lectern/locale/template.txt @@ -0,0 +1,4 @@ +# textdomain: mcl_lectern +Lectern= +Lecterns not only look good, but are job site blocks for Librarians.= +Place the Lectern on a solid node for best results. May attract villagers, so it's best to place outside of where you call 'home'.= \ No newline at end of file diff --git a/mods/ITEMS/mcl_mangrove/locale/mcl_mangrove.fr.tr b/mods/ITEMS/mcl_mangrove/locale/mcl_mangrove.fr.tr index b47ed9136..f898a58a7 100644 --- a/mods/ITEMS/mcl_mangrove/locale/mcl_mangrove.fr.tr +++ b/mods/ITEMS/mcl_mangrove/locale/mcl_mangrove.fr.tr @@ -30,7 +30,7 @@ Mangrove Trapdoor=Trappe en palétuvier Wooden trapdoors are horizontal barriers which can be opened and closed by hand or a redstone signal. They occupy the upper or lower part of a block, depending on how they have been placed. When open, they can be climbed like a ladder.=Les trappes de bois sont des barrières horizontales qui peuvent être ouvertes et fermées à la main ou avec un signal redstone. Elles occupent la partie haut ou bas d'un bloc, selon la manière dont elles ont été placées. To open or close the trapdoor, rightclick it or send a redstone signal to it.=Pour ouvrir et fermer la trappe, faire un clic droit ou lui envoyer un signal redstone. Mangrove Wood Fence=Barrière de palétuvier -Mangrove Wood Fence Gate=Portillion de palétuvier +Mangrove Wood Fence Gate=Portillon de palétuvier Mangrove Wood Stairs=Escalier en bois de palétuvier Mangrove Wood Slab=Dalle en bois de palétuvier Double Mangrove Wood Slab=Double Dalle en bois de palétuvier diff --git a/mods/ITEMS/mcl_mobitems/init.lua b/mods/ITEMS/mcl_mobitems/init.lua index eeec953a2..2dcfc6372 100644 --- a/mods/ITEMS/mcl_mobitems/init.lua +++ b/mods/ITEMS/mcl_mobitems/init.lua @@ -339,7 +339,7 @@ minetest.register_tool("mcl_mobitems:warped_fungus_on_a_stick", { description = S("Warped fungus on a Stick"), _tt_help = S("Lets you ride a strider"), _doc_items_longdesc = S("A warped fungus on a stick can be used on saddled striders to ride them."), - _doc_items_usagehelp = S("Place it on a saddled strider to mount it. You can now ride the strider like a horse. Striders will also walk towards you when you just wield the carrot on a stick."), + _doc_items_usagehelp = S("Place it on a saddled strider to mount it. You can now ride the strider like a horse. Striders will also walk towards you when you just wield the fungus on a stick."), wield_image = "mcl_mobitems_warped_fungus_on_a_stick.png^[transformFY^[transformR90", inventory_image = "mcl_mobitems_warped_fungus_on_a_stick.png", groups = { transport = 1 }, diff --git a/mods/ITEMS/mcl_mobitems/locale/mcl_mobitems.fr.tr b/mods/ITEMS/mcl_mobitems/locale/mcl_mobitems.fr.tr index 82d1f173b..9e94befa4 100644 --- a/mods/ITEMS/mcl_mobitems/locale/mcl_mobitems.fr.tr +++ b/mods/ITEMS/mcl_mobitems/locale/mcl_mobitems.fr.tr @@ -53,7 +53,7 @@ Bones can be used to tame wolves so they will protect you. They are also useful Wield the bone near wolves to attract them. Use the “Place” key on the wolf to give it a bone and tame it. You can then give commands to the tamed wolf by using the “Place” key on it.=Maniez l'os près des loups pour les attirer. Utilisez la touche «Placer» sur le loup pour lui donner un os et l'apprivoiser. Vous pouvez ensuite donner des commandes au loup apprivoisé en utilisant la touche "Placer" sur celui-ci. Squid Ink Sac=Poche d'encre -This item is dropped by dead squids. Squid ink can be used to as an ingredient to craft book and quill or black dye.= +This item is dropped by dead squids. Squid ink can be used to as an ingredient to craft book and quill or black dye.=Cet objet est lâché par des poulpes morts. L'encre de poulpe peut être utilisée comme ingrédient pour fabriquer des livres et plume ou de l'encre noire. String=Ficelle Strings are used in crafting.=Les ficelles sont utilisées dans l'artisanat. @@ -96,16 +96,25 @@ A carrot on a stick can be used on saddled pigs to ride them.=Une carotte sur un Place it on a saddled pig to mount it. You can now ride the pig like a horse. Pigs will also walk towards you when you just wield the carrot on a stick.=Placez-le sur un cochon sellé pour le monter. Vous pouvez maintenant monter le cochon comme un cheval. Les porcs marcheront également vers vous lorsque vous brandirez la carotte sur un bâton. +Warped fungus on a Stick=Champignon tordu sur un bâton +Lets you ride a strider=Vous permet de monter un arpenteur +A warped fungus on a stick can be used on saddled striders to ride them.=Un champignon tordu sur un bâton peut être utilisé sur les arpenteurs sellés pour les monter. +Place it on a saddled strider to mount it. You can now ride the strider like a horse. Striders will also walk towards you when you just wield the fungus on a stick.=Placez-le sur un arpenteur sellé pour le monter. Vous pouvez maintenant monter l'arpenteur comme un cheval. Les arpenteurs marcheront également vers vous lorsque vous brandirez le champignon sur un bâton. + Nautilus Shell=Coquille de nautile Used to craft a conduit=Utilisé pour fabriquer un conduit. The Nautilus Shell is used to craft a conduit. They can be obtained by fishing or killing a drowned that is wielding a shell.=La Coquille de nautile est utilisée pour fabriquer un conduit. Elles peuvent être obtenues en pêchant ou en tuant un noyé qui tient une coquille. Heart of the Sea=Coeur de la Mer -The Heart of the Sea is used to craft a conduit. They can be obtained by finding them in a buried treasure chest.=Le Coeur de la Mer est utilisé pour fabriquer un conduit. Il peut être obtenu dans un coffre au trésor enterré. +The Heart of the Sea is used to craft a conduit. They can be obtained by finding them in a buried treasure chest.=Le Cœur de la Mer est utilisé pour fabriquer un conduit. Il peut être obtenu dans un coffre au trésor enterré. Iron Horse Armor=Armure de cheval en fer Iron horse armor can be worn by horses to increase their protection from harm a bit.=L'armure de cheval en fer peut être portée par les chevaux pour augmenter un peu leur protection contre les dégâts. Golden Horse Armor=Armure de cheval en or Golden horse armor can be worn by horses to increase their protection from harm.=Une armure de cheval en or peut être portée par les chevaux pour augmenter leur protection contre les dégâts. Diamond Horse Armor=Armure de cheval en diamant -Diamond horse armor can be worn by horses to greatly increase their protection from harm.=Une armure de cheval en diament peut être portée par les chevaux pour augmenter fortement leur protection contre les dégâts. +Diamond horse armor can be worn by horses to greatly increase their protection from harm.=Une armure de cheval en diamant peut être portée par les chevaux pour augmenter fortement leur protection contre les dégâts. Place it on a horse to put on the horse armor. Donkeys and mules can't wear horse armor.=Placez-la sur un cheval pour mettre l'armure de cheval. Les ânes et les mules ne peuvent pas porter d'armure de cheval. + +Glow Ink Sac=Poche d'encre brillante +Use it to craft the Glow Item Frame.=Utilisez la pour fabriquer un Cadre d'objet brillant. +Use the Glow Ink Sac and the normal Item Frame to craft the Glow Item Frame.=Utilisez la Poche d'encre brillante et le Cadre d'objet normal pour fabriquer le Cadre d'objet brillant. diff --git a/mods/ITEMS/mcl_mobitems/locale/template.txt b/mods/ITEMS/mcl_mobitems/locale/template.txt index f26ab52d7..dd97fa0dd 100644 --- a/mods/ITEMS/mcl_mobitems/locale/template.txt +++ b/mods/ITEMS/mcl_mobitems/locale/template.txt @@ -96,6 +96,11 @@ A carrot on a stick can be used on saddled pigs to ride them.= Place it on a saddled pig to mount it. You can now ride the pig like a horse. Pigs will also walk towards you when you just wield the carrot on a stick.= +Warped fungus on a Stick= +Lets you ride a strider= +A warped fungus on a stick can be used on saddled striders to ride them.= +Place it on a saddled strider to mount it. You can now ride the strider like a horse. Striders will also walk towards you when you just wield the fungus on a stick.= + Nautilus Shell= Used to craft a conduit= The Nautilus Shell is used to craft a conduit. They can be obtained by fishing or killing a drowned that is wielding a shell.= @@ -109,3 +114,7 @@ Golden horse armor can be worn by horses to increase their protection from harm. Diamond Horse Armor= Diamond horse armor can be worn by horses to greatly increase their protection from harm.= Place it on a horse to put on the horse armor. Donkeys and mules can't wear horse armor.= + +Glow Ink Sac= +Use it to craft the Glow Item Frame.= +Use the Glow Ink Sac and the normal Item Frame to craft the Glow Item Frame.= diff --git a/mods/ITEMS/mcl_monster_eggs/init.lua b/mods/ITEMS/mcl_monster_eggs/init.lua index 59ab72876..f58717d04 100644 --- a/mods/ITEMS/mcl_monster_eggs/init.lua +++ b/mods/ITEMS/mcl_monster_eggs/init.lua @@ -23,10 +23,7 @@ local function register_block(subname, description, tiles, is_ground_content) sounds = mcl_sounds.node_sound_stone_defaults(), after_dig_node = spawn_silverfish, _tt_help = S("Hides a silverfish"), - _doc_items_longdesc = S([[ - An infested block is a block from which a silverfish will pop out when it is broken. - It looks identical to its normal counterpart. - ]]), + _doc_items_longdesc = S("An infested block is a block from which a silverfish will pop out when it is broken. It looks identical to its normal counterpart."), _mcl_hardness = 0, _mcl_blast_resistance = 0.5, }) diff --git a/mods/ITEMS/mcl_nether/locale/mcl_nether.fr.tr b/mods/ITEMS/mcl_nether/locale/mcl_nether.fr.tr index 864715eb7..70d8ca8e0 100644 --- a/mods/ITEMS/mcl_nether/locale/mcl_nether.fr.tr +++ b/mods/ITEMS/mcl_nether/locale/mcl_nether.fr.tr @@ -38,8 +38,9 @@ Place this item on soul sand to plant it and watch it grow.=Placez cet article s Burns your feet=Vous brûle les pieds Grows on soul sand=Pousse sur le sable de l'âme Reduces walking speed=Réduit la vitesse de marche -Netherite Scrap=Fragments de Netherite -Netherite Ingot=Lingot de Netherite +Netherite Scrap=Fragments de netherite +Netherite Ingot=Lingot de netherite Ancient Debris=Débris antiques -Netherite Block=Bloc de Netherite -Netherite block is very hard and can be made of 9 netherite ingots.=Les blocs de netherite sont très durs et peuvent être fabriqués à partir de 9 lingots de netherite. \ No newline at end of file +Ancient debris can be found in the nether and is very very rare.=Les débris antiques se trouvent dans le Nether et sont extrêmement rares. +Netherite Block=Bloc de netherite +Netherite block is very hard and can be made of 9 netherite ingots.=Les blocs de netherite sont très durs et peuvent être fabriqués à partir de 9 lingots de netherite. diff --git a/mods/ITEMS/mcl_nether/locale/template.txt b/mods/ITEMS/mcl_nether/locale/template.txt index 283472f63..de0fabcfb 100644 --- a/mods/ITEMS/mcl_nether/locale/template.txt +++ b/mods/ITEMS/mcl_nether/locale/template.txt @@ -41,5 +41,6 @@ Reduces walking speed= Netherite Scrap= Netherite Ingot= Ancient Debris= +Ancient debris can be found in the nether and is very very rare.= Netherite Block= -Netherite block is very hard and can be made of 9 netherite ingots.= \ No newline at end of file +Netherite block is very hard and can be made of 9 netherite ingots.= diff --git a/mods/ITEMS/mcl_portals/locale/mcl_portals.fr.tr b/mods/ITEMS/mcl_portals/locale/mcl_portals.fr.tr index 680e737b2..714075502 100644 --- a/mods/ITEMS/mcl_portals/locale/mcl_portals.fr.tr +++ b/mods/ITEMS/mcl_portals/locale/mcl_portals.fr.tr @@ -9,7 +9,7 @@ End Portal Frame with Eye of Ender=Cadre de portail de l'End avec œil d'Ender Nether Portal=Portail du Nether A Nether portal teleports creatures and objects to the hot and dangerous Nether dimension (and back!). Enter at your own risk!=Un portail du Nether téléporte des créatures et des objets dans la chaude et dangereuse dimension du Nether (et vice-versa !). Entrez à vos risques et périls ! Stand in the portal for a moment to activate the teleportation. Entering a Nether portal for the first time will also create a new portal in the other dimension. If a Nether portal has been built in the Nether, it will lead to the Overworld. A Nether portal is destroyed if the any of the obsidian which surrounds it is destroyed, or if it was caught in an explosion.=Tenez-vous un instant dans le portail pour activer la téléportation. Entrer pour la première fois sur un portail Nether créera également un nouveau portail dans l'Overworld. Si un portail du Nether a été construit dans le Nether, il mènera à l'Overworld. Un portail du Nether est détruit si l'une des obsidiennes qui l'entourent est détruite, ou s'il a été pris dans une explosion. -Obsidian is also used as the frame of Nether portals.=Obsidian is also used as the frame of Nether portals. +Obsidian is also used as the frame of Nether portals.=L'obsidienne est aussi utilisée comme cadre des portails du Nether. To open a Nether portal, place an upright frame of obsidian with a width of at least 4 blocks and a height of 5 blocks, leaving only air in the center. After placing this frame, light a fire in the obsidian frame. Nether portals only work in the Overworld and the Nether.=Pour ouvrir un portail du Nether, placez un cadre vertical d'obsidienne d'une largeur d'au moins 4 blocs et d'une hauteur de 5 blocs, ne laissant que de l'air au centre. Après avoir placé ce cadre, allumez un feu dans le cadre d'obsidienne. Les portails du Nether ne fonctionnent que dans l'Overworld et le Nether. Once placed, an eye of ender can not be taken back.=Une fois placé, un œil d'Ender ne peut pas être repris. Used to construct end portals=Utilisé pour construire des portails de l'End diff --git a/mods/ITEMS/mcl_raw_ores/locale/mcl_raw_ores.fr.tr b/mods/ITEMS/mcl_raw_ores/locale/mcl_raw_ores.fr.tr index e77ef66c4..a82da25e9 100644 --- a/mods/ITEMS/mcl_raw_ores/locale/mcl_raw_ores.fr.tr +++ b/mods/ITEMS/mcl_raw_ores/locale/mcl_raw_ores.fr.tr @@ -1,9 +1,9 @@ # textdomain: mcl_raw_ores Raw Iron=Fer brut Raw Gold=Or brut -Raw Iron. Mine an Iron ore to get it.=Fer brut. Miner du minerai de fer pour en obtenir. -Raw Gold. Mine a Gold ore to get it.=Or brut. Miner du minerai d'or pour en obtenir. +Raw iron. Mine an iron ore to get it.=Fer brut. Miner du minerai de fer pour en obtenir. +Raw gold. Mine a gold ore to get it.=Or brut. Miner du minerai d'or pour en obtenir. Block of Raw Iron=Bloc de fer brut Block of Raw Gold=Bloc d'or brut -A block of raw Iron is mostly a decorative block but also useful as a compact storage of raw Iron.=Un bloc de fer brut est principalement un bloc décoratif mais aussi utile comme stockage compact de fer brut. -A block of raw Gold is mostly a decorative block but also useful as a compact storage of raw Gold.=Un bloc d'or brut est principalement un bloc décoratif mais aussi utile comme stockage compact d'or brut. +A block of raw iron is mostly a decorative block but also useful as a compact storage of raw iron.=Un bloc de fer brut est principalement un bloc décoratif mais aussi utile comme stockage compact de fer brut. +A block of raw gold is mostly a decorative block but also useful as a compact storage of raw gold.=Un bloc d'or brut est principalement un bloc décoratif mais aussi utile comme stockage compact d'or brut. diff --git a/mods/ITEMS/mcl_raw_ores/locale/mcl_raw_ores.ja.tr b/mods/ITEMS/mcl_raw_ores/locale/mcl_raw_ores.ja.tr index 9be029657..dc0b8955e 100644 --- a/mods/ITEMS/mcl_raw_ores/locale/mcl_raw_ores.ja.tr +++ b/mods/ITEMS/mcl_raw_ores/locale/mcl_raw_ores.ja.tr @@ -1,9 +1,9 @@ # textdomain: mcl_raw_ores Raw Iron=鉄の粗鉱 Raw Gold=金の粗鉱 -Raw Iron. Mine an Iron ore to get it.=未処理の鉄。鉄鉱石を採掘して入手します。 -Raw Gold. Mine a Gold ore to get it.=未処理の金。金鉱石を採掘して入手します。 +Raw iron. Mine an iron ore to get it.=未処理の鉄。鉄鉱石を採掘して入手します。 +Raw gold. Mine a gold ore to get it.=未処理の金。金鉱石を採掘して入手します。 Block of Raw Iron=鉄の粗鉱ブロック Block of Raw Gold=金の粗鉱ブロック -A block of raw Iron is mostly a decorative block but also useful as a compact storage of raw Iron.=鉄の粗鉱ブロックは、主に装飾用のブロックですが、鉄の粗鉱をコンパクトに収納するのにも便利です。 -A block of raw Gold is mostly a decorative block but also useful as a compact storage of raw Gold.=金の粗鉱ブロックは、主に装飾用のブロックですが、金の粗鉱をコンパクトに収納するのにも便利です。 \ No newline at end of file +A block of raw iron is mostly a decorative block but also useful as a compact storage of raw iron.=鉄の粗鉱ブロックは、主に装飾用のブロックですが、鉄の粗鉱をコンパクトに収納するのにも便利です。 +A block of raw gold is mostly a decorative block but also useful as a compact storage of raw gold.=金の粗鉱ブロックは、主に装飾用のブロックですが、金の粗鉱をコンパクトに収納するのにも便利です。 diff --git a/mods/ITEMS/mcl_raw_ores/locale/template.txt b/mods/ITEMS/mcl_raw_ores/locale/template.txt index c9913e5c9..a9927aafa 100644 --- a/mods/ITEMS/mcl_raw_ores/locale/template.txt +++ b/mods/ITEMS/mcl_raw_ores/locale/template.txt @@ -1,9 +1,9 @@ # textdomain: mcl_raw_ores Raw Iron= Raw Gold= -Raw Iron. Mine an Iron ore to get it.= -Raw Gold. Mine a Gold ore to get it.= +Raw iron. Mine an iron ore to get it.= +Raw gold. Mine a gold ore to get it.= Block of Raw Iron= Block of Raw Gold= -A block of raw Iron is mostly a decorative block but also useful as a compact storage of raw Iron.= -A block of raw Gold is mostly a decorative block but also useful as a compact storage of raw Gold.= \ No newline at end of file +A block of raw iron is mostly a decorative block but also useful as a compact storage of raw iron.= +A block of raw gold is mostly a decorative block but also useful as a compact storage of raw gold.= diff --git a/mods/ITEMS/mcl_sculk/locale/mcl_sculk.fr.tr b/mods/ITEMS/mcl_sculk/locale/mcl_sculk.fr.tr new file mode 100644 index 000000000..fd9a1b973 --- /dev/null +++ b/mods/ITEMS/mcl_sculk/locale/mcl_sculk.fr.tr @@ -0,0 +1,7 @@ +# textdomain: mcl_sculk +Sculk=Sculk +Sculk Vein=Veine de sculk +Sculk vein.=Veine de sculk. +Sculk Catalyst=Catalyseur de sculk +Sculk Sensor=Capteur sculk +Sculk Shrieker=Hurleur sculk \ No newline at end of file diff --git a/mods/ITEMS/mcl_sculk/locale/template.txt b/mods/ITEMS/mcl_sculk/locale/template.txt new file mode 100644 index 000000000..8f2b3973d --- /dev/null +++ b/mods/ITEMS/mcl_sculk/locale/template.txt @@ -0,0 +1,7 @@ +# textdomain: mcl_sculk +Sculk= +Sculk Vein= +Sculk vein.= +Sculk Catalyst= +Sculk Sensor= +Sculk Shrieker= \ No newline at end of file diff --git a/mods/ITEMS/mcl_signs/locale/mcl_signs.fr.tr b/mods/ITEMS/mcl_signs/locale/mcl_signs.fr.tr index bf2733a92..8792f4d2e 100644 --- a/mods/ITEMS/mcl_signs/locale/mcl_signs.fr.tr +++ b/mods/ITEMS/mcl_signs/locale/mcl_signs.fr.tr @@ -9,10 +9,11 @@ Done=Terminé Can be written=Peut être écrit Oak Sign=Panneau de chêne Birch Sign=Panneau de bouleau -Spruce Sign=Panneau d'épinette -Dark Oak Sign=Panneau de chêne foncé -Jungle Sign=Panneau de la jungle +Spruce Sign=Panneau de sapin +Dark Oak Sign=Panneau de chêne noir +Jungle Sign=Panneau d'acajou Acacia Sign=Panneau d'acacia -Mangrove Sign=Panneau de la mangrove -Warped Hyphae Sign=Panneau d'hyphe déformé -Crimson Hyphae Sign=Panneau d'hyphe cramoisi +Mangrove Sign=Panneau de palétuvier +Warped Hyphae Sign=Panneau d'hyphe tordu +Crimson Hyphae Sign=Panneau d'hyphe écarlate +Bamboo Sign=Panneau de bambou diff --git a/mods/ITEMS/mcl_signs/locale/template.txt b/mods/ITEMS/mcl_signs/locale/template.txt index 137cc44cd..e1002e126 100644 --- a/mods/ITEMS/mcl_signs/locale/template.txt +++ b/mods/ITEMS/mcl_signs/locale/template.txt @@ -14,3 +14,6 @@ Dark Oak Sign= Jungle Sign= Acacia Sign= Mangrove Sign= +Warped Hyphae Sign= +Crimson Hyphae Sign= +Bamboo Sign= diff --git a/mods/ITEMS/mcl_smithing_table/locale/mcl_smithing_table.fr.tr b/mods/ITEMS/mcl_smithing_table/locale/mcl_smithing_table.fr.tr index 4fcdc22a3..b3f9349a7 100644 --- a/mods/ITEMS/mcl_smithing_table/locale/mcl_smithing_table.fr.tr +++ b/mods/ITEMS/mcl_smithing_table/locale/mcl_smithing_table.fr.tr @@ -1,2 +1,4 @@ # textdomain: mcl_smithing_table +Inventory=Inventaire +Upgrade Gear=Améliorer l'équipement Smithing table=Table de forgeron diff --git a/mods/ITEMS/mcl_smithing_table/locale/template.txt b/mods/ITEMS/mcl_smithing_table/locale/template.txt index 48b407d97..6133a22db 100644 --- a/mods/ITEMS/mcl_smithing_table/locale/template.txt +++ b/mods/ITEMS/mcl_smithing_table/locale/template.txt @@ -1,2 +1,4 @@ # textdomain: mcl_smithing_table +Inventory= +Upgrade Gear= Smithing table= diff --git a/mods/ITEMS/mcl_smoker/init.lua b/mods/ITEMS/mcl_smoker/init.lua index 81f3c366f..4a4cfca15 100644 --- a/mods/ITEMS/mcl_smoker/init.lua +++ b/mods/ITEMS/mcl_smoker/init.lua @@ -415,14 +415,12 @@ end minetest.register_node("mcl_smoker:smoker", { description = S("Smoker"), _tt_help = S("Cooks food faster than furnace"), - _doc_items_longdesc = S("Smokers cook several items, using a furnace fuel, into something else, but twice as fast as a normal furnace"), + _doc_items_longdesc = S("Smokers cook several items, mainly raw foods, into cooked foods, but twice as fast as a normal furnace."), _doc_items_usagehelp = - S([[ - Use the smoker to open the furnace menu. - Place a furnace fuel in the lower slot and the source material in the upper slot. - The smoker will slowly use its fuel to smelt the item. - The result will be placed into the output slot at the right side. - ]]).."\n".. + S("Use the smoker to open the furnace menu.").."\n".. + S("Place a furnace fuel in the lower slot and the source material in the upper slot.").."\n".. + S("The smoker will slowly use its fuel to smelt the item.").."\n".. + S("The result will be placed into the output slot at the right side.").."\n".. S("Use the recipe book to see what foods you can smelt, what you can use as fuel and how long it will burn."), _doc_items_hidden = false, tiles = { diff --git a/mods/ITEMS/mcl_smoker/locale/mcl_smoker.fr.tr b/mods/ITEMS/mcl_smoker/locale/mcl_smoker.fr.tr index 55f6a2ba8..cfbbff113 100644 --- a/mods/ITEMS/mcl_smoker/locale/mcl_smoker.fr.tr +++ b/mods/ITEMS/mcl_smoker/locale/mcl_smoker.fr.tr @@ -2,7 +2,10 @@ Inventory=Inventaire Smoker=Fumoir Cooks food faster than furnace=Cuit la nourriture plus vite qu'un fourneau -Use the recipe book to see what you can smelt, what you can use as fuel and how long it will burn.=Utiliser le livre de recettes pour voir ce que vous pouvez fondre, ce que vous pouvez utiliser comme combustible et combien de temps ça va brûler. -Use the furnace to open the furnace menu.\nPlace a furnace fuel in the lower slot and the source material in the upper slot.\nThe furnace will slowly use its fuel to smelt the item.\nThe result will be placed into the output slot at the right side.=Utiliser le fourneau pour ouvrir le menu.\nPlacer le combustible dans la case en bas et le matériau source dans la case du haut.\nLe fourneau utilisera son combustible pour fondre lentement l'objet.\nLe résultat sera placé dans la case de sortie à droite. -Smokers cook several items, mainly raw foods, into cooked foods, but twice as fast as a normal furnace.=Les fumoirs cuisent plusieurs objets, surtout de la nourriture crue, en de la nourriture cuite. -Burning Smoker=Fumoir actif \ No newline at end of file +Use the smoker to open the furnace menu.=Utiliser le fumoir pour ouvrir le menu. +Place a furnace fuel in the lower slot and the source material in the upper slot.=Placer le combustible dans la case en bas et le matériau source dans la case du haut. +The smoker will slowly use its fuel to smelt the item.=Le fumoir utilisera son combustible pour fondre lentement l'objet. +The result will be placed into the output slot at the right side.=Le résultat sera placé dans la case de sortie à droite. +Use the recipe book to see what foods you can smelt, what you can use as fuel and how long it will burn.=Utiliser le livre de recettes pour voir quels aliments vous pouvez cuire, ce que vous pouvez utiliser comme combustible et combien de temps ça va brûler. +Smokers cook several items, mainly raw foods, into cooked foods, but twice as fast as a normal furnace.=Les fumoirs cuisent plusieurs objets, surtout de la nourriture crue, en de la nourriture cuite, mais deux fois plus vite qu'un fourneau normal. +Burning Smoker=Fumoir actif diff --git a/mods/ITEMS/mcl_smoker/locale/template.txt b/mods/ITEMS/mcl_smoker/locale/template.txt index dcf0be9b3..b8e27608a 100644 --- a/mods/ITEMS/mcl_smoker/locale/template.txt +++ b/mods/ITEMS/mcl_smoker/locale/template.txt @@ -2,7 +2,10 @@ Inventory= Smoker= Cooks food faster than furnace= -Use the recipe book to see what you can smelt, what you can use as fuel and how long it will burn.= -Use the furnace to open the furnace menu.\nPlace a furnace fuel in the lower slot and the source material in the upper slot.\nThe furnace will slowly use its fuel to smelt the item.\nThe result will be placed into the output slot at the right side.= +Use the smoker to open the furnace menu.= +Place a furnace fuel in the lower slot and the source material in the upper slot.= +The smoker will slowly use its fuel to smelt the item.= +The result will be placed into the output slot at the right side.= +Use the recipe book to see what foods you can smelt, what you can use as fuel and how long it will burn.= Smokers cook several items, mainly raw foods, into cooked foods, but twice as fast as a normal furnace.= Burning Smoker= diff --git a/mods/ITEMS/mcl_tools/locale/mcl_tools.fr.tr b/mods/ITEMS/mcl_tools/locale/mcl_tools.fr.tr index f09ccfcc3..1d3c46648 100644 --- a/mods/ITEMS/mcl_tools/locale/mcl_tools.fr.tr +++ b/mods/ITEMS/mcl_tools/locale/mcl_tools.fr.tr @@ -14,23 +14,23 @@ Stone Pickaxe=Pioche en pierre Iron Pickaxe=Pioche en fer Golden Pickaxe=Pioche en or Diamond Pickaxe=Pioche en diamant -Netherite Pickaxe=Pioche en Netherite +Netherite Pickaxe=Pioche en netherite Wooden Shovel=Pelle en bois Stone Shovel=Pelle en pierre Iron Shovel=Pelle en fer Golden Shovel=Pelle en or Diamond Shovel=Pelle en diamant -Netherite Shovel=Pelle en Netherite +Netherite Shovel=Pelle en netherite Wooden Axe=Hache en bois Stone Axe=Hache en pierre Iron Axe=Hache en fer Golden Axe=Hache en or Diamond Axe=Hache en diamant -Netherite Axe=Hache en Netherite +Netherite Axe=Hache en netherite Wooden Sword=Épée en bois Stone Sword=Épée en pierre Iron Sword=Épée en fer Golden Sword=Épée en or Diamond Sword=Épée en diamant -Netherite Sword=Épée en Netherite +Netherite Sword=Épée en netherite Shears=Cisailles diff --git a/mods/ITEMS/mclx_fences/locale/mclx_fences.fr.tr b/mods/ITEMS/mclx_fences/locale/mclx_fences.fr.tr index 244b588c1..77d38d2c6 100644 --- a/mods/ITEMS/mclx_fences/locale/mclx_fences.fr.tr +++ b/mods/ITEMS/mclx_fences/locale/mclx_fences.fr.tr @@ -1,4 +1,4 @@ # textdomain: mclx_fences Red Nether Brick Fence=Barrière en Brique Rouge du Nether -Red Nether Brick Fence Gate=Porte de Barrière en Brique Rouge du Nether -Nether Brick Fence Gate=Porte de Barrière en Brique du Nether +Red Nether Brick Fence Gate=Portillon en Brique Rouge du Nether +Nether Brick Fence Gate=Portillon en Brique du Nether diff --git a/mods/ITEMS/mclx_stairs/locale/mclx_stairs.fr.tr b/mods/ITEMS/mclx_stairs/locale/mclx_stairs.fr.tr index 09461eefd..243fc1e91 100644 --- a/mods/ITEMS/mclx_stairs/locale/mclx_stairs.fr.tr +++ b/mods/ITEMS/mclx_stairs/locale/mclx_stairs.fr.tr @@ -1,20 +1,20 @@ # textdomain: mclx_stairs -Oak Bark Stairs=Escalier en écorse de chêne +Oak Bark Stairs=Escalier en écorce de chêne Oak Bark Slab=Plaque d'écorce de chêne Double Oak Bark Slab=Double dalle d'écorce de chêne Acacia Bark Stairs=Escalier en écorce d'acacia Acacia Bark Slab=Plaque d'écorce d'acacia Double Acacia Bark Slab=Double dalle d'écorce d'acacia -Spruce Bark Stairs=Escalier en écorse de sapin +Spruce Bark Stairs=Escalier en écorce de sapin Spruce Bark Slab=Plaque d'écorce de sapin Double Spruce Bark Slab=Double dalle d'écorce de sapin -Birch Bark Stairs=Escalier en écorse de bouleau +Birch Bark Stairs=Escalier en écorce de bouleau Birch Bark Slab=Plaque d'écorce de bouleau Double Birch Bark Slab=Double dalle d'écorce de bouleau -Jungle Bark Stairs=Escalier en écorse d'acajou +Jungle Bark Stairs=Escalier en écorce d'acajou Jungle Bark Slab=Plaque d'écorce d'acajou Double Jungle Bark Slab=Double dalle d'écorce d'acajou -Dark Oak Bark Stairs=Escalier en écorse de chêne noir +Dark Oak Bark Stairs=Escalier en écorce de chêne noir Dark Oak Bark Slab=Plaque d'écorce de chêne noir Double Dark Oak Bark Slab=Double dalle d'écorce de chêne noir Lapis Lazuli Slab=Dalle de lapis-lazuli diff --git a/mods/ITEMS/screwdriver/locale/screwdriver.fr.tr b/mods/ITEMS/screwdriver/locale/screwdriver.fr.tr index ae014ea09..cce37b34a 100644 --- a/mods/ITEMS/screwdriver/locale/screwdriver.fr.tr +++ b/mods/ITEMS/screwdriver/locale/screwdriver.fr.tr @@ -1,2 +1,2 @@ -#textdomain: screwdriver +# textdomain: screwdriver Screwdriver=Tournevis diff --git a/mods/ITEMS/screwdriver/locale/screwdriver.ja.tr b/mods/ITEMS/screwdriver/locale/screwdriver.ja.tr index dbb80fb61..0a80459f6 100644 --- a/mods/ITEMS/screwdriver/locale/screwdriver.ja.tr +++ b/mods/ITEMS/screwdriver/locale/screwdriver.ja.tr @@ -1,2 +1,2 @@ -#textdomain: screwdriver +# textdomain: screwdriver Screwdriver=ドライバー diff --git a/mods/ITEMS/screwdriver/locale/screwdriver.pl.tr b/mods/ITEMS/screwdriver/locale/screwdriver.pl.tr index b9adac135..d4c0436ab 100644 --- a/mods/ITEMS/screwdriver/locale/screwdriver.pl.tr +++ b/mods/ITEMS/screwdriver/locale/screwdriver.pl.tr @@ -1,2 +1,2 @@ -#textdomain: screwdriver +# textdomain: screwdriver Screwdriver=Śrubokręt diff --git a/mods/ITEMS/screwdriver/locale/screwdriver.ru.tr b/mods/ITEMS/screwdriver/locale/screwdriver.ru.tr index fb6321684..6d7605ae5 100644 --- a/mods/ITEMS/screwdriver/locale/screwdriver.ru.tr +++ b/mods/ITEMS/screwdriver/locale/screwdriver.ru.tr @@ -1,2 +1,2 @@ -#textdomain: screwdriver +# textdomain: screwdriver Screwdriver=Отвёртка diff --git a/mods/ITEMS/screwdriver/locale/screwdriver.zh_TW.tr b/mods/ITEMS/screwdriver/locale/screwdriver.zh_TW.tr index f29a4bf33..12eb2576c 100644 --- a/mods/ITEMS/screwdriver/locale/screwdriver.zh_TW.tr +++ b/mods/ITEMS/screwdriver/locale/screwdriver.zh_TW.tr @@ -1,2 +1,2 @@ -#textdomain: screwdriver +# textdomain: screwdriver Screwdriver=螺絲刀 diff --git a/mods/ITEMS/screwdriver/locale/template.txt b/mods/ITEMS/screwdriver/locale/template.txt index b3871a116..41309d57e 100644 --- a/mods/ITEMS/screwdriver/locale/template.txt +++ b/mods/ITEMS/screwdriver/locale/template.txt @@ -1,2 +1,2 @@ -#textdomain: screwdriver +# textdomain: screwdriver Screwdriver= From d42260cea3c9c7224f2710e5bf851d9522a3890c Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Thu, 11 May 2023 23:49:46 +0100 Subject: [PATCH 104/155] Fix dropped out bamboo lines from translation work --- mods/ITEMS/mcl_bamboo/bamboo_items.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mods/ITEMS/mcl_bamboo/bamboo_items.lua b/mods/ITEMS/mcl_bamboo/bamboo_items.lua index 2f3b463a8..63f07f896 100644 --- a/mods/ITEMS/mcl_bamboo/bamboo_items.lua +++ b/mods/ITEMS/mcl_bamboo/bamboo_items.lua @@ -65,6 +65,8 @@ if minetest.get_modpath("mcl_doors") then description = S("Bamboo Door"), inventory_image = "mcl_bamboo_door_wield.png", wield_image = "mcl_bamboo_door_wield.png", + _doc_items_longdesc = S("Wooden doors are 2-block high barriers which can be opened or closed by hand and by a redstone signal."), + _doc_items_usagehelp = S("To open or close a wooden door, rightclick it or supply its lower half with a redstone signal."), groups = { handy = 1, axey = 1, material_wood = 1, flammable = -1 }, _mcl_hardness = 3, _mcl_blast_resistance = 3, From 3aed71fb8551d1f2a27a29bbb9516dc63d5187de Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Thu, 11 May 2023 01:16:24 +0100 Subject: [PATCH 105/155] Piglins no longer aggro for enchanted gold armour --- mods/ENTITIES/mobs_mc/piglin.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mods/ENTITIES/mobs_mc/piglin.lua b/mods/ENTITIES/mobs_mc/piglin.lua index b8c8faf21..f3e2a1f1b 100644 --- a/mods/ENTITIES/mobs_mc/piglin.lua +++ b/mods/ENTITIES/mobs_mc/piglin.lua @@ -25,7 +25,10 @@ function mobs_mc.player_wears_gold(player) for i=1, 6 do local stack = player:get_inventory():get_stack("armor", i) local item = stack:get_name() - if item == "mcl_armor:chestplate_gold" or item == "mcl_armor:leggings_gold" or item == "mcl_armor:helmet_gold" or item == "mcl_armor:boots_gold" then + if string.find(item, "mcl_armor:chestplate_gold") + or string.find(item, "mcl_armor:leggings_gold") + or string.find(item, "mcl_armor:helmet_gold") + or string.find(item, "mcl_armor:boots_gold") then return true end end From be32ffde6b590606f44443f6d68bdb06fb159551 Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Fri, 12 May 2023 13:41:56 -0600 Subject: [PATCH 106/155] Remove Flower Forest Beaches from Wolf biome spawn list --- mods/ENTITIES/mobs_mc/wolf.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/mods/ENTITIES/mobs_mc/wolf.lua b/mods/ENTITIES/mobs_mc/wolf.lua index 922069508..7b142086d 100644 --- a/mods/ENTITIES/mobs_mc/wolf.lua +++ b/mods/ENTITIES/mobs_mc/wolf.lua @@ -216,7 +216,6 @@ mcl_mobs:spawn_specific( "MegaTaiga", "Forest", "ColdTaiga", - "FlowerForest_beach", "Forest_beach", "ColdTaiga_beach_water", "Taiga_beach", From 998983445b253a6b24c6593733c36a2f312951fa Mon Sep 17 00:00:00 2001 From: FossFanatic Date: Sun, 14 May 2023 11:41:39 +0000 Subject: [PATCH 107/155] Rename Bucket Textures (#3708) This pull request renames buckets so that they use the `mcl_` naming convention. I originally was going to do some renaming on a bigger scope, but decided against it for now. Reviewed-on: https://git.minetest.land/MineClone2/MineClone2/pulls/3708 Reviewed-by: ancientmarinerdev Co-authored-by: FossFanatic Co-committed-by: FossFanatic --- mods/ITEMS/mcl_buckets/init.lua | 2 +- mods/ITEMS/mcl_buckets/register.lua | 6 +++--- textures/{bucket.png => mcl_buckets_bucket.png} | Bin ...{bucket_lava.png => mcl_buckets_lava_bucket.png} | Bin ...water.png => mcl_buckets_river_water_bucket.png} | Bin ...ucket_water.png => mcl_buckets_water_bucket.png} | Bin 6 files changed, 4 insertions(+), 4 deletions(-) rename textures/{bucket.png => mcl_buckets_bucket.png} (100%) rename textures/{bucket_lava.png => mcl_buckets_lava_bucket.png} (100%) rename textures/{bucket_river_water.png => mcl_buckets_river_water_bucket.png} (100%) rename textures/{bucket_water.png => mcl_buckets_water_bucket.png} (100%) diff --git a/mods/ITEMS/mcl_buckets/init.lua b/mods/ITEMS/mcl_buckets/init.lua index ecc867482..6aebbc759 100644 --- a/mods/ITEMS/mcl_buckets/init.lua +++ b/mods/ITEMS/mcl_buckets/init.lua @@ -325,7 +325,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"), - inventory_image = "bucket.png", + inventory_image = "mcl_buckets_bucket.png", stack_max = 16, liquids_pointable = use_select_box, on_place = on_place_bucket_empty, diff --git a/mods/ITEMS/mcl_buckets/register.lua b/mods/ITEMS/mcl_buckets/register.lua index d9054d498..109941ab0 100644 --- a/mods/ITEMS/mcl_buckets/register.lua +++ b/mods/ITEMS/mcl_buckets/register.lua @@ -38,7 +38,7 @@ if mod_mcl_core then end end, bucketname = "mcl_buckets:bucket_lava", - inventory_image = "bucket_lava.png", + inventory_image = "mcl_buckets_lava_bucket.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."), usagehelp = S("Get in a safe distance and place the bucket to empty it and create a lava source at this spot. Don't burn yourself!"), @@ -50,7 +50,7 @@ if mod_mcl_core then source_place = "mcl_core:water_source", source_take = {"mcl_core:water_source"}, bucketname = "mcl_buckets:bucket_water", - inventory_image = "bucket_water.png", + inventory_image = "mcl_buckets_water_bucket.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."), @@ -89,7 +89,7 @@ if mod_mclx_core then source_place = "mclx_core:river_water_source", source_take = {"mclx_core:river_water_source"}, bucketname = "mcl_buckets:bucket_river_water", - inventory_image = "bucket_river_water.png", + inventory_image = "mcl_buckets_river_water_bucket.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."), diff --git a/textures/bucket.png b/textures/mcl_buckets_bucket.png similarity index 100% rename from textures/bucket.png rename to textures/mcl_buckets_bucket.png diff --git a/textures/bucket_lava.png b/textures/mcl_buckets_lava_bucket.png similarity index 100% rename from textures/bucket_lava.png rename to textures/mcl_buckets_lava_bucket.png diff --git a/textures/bucket_river_water.png b/textures/mcl_buckets_river_water_bucket.png similarity index 100% rename from textures/bucket_river_water.png rename to textures/mcl_buckets_river_water_bucket.png diff --git a/textures/bucket_water.png b/textures/mcl_buckets_water_bucket.png similarity index 100% rename from textures/bucket_water.png rename to textures/mcl_buckets_water_bucket.png From f019f4ae4591071c78f6b13e3f34b519c72f2cc7 Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Wed, 10 May 2023 15:05:11 -0600 Subject: [PATCH 108/155] Lightning rod param2 is now saved upon being struck --- mods/ITEMS/mcl_lightning_rods/init.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_lightning_rods/init.lua b/mods/ITEMS/mcl_lightning_rods/init.lua index 82e04db0c..3cd2dc1dc 100644 --- a/mods/ITEMS/mcl_lightning_rods/init.lua +++ b/mods/ITEMS/mcl_lightning_rods/init.lua @@ -82,7 +82,7 @@ rod_def_a.on_timer = function(pos, elapsed) local node = minetest.get_node(pos) if node.name == "mcl_lightning_rods:rod_powered" then --has not been dug - minetest.set_node(pos, { name = "mcl_lightning_rods:rod" }) + minetest.set_node(pos, { name = "mcl_lightning_rods:rod", param2 = node.param2 }) mesecon.receptor_off(pos, mesecon.rules.alldirs) end @@ -99,7 +99,7 @@ lightning.register_on_strike(function(pos, pos2, objects) local node = minetest.get_node(lr) if node.name == "mcl_lightning_rods:rod" then - minetest.set_node(lr, { name = "mcl_lightning_rods:rod_powered" }) + minetest.set_node(lr, { name = "mcl_lightning_rods:rod_powered", param2 = node.param2 }) mesecon.receptor_on(lr, mesecon.rules.alldirs) minetest.get_node_timer(lr):start(0.4) end From 530c8ec0da3159892c201d0fb719096d9b47d51b Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 12 May 2023 00:02:30 +0100 Subject: [PATCH 109/155] Remove zombie pigmen and ensure zombie piglin named correctly. Add Piglin description names. --- mods/ENTITIES/mobs_mc/README.md | 2 +- mods/ENTITIES/mobs_mc/init.lua | 3 +- mods/ENTITIES/mobs_mc/locale/mobs_mc.de.tr | 2 +- mods/ENTITIES/mobs_mc/locale/mobs_mc.es.tr | 4 +- mods/ENTITIES/mobs_mc/locale/mobs_mc.fr.tr | 2 +- mods/ENTITIES/mobs_mc/locale/mobs_mc.ja.tr | 2 +- mods/ENTITIES/mobs_mc/locale/template.txt | 2 +- mods/ENTITIES/mobs_mc/piglin.lua | 199 ++++++++++++++---- mods/ENTITIES/mobs_mc/zombiepig.lua | 52 +---- .../locale/mcl_death_messages.es.tr | 4 +- .../locale/mcl_death_messages.ru.tr | 4 +- mods/ITEMS/mcl_beds/functions.lua | 2 +- 12 files changed, 181 insertions(+), 97 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/README.md b/mods/ENTITIES/mobs_mc/README.md index 881f56619..bdc561295 100644 --- a/mods/ENTITIES/mobs_mc/README.md +++ b/mods/ENTITIES/mobs_mc/README.md @@ -39,7 +39,7 @@ This mod adds mobs which closely resemble the mobs from the game Minecraft, vers * Cave Spider * Enderman * Zombie Villager -* Zombie Pigman +* Zombie Piglin * Wither Skeleton * Magma Cube * Blaze diff --git a/mods/ENTITIES/mobs_mc/init.lua b/mods/ENTITIES/mobs_mc/init.lua index c2b3d8ed0..483efdcb4 100644 --- a/mods/ENTITIES/mobs_mc/init.lua +++ b/mods/ENTITIES/mobs_mc/init.lua @@ -139,7 +139,6 @@ dofile(path .. "/silverfish.lua") -- maikerumine Mesh and animation by toby109tt dofile(path .. "/skeleton+stray.lua") -- Mesh by Morn76 Animation by Pavel_S dofile(path .. "/skeleton_wither.lua") -- Mesh by Morn76 Animation by Pavel_S dofile(path .. "/zombie.lua") -- Mesh by Morn76 Animation by Pavel_S -dofile(path .. "/zombiepig.lua") -- Mesh by Morn76 Animation by Pavel_S dofile(path .. "/slime+magma_cube.lua") -- Wuzzy dofile(path .. "/spider.lua") -- Spider by AspireMint (fishyWET (CC-BY-SA 3.0 license for texture) dofile(path .. "/vex.lua") -- KrupnoPavel @@ -153,7 +152,7 @@ dofile(path .. "/dolphin.lua") dofile(path .. "/glow_squid.lua") -dofile(path .. "/piglin.lua") +dofile(path .. "/piglin.lua") -- "mobs_mc_zombie_pigman.b3d" Mesh by Morn76 Animation by Pavel_S dofile(path .. "/hoglin+zoglin.lua") dofile(path .. "/strider.lua") diff --git a/mods/ENTITIES/mobs_mc/locale/mobs_mc.de.tr b/mods/ENTITIES/mobs_mc/locale/mobs_mc.de.tr index 676415d69..84aade90e 100644 --- a/mods/ENTITIES/mobs_mc/locale/mobs_mc.de.tr +++ b/mods/ENTITIES/mobs_mc/locale/mobs_mc.de.tr @@ -48,7 +48,7 @@ Wither=Wither Wolf=Wolf Husk=Wüstenzombie Zombie=Zombie -Zombie Pigman=Schweinezombie +Zombie Piglin=Schweinezombie Farmer=Bauer Fisherman=Fischer Fletcher=Pfeilmacher diff --git a/mods/ENTITIES/mobs_mc/locale/mobs_mc.es.tr b/mods/ENTITIES/mobs_mc/locale/mobs_mc.es.tr index 0d4c94ef3..7f81f0280 100644 --- a/mods/ENTITIES/mobs_mc/locale/mobs_mc.es.tr +++ b/mods/ENTITIES/mobs_mc/locale/mobs_mc.es.tr @@ -54,8 +54,8 @@ Baby Husk=Bebé Zombi Momificado Baby Zombie=Bebé Zombi Husk=Zombi Momificado Zombie=Zombi -Baby Zombie Pigman=Bebé Hombrecerdo Zombi -Zombie Pigman=Hombrecerdo Zombi +Baby Zombie Piglin=Bebé Hombrecerdo Zombi +Zombie Piglin=Hombrecerdo Zombi Cartographer=Cartógrafo Armorer=Escudero Leatherworker=Peletero diff --git a/mods/ENTITIES/mobs_mc/locale/mobs_mc.fr.tr b/mods/ENTITIES/mobs_mc/locale/mobs_mc.fr.tr index c4440a727..81c93a33b 100644 --- a/mods/ENTITIES/mobs_mc/locale/mobs_mc.fr.tr +++ b/mods/ENTITIES/mobs_mc/locale/mobs_mc.fr.tr @@ -49,7 +49,7 @@ Wither=Wither Wolf=Loup Husk=Zombie Momifié Zombie=Zombie -Zombie Pigman=Zombie Cochon +Zombie Piglin=Zombie Cochon Farmer=Fermier Fisherman=Pêcheur Fletcher=Archer diff --git a/mods/ENTITIES/mobs_mc/locale/mobs_mc.ja.tr b/mods/ENTITIES/mobs_mc/locale/mobs_mc.ja.tr index ff6966131..63d73e222 100644 --- a/mods/ENTITIES/mobs_mc/locale/mobs_mc.ja.tr +++ b/mods/ENTITIES/mobs_mc/locale/mobs_mc.ja.tr @@ -49,7 +49,7 @@ Wither=ウィザー Wolf=オオカミ Husk=ハスク Zombie=ゾンビ -Zombie Pigman=ゾンビピッグマン +Zombie Piglin=ゾンビピッグマン Farmer=農民 Fisherman=漁師 Fletcher=矢師 diff --git a/mods/ENTITIES/mobs_mc/locale/template.txt b/mods/ENTITIES/mobs_mc/locale/template.txt index 9c1ee5cd7..4710c713f 100644 --- a/mods/ENTITIES/mobs_mc/locale/template.txt +++ b/mods/ENTITIES/mobs_mc/locale/template.txt @@ -49,7 +49,7 @@ Wither= Wolf= Husk= Zombie= -Zombie Pigman= +Zombie Piglin= Farmer= Fisherman= Fletcher= diff --git a/mods/ENTITIES/mobs_mc/piglin.lua b/mods/ENTITIES/mobs_mc/piglin.lua index f3e2a1f1b..e0247f548 100644 --- a/mods/ENTITIES/mobs_mc/piglin.lua +++ b/mods/ENTITIES/mobs_mc/piglin.lua @@ -38,6 +38,7 @@ end --################### piglin --################### local piglin = { + S("Piglin"), type = "monster", passive = false, spawn_class = "hostile", @@ -181,6 +182,7 @@ mcl_mobs.register_mob("mobs_mc:piglin", piglin) local sword_piglin = table.copy(piglin) +sword_piglin.description = S("Sword Piglin") sword_piglin.mesh = "extra_mobs_sword_piglin.b3d" sword_piglin.textures = {"extra_mobs_piglin.png", "default_tool_goldsword.png"} sword_piglin.on_spawn = function(self) @@ -209,43 +211,127 @@ sword_piglin.animation = { punch_start = 189, punch_end = 198, } + mcl_mobs.register_mob("mobs_mc:sword_piglin", sword_piglin) -local zombified_piglin = table.copy(piglin) -zombified_piglin.fire_resistant = 1 -zombified_piglin.do_custom = function() - return -end -zombified_piglin.on_spawn = function() - return -end -zombified_piglin.on_rightclick = function() - return -end -zombified_piglin.lava_damage = 0 -zombified_piglin.fire_damage = 0 -zombified_piglin.attack_animals = true -zombified_piglin.mesh = "extra_mobs_sword_piglin.b3d" -zombified_piglin.textures = {"extra_mobs_zombified_piglin.png", "default_tool_goldsword.png", "extra_mobs_trans.png"} -zombified_piglin.attack_type = "dogfight" -zombified_piglin.animation = { - stand_speed = 30, - walk_speed = 30, - punch_speed = 45, - run_speed = 30, - stand_start = 0, - stand_end = 79, - walk_start = 168, - walk_end = 187, - run_start = 440, - run_end = 459, - punch_start = 189, - punch_end = 198, + +-- Zombified Piglin -- + + +local zombified_piglin = { + description = S("Zombie Piglin"), + -- type="animal", passive=false: This combination is needed for a neutral mob which becomes hostile, if attacked + type = "animal", + passive = false, + spawn_class = "passive", + hp_min = 20, + hp_max = 20, + xp_min = 6, + xp_max = 6, + armor = {undead = 90, fleshy = 90}, + attack_type = "dogfight", + group_attack = {"mobs_mc:zombified_piglin", "mobs_mc:baby_zombified_piglin"}, + damage = 9, + reach = 2, + head_swivel = "head.control", + bone_eye_height = 2.4, + head_eye_height = 1.4, + curiosity = 15, + collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.94, 0.3}, -- same + visual = "mesh", + mesh = "mobs_mc_zombie_pigman.b3d", + textures = { { + "blank.png", --baby + "default_tool_goldsword.png", --sword + "mobs_mc_zombie_pigman.png", --pigman + } }, + visual_size = {x=3, y=3}, + sounds = { + random = "mobs_mc_zombiepig_random", + war_cry = "mobs_mc_zombiepig_war_cry", + death = "mobs_mc_zombiepig_death", + damage = "mobs_mc_zombiepig_hurt", + distance = 16, + }, + jump = true, + makes_footstep_sound = true, + walk_velocity = .8, + run_velocity = 2.6, + pathfinding = 1, + drops = { + {name = "mcl_mobitems:rotten_flesh", + chance = 1, + min = 1, + max = 1, + looting = "common"}, + {name = "mcl_core:gold_nugget", + chance = 1, + min = 0, + max = 1, + looting = "common"}, + {name = "mcl_core:gold_ingot", + chance = 40, -- 2.5% + min = 1, + max = 1, + looting = "rare"}, + {name = "mcl_tools:sword_gold", + chance = 100 / 8.5, + min = 1, + max = 1, + looting = "rare"}, + }, + animation = { + stand_speed = 25, + walk_speed = 25, + run_speed = 50, + stand_start = 40, + stand_end = 80, + walk_start = 0, + walk_end = 40, + run_start = 0, + run_end = 40, + punch_start = 90, + punch_end = 130, + }, + lava_damage = 0, + fire_damage = 0, + fear_height = 4, + view_range = 16, + harmed_by_heal = true, + fire_damage_resistant = true, } + mcl_mobs.register_mob("mobs_mc:zombified_piglin", zombified_piglin) +local baby_zombified_piglin = table.copy(zombified_piglin) +baby_zombified_piglin.description = S("Baby Zombie Piglin") +baby_zombified_piglin.collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.94, 0.25} +baby_zombified_piglin.xp_min = 13 +baby_zombified_piglin.xp_max = 13 +baby_zombified_piglin.textures = { + { + "mobs_mc_zombie_pigman.png", --baby + "default_tool_goldsword.png", --sword + "mobs_mc_zombie_pigman.png", --pigman + } +} +baby_zombified_piglin.walk_velocity = 1.2 +baby_zombified_piglin.run_velocity = 2.4 +baby_zombified_piglin.light_damage = 0 +baby_zombified_piglin.child = 1 + +mcl_mobs.register_mob("mobs_mc:baby_zombified_piglin", baby_zombified_piglin) + +-- Compatibility code. These were removed, and now are called zombie piglins. They don't spawn. +-- This is only to catch old cases. Maybe could be an alias? +mcl_mobs.register_mob("mobs_mc:pigman", zombified_piglin) +mcl_mobs.register_mob("mobs_mc:baby_pigman", baby_zombified_piglin) + + +-- Piglin Brute -- local piglin_brute = table.copy(piglin) +piglin_brute.description = S("Piglin Brute") piglin_brute.xp_min = 20 piglin_brute.xp_max = 20 piglin_brute.hp_min = 50 @@ -283,10 +369,11 @@ piglin_brute.animation = { } piglin_brute.can_despawn = false piglin_brute.group_attack = { "mobs_mc:piglin", "mobs_mc:piglin_brute" } + mcl_mobs.register_mob("mobs_mc:piglin_brute", piglin_brute) -mcl_mobs:non_spawn_specific("mobs_mc:piglin","overworld",0,7) + -- Regular spawning in the Nether mcl_mobs:spawn_specific( "mobs_mc:piglin", @@ -303,15 +390,15 @@ minetest.LIGHT_MAX+1, 3, mcl_vars.mg_lava_nether_max, mcl_vars.mg_nether_max) -mcl_mobs:non_spawn_specific("mobs_mc:sword_piglin","overworld",0,7) + mcl_mobs:spawn_specific( "mobs_mc:sword_piglin", "nether", "ground", { -"Nether", -"CrimsonForest" -}, + "Nether", + "CrimsonForest" + }, 0, minetest.LIGHT_MAX+1, 30, @@ -319,7 +406,45 @@ minetest.LIGHT_MAX+1, 3, mcl_vars.mg_lava_nether_max, mcl_vars.mg_nether_max) --- spawn eggs + +mcl_mobs:spawn_specific( + "mobs_mc:zombified_piglin", + "nether", + "ground", + { + "Nether", + "CrimsonForest", + }, + 0, + minetest.LIGHT_MAX+1, + 30, + 6000, + 3, + mcl_vars.mg_nether_min, + mcl_vars.mg_nether_max) + +-- Baby zombie is 20 times less likely than regular zombies +mcl_mobs:spawn_specific( + "mobs_mc:baby_zombified_piglin", + "nether", + "ground", + { + "Nether", + "CrimsonForest", + }, + 0, + minetest.LIGHT_MAX+1, + 30, + 100000, + 4, + mcl_vars.mg_nether_min, + mcl_vars.mg_nether_max) + +mcl_mobs:non_spawn_specific("mobs_mc:piglin","overworld",0,7) +mcl_mobs:non_spawn_specific("mobs_mc:sword_piglin","overworld",0,7) +mcl_mobs:non_spawn_specific("mobs_mc:piglin_brute","overworld",0,7) +mcl_mobs:non_spawn_specific("mobs_mc:zombified_piglin","overworld",0,minetest.LIGHT_MAX+1) + mcl_mobs.register_egg("mobs_mc:piglin", S("Piglin"), "#7b4a17","#d5c381", 0) mcl_mobs.register_egg("mobs_mc:piglin_brute", S("Piglin Brute"), "#562b0c","#ddc89d", 0) -mcl_mobs:non_spawn_specific("mobs_mc:piglin_brute","overworld",0,7) +mcl_mobs.register_egg("mobs_mc:zombified_piglin", S("Zombie Piglin"), "#ea9393", "#4c7129", 0) \ No newline at end of file diff --git a/mods/ENTITIES/mobs_mc/zombiepig.lua b/mods/ENTITIES/mobs_mc/zombiepig.lua index f753b5f85..a2104027b 100644 --- a/mods/ENTITIES/mobs_mc/zombiepig.lua +++ b/mods/ENTITIES/mobs_mc/zombiepig.lua @@ -5,13 +5,14 @@ local S = minetest.get_translator("mobs_mc") ---################### ---################### ZOMBIE PIGMAN ---################### +-- TODO Alias needs to be created +-- TODO DELETE THIS FILE. No longer needed. +-- Spawning removed +-- Mob copied to piglin.lua local pigman = { - description = S("Zombie Pigman"), + description = S("Zombie Piglin"), -- type="animal", passive=false: This combination is needed for a neutral mob which becomes hostile, if attacked type = "animal", passive = false, @@ -93,13 +94,12 @@ local pigman = { fire_damage_resistant = true, } -mcl_mobs.register_mob("mobs_mc:pigman", pigman) -- Baby pigman. -- A smaller and more dangerous variant of the pigman local baby_pigman = table.copy(pigman) -baby_pigman.description = S("Baby Zombie Pigman") +baby_pigman.description = S("Baby Zombie Piglin") baby_pigman.collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.94, 0.25} baby_pigman.xp_min = 13 baby_pigman.xp_max = 13 @@ -113,44 +113,4 @@ baby_pigman.run_velocity = 2.4 baby_pigman.light_damage = 0 baby_pigman.child = 1 -mcl_mobs.register_mob("mobs_mc:baby_pigman", baby_pigman) --- Regular spawning in the Nether -mcl_mobs:spawn_specific( -"mobs_mc:pigman", -"nether", -"ground", -{ -"Nether", -"CrimsonForest", -}, -0, -minetest.LIGHT_MAX+1, -30, -6000, -3, -mcl_vars.mg_nether_min, -mcl_vars.mg_nether_max) --- Baby zombie is 20 times less likely than regular zombies -mcl_mobs:spawn_specific( -"mobs_mc:baby_pigman", -"nether", -"ground", -{ -"Nether", -"CrimsonForest", -}, -0, -minetest.LIGHT_MAX+1, -30, -100000, -4, -mcl_vars.mg_nether_min, -mcl_vars.mg_nether_max) - --- Spawning in Nether portals in the Overworld ---mobs:spawn_specific("mobs_mc:pigman", {"mcl_portals:portal"}, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 500, 4, mcl_vars.mg_overworld_min, mcl_vars.mg_overworld_max) - --- spawn eggs -mcl_mobs.register_egg("mobs_mc:pigman", S("Zombie Pigman"), "#ea9393", "#4c7129", 0) -mcl_mobs:non_spawn_specific("mobs_mc:pigman","overworld",0,minetest.LIGHT_MAX+1) diff --git a/mods/HUD/mcl_death_messages/locale/mcl_death_messages.es.tr b/mods/HUD/mcl_death_messages/locale/mcl_death_messages.es.tr index bbdbb5a9e..8c56ebe9e 100644 --- a/mods/HUD/mcl_death_messages/locale/mcl_death_messages.es.tr +++ b/mods/HUD/mcl_death_messages/locale/mcl_death_messages.es.tr @@ -56,5 +56,5 @@ A ghast scared @1 to death.=Se ha asustado @1 hasta morir. @1 was killed by a zombie villager.=@1 fue asesinado por un aldeano zombie. @1 was killed by a husk.=@1 fue asesinado por un husk. @1 was killed by a baby husk.=@1 fue asesinado por un bebé husk. -@1 was killed by a zombie pigman.=@1 fue asesinado por un cerdo zombie. -@1 was killed by a baby zombie pigman.=@1 fue asesinado por un bebé cerdo zombie. \ No newline at end of file +@1 was killed by a zombie piglin.=@1 fue asesinado por un cerdo zombie. +@1 was killed by a baby zombie piglin.=@1 fue asesinado por un bebé cerdo zombie. \ No newline at end of file diff --git a/mods/HUD/mcl_death_messages/locale/mcl_death_messages.ru.tr b/mods/HUD/mcl_death_messages/locale/mcl_death_messages.ru.tr index 295f19986..816546e5e 100644 --- a/mods/HUD/mcl_death_messages/locale/mcl_death_messages.ru.tr +++ b/mods/HUD/mcl_death_messages/locale/mcl_death_messages.ru.tr @@ -57,5 +57,5 @@ A ghast scared @1 to death.=Гаст напугал @1 до смерти. @1 was killed by a zombie villager.=@1 был(а) убит(а) зомби-жителем. @1 was killed by a husk.=@1 был(а) убит(а) кадавром. @1 was killed by a baby husk.=@1 был(а) убит(а) машылом-кадавром. -@1 was killed by a zombie pigman.=@1 был(а) убит(а) зомби-свиночеловеком. -@1 was killed by a baby zombie pigman.=@1 был(а) убит(а) малышом-зомби-свиночеловеком. +@1 was killed by a zombie piglin.=@1 был(а) убит(а) зомби-свиночеловеком. +@1 was killed by a baby zombie piglin.=@1 был(а) убит(а) малышом-зомби-свиночеловеком. diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index 59eea5f33..07ad1cba5 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -118,7 +118,7 @@ local function lay_down(player, pos, bed_pos, state, skip) -- No sleeping if monsters nearby. -- The exceptions above apply. - -- Zombie pigmen only prevent sleep while they are hostle. + -- Zombie piglin only prevent sleep while they are hostle. for _, obj in pairs(minetest.get_objects_inside_radius(bed_pos, 8)) do if obj and not obj:is_player() then local ent = obj:get_luaentity() From 92c0809dbe9a7ce1fd485081d922e6e44e76a4a1 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 12 May 2023 00:07:33 +0100 Subject: [PATCH 110/155] Remove zombie pigman file as no longer needed --- mods/ENTITIES/mobs_mc/zombiepig.lua | 116 ---------------------------- 1 file changed, 116 deletions(-) delete mode 100644 mods/ENTITIES/mobs_mc/zombiepig.lua diff --git a/mods/ENTITIES/mobs_mc/zombiepig.lua b/mods/ENTITIES/mobs_mc/zombiepig.lua deleted file mode 100644 index a2104027b..000000000 --- a/mods/ENTITIES/mobs_mc/zombiepig.lua +++ /dev/null @@ -1,116 +0,0 @@ ---MCmobs v0.4 ---maikerumine ---made for MC like Survival game ---License for code WTFPL and otherwise stated in readmes - -local S = minetest.get_translator("mobs_mc") - - --- TODO Alias needs to be created --- TODO DELETE THIS FILE. No longer needed. --- Spawning removed --- Mob copied to piglin.lua - -local pigman = { - description = S("Zombie Piglin"), - -- type="animal", passive=false: This combination is needed for a neutral mob which becomes hostile, if attacked - type = "animal", - passive = false, - spawn_class = "passive", - hp_min = 20, - hp_max = 20, - xp_min = 6, - xp_max = 6, - armor = {undead = 90, fleshy = 90}, - attack_type = "dogfight", - group_attack = { "mobs_mc:pigman", "mobs_mc:baby_pigman" }, - damage = 9, - reach = 2, - head_swivel = "head.control", - bone_eye_height = 2.4, - head_eye_height = 1.4, - curiosity = 15, - collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.94, 0.3}, - visual = "mesh", - mesh = "mobs_mc_zombie_pigman.b3d", - textures = { { - "blank.png", --baby - "default_tool_goldsword.png", --sword - "mobs_mc_zombie_pigman.png", --pigman - } }, - visual_size = {x=3, y=3}, - sounds = { - random = "mobs_mc_zombiepig_random", - war_cry = "mobs_mc_zombiepig_war_cry", - death = "mobs_mc_zombiepig_death", - damage = "mobs_mc_zombiepig_hurt", - distance = 16, - }, - jump = true, - makes_footstep_sound = true, - walk_velocity = .8, - run_velocity = 2.6, - pathfinding = 1, - drops = { - {name = "mcl_mobitems:rotten_flesh", - chance = 1, - min = 1, - max = 1, - looting = "common"}, - {name = "mcl_core:gold_nugget", - chance = 1, - min = 0, - max = 1, - looting = "common"}, - {name = "mcl_core:gold_ingot", - chance = 40, -- 2.5% - min = 1, - max = 1, - looting = "rare"}, - {name = "mcl_tools:sword_gold", - chance = 100 / 8.5, - min = 1, - max = 1, - looting = "rare"}, - }, - animation = { - stand_speed = 25, - walk_speed = 25, - run_speed = 50, - stand_start = 40, - stand_end = 80, - walk_start = 0, - walk_end = 40, - run_start = 0, - run_end = 40, - punch_start = 90, - punch_end = 130, - }, - lava_damage = 0, - fire_damage = 0, - fear_height = 4, - view_range = 16, - harmed_by_heal = true, - fire_damage_resistant = true, -} - - --- Baby pigman. --- A smaller and more dangerous variant of the pigman - -local baby_pigman = table.copy(pigman) -baby_pigman.description = S("Baby Zombie Piglin") -baby_pigman.collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.94, 0.25} -baby_pigman.xp_min = 13 -baby_pigman.xp_max = 13 -baby_pigman.textures = { { - "mobs_mc_zombie_pigman.png", --baby - "default_tool_goldsword.png", --sword - "mobs_mc_zombie_pigman.png", --pigman -} } -baby_pigman.walk_velocity = 1.2 -baby_pigman.run_velocity = 2.4 -baby_pigman.light_damage = 0 -baby_pigman.child = 1 - - From 2d89440972dbd76ee9f6c84dc38aa0427d6d167f Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 12 May 2023 00:39:29 +0100 Subject: [PATCH 111/155] Fix Piglin naming and add localisation entries --- mods/ENTITIES/mobs_mc/hoglin+zoglin.lua | 3 +++ mods/ENTITIES/mobs_mc/locale/template.txt | 5 +++++ mods/ENTITIES/mobs_mc/piglin.lua | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/mods/ENTITIES/mobs_mc/hoglin+zoglin.lua b/mods/ENTITIES/mobs_mc/hoglin+zoglin.lua index 2643467b6..8f8590933 100644 --- a/mods/ENTITIES/mobs_mc/hoglin+zoglin.lua +++ b/mods/ENTITIES/mobs_mc/hoglin+zoglin.lua @@ -10,6 +10,7 @@ local S = minetest.get_translator("mobs_mc") --################### local hoglin = { + description = S("Hoglin"), type = "monster", passive = false, spawn_class = "hostile", @@ -88,6 +89,7 @@ local hoglin = { mcl_mobs.register_mob("mobs_mc:hoglin", hoglin) local zoglin = table.copy(hoglin) +zoglin.description = S("Zoglin") zoglin.fire_resistant = 1 zoglin.textures = {"extra_mobs_zoglin.png"} zoglin.do_custom = function() @@ -101,6 +103,7 @@ mcl_mobs.register_mob("mobs_mc:zoglin", zoglin) -- Baby hoglin. local baby_hoglin = table.copy(hoglin) +baby_hoglin.description = S("Baby hoglin") baby_hoglin.collisionbox = {-.3, -0.01, -.3, .3, 0.94, .3} baby_hoglin.xp_min = 20 baby_hoglin.xp_max = 20 diff --git a/mods/ENTITIES/mobs_mc/locale/template.txt b/mods/ENTITIES/mobs_mc/locale/template.txt index 4710c713f..589a1a3c4 100644 --- a/mods/ENTITIES/mobs_mc/locale/template.txt +++ b/mods/ENTITIES/mobs_mc/locale/template.txt @@ -49,7 +49,12 @@ Wither= Wolf= Husk= Zombie= +Piglin= +Baby Piglin= Zombie Piglin= +Baby Zombie Piglin= +Sword Piglin= +Piglin Brute= Farmer= Fisherman= Fletcher= diff --git a/mods/ENTITIES/mobs_mc/piglin.lua b/mods/ENTITIES/mobs_mc/piglin.lua index e0247f548..2cfe4b26c 100644 --- a/mods/ENTITIES/mobs_mc/piglin.lua +++ b/mods/ENTITIES/mobs_mc/piglin.lua @@ -38,7 +38,7 @@ end --################### piglin --################### local piglin = { - S("Piglin"), + description = S("Piglin"), type = "monster", passive = false, spawn_class = "hostile", From 92a8f23d22d144045d513d51a780659478e7e18e Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 12 May 2023 00:44:53 +0100 Subject: [PATCH 112/155] Fix creeper name --- mods/ENTITIES/mobs_mc/creeper.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ENTITIES/mobs_mc/creeper.lua b/mods/ENTITIES/mobs_mc/creeper.lua index fa0717e47..f751b1240 100644 --- a/mods/ENTITIES/mobs_mc/creeper.lua +++ b/mods/ENTITIES/mobs_mc/creeper.lua @@ -10,6 +10,7 @@ local S = minetest.get_translator("mobs_mc") mcl_mobs.register_mob("mobs_mc:creeper", { + description = S("Creeper"), type = "monster", spawn_class = "hostile", spawn_in_group = 1, From 53637bbc19780718306c5a12f78c2131aa0fd6e9 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 12 May 2023 01:49:09 +0100 Subject: [PATCH 113/155] Group attack configured so that sword piglins and piglins will also respond to aggression on other piglins. --- mods/ENTITIES/mobs_mc/piglin.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mobs_mc/piglin.lua b/mods/ENTITIES/mobs_mc/piglin.lua index 2cfe4b26c..a4ac2c83f 100644 --- a/mods/ENTITIES/mobs_mc/piglin.lua +++ b/mods/ENTITIES/mobs_mc/piglin.lua @@ -42,6 +42,7 @@ local piglin = { type = "monster", passive = false, spawn_class = "hostile", + group_attack = {"mobs_mc:piglin", "mobs_mc:sword_piglin", "mobs_mc:piglin_brute"}, hp_min = 16, hp_max = 16, xp_min = 9, @@ -368,7 +369,6 @@ piglin_brute.animation = { punch_end = 198, } piglin_brute.can_despawn = false -piglin_brute.group_attack = { "mobs_mc:piglin", "mobs_mc:piglin_brute" } mcl_mobs.register_mob("mobs_mc:piglin_brute", piglin_brute) From 818052dc6cf89cdc33fd5ff2fab91b00052d0324 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 12 May 2023 14:27:02 +0100 Subject: [PATCH 114/155] Fix mob textures getting reset on shutdown/startup --- mods/ENTITIES/mcl_mobs/api.lua | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index a5af89690..9c0beaeec 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -111,6 +111,21 @@ function mob_class:get_staticdata() return minetest.serialize(tmp) end +local function valid_texture(self, def_textures) + if not self.base_texture then + return false + end + + if self.texture_selected then + if #def_textures < self.texture_selected then + self.texture_selected = nil + else + return true + end + end + return false +end + function mob_class:mob_activate(staticdata, def, dtime) if not self.object:get_pos() or staticdata == "remove" then mcl_burning.extinguish(self.object) @@ -133,16 +148,20 @@ function mob_class:mob_activate(staticdata, def, dtime) end --If textures in definition change, reload textures - if not self.base_texture or (def.textures and table.indexof(def.textures, self.base_texture) == -1) then + if not valid_texture(self, def.textures) then + -- compatiblity with old simple mobs textures if type(def.textures[1]) == "string" then def.textures = {def.textures} end - local c = 1 - if #def.textures > c then c = #def.textures end + if not self.texture_selected then + local c = 1 + if #def.textures > c then c = #def.textures end + self.texture_selected = math.random(c) + end - self.base_texture = def.textures[math.random(c)] + self.base_texture = def.textures[self.texture_selected] self.base_mesh = def.mesh self.base_size = self.visual_size self.base_colbox = self.collisionbox From 72c3f87925bc08f6d07869cca1ac4ae171eb44ab Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 12 May 2023 15:33:49 +0100 Subject: [PATCH 115/155] Reduce excessive mob overhead --- mods/ENTITIES/mcl_mobs/api.lua | 7 +++++-- mods/ENTITIES/mcl_mobs/effects.lua | 6 +++--- mods/ENTITIES/mcl_mobs/movement.lua | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 9c0beaeec..092c8939c 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -407,8 +407,11 @@ local function on_step_work (self, dtime) self:check_water_flow() self:env_danger_movement_checks (dtime) - -- Follow code is heavy and probably shouldn't run when not in range, but we need to extract the cancel follow stuff - self:check_follow() + if player_in_active_range then + if mcl_util.check_dtime_timer(self, dtime, "onstep_follow", 0.2) then + self:check_follow() + end + end self:flop() self:check_smooth_rotation(dtime) diff --git a/mods/ENTITIES/mcl_mobs/effects.lua b/mods/ENTITIES/mcl_mobs/effects.lua index 696994d0d..1a1578834 100644 --- a/mods/ENTITIES/mcl_mobs/effects.lua +++ b/mods/ENTITIES/mcl_mobs/effects.lua @@ -269,7 +269,7 @@ function mob_class:set_animation(anim, fixed_frame) - if self:flight_check() and self.fly and anim == "walk" then anim = "fly" end + if self.fly and self:flight_check() and anim == "walk" then anim = "fly" end self._current_animation = self._current_animation or "" @@ -324,12 +324,12 @@ local function who_are_you_looking_at (self) self._locked_object = nil end elseif not self._locked_object then - if math.random(1, 30) then + if mcl_util.check_dtime_timer(self, dtime, "step_look_for_someone", 0.2) then --minetest.log("Change look check: ".. self.name) -- For the wither this was 20/60=0.33, so probably need to rebalance and divide rates. -- but frequency of check isn't good as it is costly. Making others too infrequent requires testing - local chance = 20/self.curiosity + local chance = 150/self.curiosity if chance < 1 then chance = 1 end local look_at_player_chance = math.random(chance) diff --git a/mods/ENTITIES/mcl_mobs/movement.lua b/mods/ENTITIES/mcl_mobs/movement.lua index 469ac9e85..21595ef54 100644 --- a/mods/ENTITIES/mcl_mobs/movement.lua +++ b/mods/ENTITIES/mcl_mobs/movement.lua @@ -623,7 +623,7 @@ function mob_class:check_runaway_from() end --- follow player if owner or holding item, if fish outta water then flop +-- follow player if owner or holding item function mob_class:check_follow() -- find player to follow if (self.follow ~= "" or self.order == "follow") and not self.following From 519b237ba85d570d28d2f905e3341bfbe113afde Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 12 May 2023 19:42:55 +0100 Subject: [PATCH 116/155] Jumping check only called once per mob_step and refactor duplicate water danger, cliff fall logic --- mods/ENTITIES/mcl_mobs/api.lua | 27 ++++++----- mods/ENTITIES/mcl_mobs/movement.lua | 75 ++++++++++++++--------------- 2 files changed, 52 insertions(+), 50 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 092c8939c..485ea1f65 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -325,6 +325,8 @@ function mob_class:do_states(dtime) return end + self:env_danger_movement_checks (dtime) + if self.state == PATHFINDING then self:check_gowp(dtime) elseif self.state == "attack" then @@ -405,13 +407,13 @@ local function on_step_work (self, dtime) -- End: Death/damage processing self:check_water_flow() - self:env_danger_movement_checks (dtime) - if player_in_active_range then - if mcl_util.check_dtime_timer(self, dtime, "onstep_follow", 0.2) then - self:check_follow() - end + if not self._jumping_cliff then + self._can_jump_cliff = self:can_jump_cliff() + else + self._can_jump_cliff = false end + self:flop() self:check_smooth_rotation(dtime) @@ -421,14 +423,17 @@ local function on_step_work (self, dtime) self:check_head_swivel(dtime) - if self.jump_sound_cooloff > 0 then self.jump_sound_cooloff = self.jump_sound_cooloff - dtime end - self:do_jump() - - self:check_runaway_from() - self:monster_attack() - self:npc_attack() + if mcl_util.check_dtime_timer(self, dtime, "onstep_engage", 0.2) then + self:check_follow() + self:check_runaway_from() + self:monster_attack() + self:npc_attack() + end self:check_herd(dtime) + + if self.jump_sound_cooloff > 0 then self.jump_sound_cooloff = self.jump_sound_cooloff - dtime end + self:do_jump() end self:check_aggro(dtime) diff --git a/mods/ENTITIES/mcl_mobs/movement.lua b/mods/ENTITIES/mcl_mobs/movement.lua index 21595ef54..147930b87 100644 --- a/mods/ENTITIES/mcl_mobs/movement.lua +++ b/mods/ENTITIES/mcl_mobs/movement.lua @@ -4,8 +4,9 @@ local DEFAULT_FALL_SPEED = -9.81*1.5 local FLOP_HEIGHT = 6 local FLOP_HOR_SPEED = 1.5 -local node_snow = "mcl_core:snow" +local CHECK_HERD_FREQUENCY = 4 +local node_snow = "mcl_core:snow" local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false @@ -202,12 +203,8 @@ function mob_class:can_jump_cliff() end -- is mob facing a cliff or danger -function mob_class:is_at_cliff_or_danger(can_jump_cliff) - if can_jump_cliff == nil then - can_jump_cliff = self:can_jump_cliff() - end - - if self.fear_height == 0 or can_jump_cliff or self._jumping_cliff or not self.object:get_luaentity() then -- 0 for no falling protection! +function mob_class:is_at_cliff_or_danger() + if self.fear_height == 0 or self._jumping_cliff or self._can_jump_cliff or not self.object:get_luaentity() then -- 0 for no falling protection! return false end @@ -242,12 +239,16 @@ end -- copy the 'mob facing cliff_or_danger check' from above, and rework to avoid water -function mob_class:is_at_water_danger(can_jump_cliff) - if can_jump_cliff == nil then - can_jump_cliff = self:can_jump_cliff() +function mob_class:is_at_water_danger() + if self.water_damage == 0 and self.breath_max == -1 then + --minetest.log("Do not need a water check for: " .. self.name) + return end - if not self.object:get_luaentity() or can_jump_cliff or self._jumping_cliff then + local in_water_danger = self:is_node_waterhazard(self.standing_in) or self:is_node_waterhazard(self.standing_on) + if in_water_danger then return false end -- If you're in trouble, do not stop + + if not self.object:get_luaentity() or self._jumping_cliff or self._can_jump_cliff then return false end local yaw = self.object:get_yaw() @@ -262,25 +263,16 @@ function mob_class:is_at_water_danger(can_jump_cliff) local ypos = pos.y + self.collisionbox[2] -- just above floor - local free_fall, blocker = minetest.line_of_sight( + local los, blocker = minetest.line_of_sight( vector.new(pos.x + dir_x, ypos, pos.z + dir_z), vector.new(pos.x + dir_x, ypos - 3, pos.z + dir_z)) - if free_fall then - return true - else + if not los then local bnode = minetest.get_node(blocker) local waterdanger = self:is_node_waterhazard(bnode.name) - if - waterdanger and (self:is_node_waterhazard(self.standing_in) or self:is_node_waterhazard( self.standing_on)) then - return false - elseif waterdanger and (self:is_node_waterhazard(self.standing_in) or self:is_node_waterhazard(self.standing_on)) == false then + + if waterdanger and not in_water_danger then return true - else - local def = minetest.registered_nodes[bnode.name] - if def and def.walkable then - return false - end end end @@ -290,24 +282,29 @@ end function mob_class:env_danger_movement_checks(dtime) local yaw = 0 - local can_jump_cliff = self:can_jump_cliff() - if self.state ~= "attack" and self:is_at_water_danger(can_jump_cliff) then - if math.random(1, 10) <= 6 then - self:set_velocity(0) - self.state = "stand" - self:set_animation( "stand") + if self.state ~= "attack" and self:is_at_water_danger() then + --minetest.log("At water danger for mob, stop?: " .. self.name) + if math.random(1, 10) <= 7 then + if self.state ~= "stand" then + self:set_velocity(0) + self.state = "stand" + self:set_animation( "stand") + end yaw = yaw + math.random(-0.5, 0.5) yaw = self:set_yaw( yaw, 8) + return end end - if self:is_at_cliff_or_danger(can_jump_cliff) then - self:set_velocity(0) - self.state = "stand" - self:set_animation( "stand") + --[[if self:is_at_cliff_or_danger(can_jump_cliff) then + if self.state ~= "stand" then + self:set_velocity(0) + self.state = "stand" + self:set_animation( "stand") + end local yaw = self.object:get_yaw() or 0 yaw = self:set_yaw( yaw + 0.78, 8) - end + end--]] end -- jump if facing a solid node (not fences or gates) @@ -378,7 +375,7 @@ function mob_class:do_jump() end local ndef = minetest.registered_nodes[nod.name] - if self.walk_chance == 0 or ndef and ndef.walkable or self:can_jump_cliff() then + if self.walk_chance == 0 or ndef and ndef.walkable or self._can_jump_cliff then if minetest.get_item_group(nod.name, "fence") == 0 and minetest.get_item_group(nod.name, "fence_gate") == 0 @@ -388,7 +385,7 @@ function mob_class:do_jump() v.y = self.jump_height + 0.1 * 3 - if self:can_jump_cliff() then + if self._can_jump_cliff then v=vector.multiply(v, vector.new(2.8,1,2.8)) end @@ -724,7 +721,7 @@ function mob_class:flop() return elseif self.state == "flop" then self.state = "stand" - self.object:set_acceleration({x = 0, y = 0, z = 0}) + self.object:set_acceleration(vector.zero()) self:set_velocity(0) end end @@ -756,7 +753,7 @@ function mob_class:check_herd(dtime) if self.move_in_group == false then return end check_herd_timer = check_herd_timer + dtime - if check_herd_timer < 4 then return end + if check_herd_timer < CHECK_HERD_FREQUENCY then return end check_herd_timer = 0 for _,o in pairs(minetest.get_objects_inside_radius(pos,self.view_range)) do local l = o:get_luaentity() From 3d1fb8cf4af394e42263ccb3f994a14988740584 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 12 May 2023 20:17:13 +0100 Subject: [PATCH 117/155] Clean up and optimise falling --- mods/ENTITIES/mcl_mobs/physics.lua | 37 +++++++++++------------------- 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/physics.lua b/mods/ENTITIES/mcl_mobs/physics.lua index 2859cfe98..55199d9f3 100644 --- a/mods/ENTITIES/mcl_mobs/physics.lua +++ b/mods/ENTITIES/mcl_mobs/physics.lua @@ -903,47 +903,36 @@ function mob_class:falling(pos) -- floating in water (or falling) local v = self.object:get_velocity() if v then + local new_acceleration + if v.y > 0 then -- apply gravity when moving up - self.object:set_acceleration({ - x = 0, - y = DEFAULT_FALL_SPEED, - z = 0 - }) - + new_acceleration = vector.new(0, DEFAULT_FALL_SPEED, 0) elseif v.y <= 0 and v.y > self.fall_speed then -- fall downwards at set speed - self.object:set_acceleration({ - x = 0, - y = self.fall_speed, - z = 0 - }) + new_acceleration = vector.new(0, self.fall_speed, 0) else -- stop accelerating once max fall speed hit - self.object:set_acceleration({x = 0, y = 0, z = 0}) + new_acceleration =vector.zero() end + + self.object:set_acceleration(new_acceleration) end local acc = self.object:get_acceleration() - if minetest.registered_nodes[node_ok(pos).name].groups.lava then + local registered_node = minetest.registered_nodes[node_ok(pos).name] + + if registered_node.groups.lava then if acc and self.floats_on_lava == 1 then - self.object:set_acceleration({ - x = 0, - y = -self.fall_speed / (math.max(1, v.y) ^ 2), - z = 0 - }) + self.object:set_acceleration(vector.new(0, -self.fall_speed / (math.max(1, v.y) ^ 2), 0)) end end -- in water then float up - if minetest.registered_nodes[node_ok(pos).name].groups.water then + if registered_node.groups.water then if acc and self.floats == 1 then - self.object:set_acceleration({ - x = 0, - y = -self.fall_speed / (math.max(1, v.y) ^ 2), - z = 0 - }) + self.object:set_acceleration(vector.new(0, -self.fall_speed / (math.max(1, v.y) ^ 2), 0)) end else -- fall damage onto solid ground From f326fa620f1e715c541d56d59be4afce303f42f6 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 12 May 2023 21:00:01 +0100 Subject: [PATCH 118/155] Optimise do states and env danger check --- mods/ENTITIES/mcl_mobs/api.lua | 8 +++---- mods/ENTITIES/mcl_mobs/movement.lua | 33 ++++++++++++++++++++--------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 485ea1f65..323d25f10 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -316,7 +316,7 @@ end -- execute current state (stand, walk, run, attacks) -- returns true if mob has died -function mob_class:do_states(dtime) +function mob_class:do_states(dtime, player_in_active_range) --if self.can_open_doors then check_doors(self) end -- knockback timer. set in on_punch @@ -325,7 +325,7 @@ function mob_class:do_states(dtime) return end - self:env_danger_movement_checks (dtime) + self:env_danger_movement_checks(player_in_active_range) if self.state == PATHFINDING then self:check_gowp(dtime) @@ -336,7 +336,7 @@ function mob_class:do_states(dtime) else if mcl_util.check_dtime_timer(self, dtime, "onstep_dostates", 1) then if self.state == "stand" then - self:do_states_stand() + self:do_states_stand(player_in_active_range) elseif self.state == "walk" then self:do_states_walk() elseif self.state == "runaway" then @@ -452,7 +452,7 @@ local function on_step_work (self, dtime) end end - if self:do_states(dtime) then return end + if self:do_states(dtime, player_in_active_range) then return end if mobs_debug then self:update_tag() end diff --git a/mods/ENTITIES/mcl_mobs/movement.lua b/mods/ENTITIES/mcl_mobs/movement.lua index 147930b87..377e25f6e 100644 --- a/mods/ENTITIES/mcl_mobs/movement.lua +++ b/mods/ENTITIES/mcl_mobs/movement.lua @@ -6,6 +6,8 @@ local FLOP_HOR_SPEED = 1.5 local CHECK_HERD_FREQUENCY = 4 +local PATHFINDING = "gowp" + local node_snow = "mcl_core:snow" local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false @@ -279,10 +281,19 @@ function mob_class:is_at_water_danger() return false end -function mob_class:env_danger_movement_checks(dtime) +function mob_class:env_danger_movement_checks(player_in_active_range) local yaw = 0 - if self.state ~= "attack" and self:is_at_water_danger() then + if not player_in_active_range then return end + + if self.state == PATHFINDING + or self.state == "attack" + or self.state == "stand" + or self.state == "runaway" then + return + end + + if self:is_at_water_danger() then --minetest.log("At water danger for mob, stop?: " .. self.name) if math.random(1, 10) <= 7 then if self.state ~= "stand" then @@ -884,7 +895,7 @@ function mob_class:do_states_walk() end end -function mob_class:do_states_stand() +function mob_class:do_states_stand(player_in_active_range) local yaw = self.object:get_yaw() or 0 if math.random(1, 4) == 1 then @@ -928,14 +939,16 @@ function mob_class:do_states_stand() if self.order == "stand" or self.order == "sleep" or self.order == "work" then else - if self.walk_chance ~= 0 - and self.facing_fence ~= true - and math.random(1, 100) <= self.walk_chance - and self:is_at_cliff_or_danger() == false then + if player_in_active_range then + if self.walk_chance ~= 0 + and self.facing_fence ~= true + and math.random(1, 100) <= self.walk_chance + and self:is_at_cliff_or_danger() == false then - self:set_velocity(self.walk_velocity) - self.state = "walk" - self:set_animation( "walk") + self:set_velocity(self.walk_velocity) + self.state = "walk" + self:set_animation( "walk") + end end end end From 952a90bfde3665a48f9059fa3d73cb08eb6a5825 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 12 May 2023 23:45:11 +0100 Subject: [PATCH 119/155] Re-organise mob_step for better clarity --- mods/ENTITIES/mcl_mobs/api.lua | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 323d25f10..d4913305d 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -436,22 +436,23 @@ local function on_step_work (self, dtime) self:do_jump() end - self:check_aggro(dtime) - - self:check_particlespawners(dtime) - - if self.do_custom and self.do_custom(self, dtime) == false then return end - if mcl_util.check_dtime_timer(self, dtime, "onstep_occassional", 1) then - self:check_breeding() if player_in_active_range then self:check_item_pickup() self:set_armor_texture() self:step_opinion_sound(dtime) end + + self:check_breeding() end + self:check_aggro(dtime) + + self:check_particlespawners(dtime) + + if self.do_custom and self.do_custom(self, dtime) == false then return end + if self:do_states(dtime, player_in_active_range) then return end if mobs_debug then self:update_tag() end From 5a059379b289456d457cf3b5644e8d434cce2c41 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Sat, 13 May 2023 18:10:20 +0100 Subject: [PATCH 120/155] Group damage logic. Remove physics falling logic out of suspend with duplicate falling call --- mods/ENTITIES/mcl_mobs/api.lua | 19 ++++--------------- mods/ENTITIES/mcl_mobs/physics.lua | 15 ++++++++++----- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index d4913305d..a9a1a0dad 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -387,25 +387,14 @@ local function on_step_work (self, dtime) end if self:falling(pos) then return end - - local player_in_active_range = self:player_in_active_range() - - self:check_suspend(player_in_active_range) - - if not self.fire_resistant then - mcl_burning.tick(self.object, dtime, self) - if not self.object:get_pos() then return end -- mcl_burning.tick may remove object immediately - - if self:check_for_death("fire", {type = "fire"}) then - return true - end - end - - if self:env_damage (dtime, pos) then return end + if self:step_damage (dtime, pos) then return end if self.state == "die" then return end -- End: Death/damage processing + local player_in_active_range = self:player_in_active_range() + self:check_suspend(player_in_active_range) + self:check_water_flow() if not self._jumping_cliff then diff --git a/mods/ENTITIES/mcl_mobs/physics.lua b/mods/ENTITIES/mcl_mobs/physics.lua index 55199d9f3..090b921c7 100644 --- a/mods/ENTITIES/mcl_mobs/physics.lua +++ b/mods/ENTITIES/mcl_mobs/physics.lua @@ -820,11 +820,19 @@ function mob_class:do_env_damage() return self:check_for_death("unknown", {type = "unknown"}) end -function mob_class:env_damage (dtime, pos) +function mob_class:step_damage (dtime, pos) + if not self.fire_resistant then + mcl_burning.tick(self.object, dtime, self) + if not self.object:get_pos() then return end -- mcl_burning.tick may remove object immediately + + if self:check_for_death("fire", {type = "fire"}) then + return true + end + end + -- environmental damage timer (every 1 second) self.env_damage_timer = self.env_damage_timer + dtime - if self.env_damage_timer > 1 then self.env_damage_timer = 0 @@ -1019,9 +1027,6 @@ function mob_class:check_suspend(player_in_active_range) self.object:set_acceleration(vector.zero()) self.object:set_velocity(vector.zero()) end - if acc.y == 0 and node_under == "air" then - self:falling(pos) - end end return true end From d467b80491e0e76382f1cf222a5b9473ed6fcf43 Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Fri, 12 May 2023 14:46:33 -0600 Subject: [PATCH 121/155] Fix waterlogged mangrove roots leaving water in the nether --- mods/ITEMS/mcl_buckets/register.lua | 26 +++++++++++--------------- mods/ITEMS/mcl_mangrove/init.lua | 21 ++++++++++++++++++++- mods/ITEMS/mcl_mangrove/mod.conf | 2 +- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/mods/ITEMS/mcl_buckets/register.lua b/mods/ITEMS/mcl_buckets/register.lua index 109941ab0..1d247e827 100644 --- a/mods/ITEMS/mcl_buckets/register.lua +++ b/mods/ITEMS/mcl_buckets/register.lua @@ -57,6 +57,7 @@ if mod_mcl_core then tt_help = S("Places a water source"), extra_check = function(pos, placer) local nn = minetest.get_node(pos).name + local dim = mcl_worlds.pos_to_dimension(pos) -- Pour water into cauldron if minetest.get_item_group(nn, "cauldron") ~= 0 then -- Put water into cauldron @@ -66,17 +67,14 @@ if mod_mcl_core then sound_place("mcl_core:water_source", pos) return false, true -- Put water into mangrove roots - elseif minetest.get_node(pos).name == "mcl_mangrove:mangrove_roots" then + elseif minetest.get_node(pos).name == "mcl_mangrove:mangrove_roots" and dim ~= "nether" then minetest.set_node(pos, {name="mcl_mangrove:water_logged_roots"}) sound_place("mcl_core:water_source", pos) 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, true - end + elseif dim == "nether" then + minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true) + return false, true end end, groups = { water_bucket = 1 }, @@ -96,6 +94,7 @@ if mod_mclx_core then tt_help = S("Places a river water source"), extra_check = function(pos, placer) local nn = minetest.get_node(pos).name + local dim = mcl_worlds.pos_to_dimension(pos) -- Pour into cauldron if minetest.get_item_group(nn, "cauldron") ~= 0 then -- Put water into cauldron @@ -105,17 +104,14 @@ if mod_mclx_core then sound_place("mcl_core:water_source", pos) return false, true -- Put river water into mangrove roots - elseif minetest.get_node(pos).name == "mcl_mangrove:mangrove_roots" then + elseif minetest.get_node(pos).name == "mcl_mangrove:mangrove_roots" and dim ~= "nether" then minetest.set_node(pos, {name="mcl_mangrove:river_water_logged_roots"}) sound_place("mcl_core:water_source", pos) 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, true - end + -- Evaporate water if used in Nether (except on cauldron) + elseif dim == "nether" then + minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true) + return false, true end end, groups = { water_bucket = 1 }, diff --git a/mods/ITEMS/mcl_mangrove/init.lua b/mods/ITEMS/mcl_mangrove/init.lua index 3e1cecba9..dd2b653c4 100644 --- a/mods/ITEMS/mcl_mangrove/init.lua +++ b/mods/ITEMS/mcl_mangrove/init.lua @@ -352,10 +352,20 @@ local wlroots = { handy = 1, hoey = 1, water=3, liquid=3, puts_out_fire=1, dig_by_piston = 1, deco_block = 1, not_in_creative_inventory=1 }, _mcl_blast_resistance = 100, _mcl_hardness = -1, -- Hardness intentionally set to infinite instead of 100 (Minecraft value) to avoid problems in creative mode + on_construct = function(pos) + 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) + minetest.set_node(pos, {name="mcl_mangrove:mangrove_roots"}) + end + end, after_dig_node = function(pos) local node = minetest.get_node(pos) - if minetest.get_item_group(node.name, "water") == 0 then + local dim = mcl_worlds.pos_to_dimension(pos) + if minetest.get_item_group(node.name, "water") == 0 and dim ~= "nether" then minetest.set_node(pos, {name="mcl_core:water_source"}) + else + minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true) end end, } @@ -369,6 +379,15 @@ rwlroots.tiles = { "("..water_tex..")^mcl_mangrove_roots_side.png", "("..water_tex..")^mcl_mangrove_roots_side.png", } +rwlroots.after_dig_node = function(pos) + local node = minetest.get_node(pos) + local dim = mcl_worlds.pos_to_dimension(pos) + if minetest.get_item_group(node.name, "water") == 0 and dim ~= "nether" then + minetest.set_node(pos, {name="mclx_core:river_water_source"}) + else + minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true) + end +end minetest.register_node("mcl_mangrove:water_logged_roots", wlroots) minetest.register_node("mcl_mangrove:river_water_logged_roots",rwlroots) diff --git a/mods/ITEMS/mcl_mangrove/mod.conf b/mods/ITEMS/mcl_mangrove/mod.conf index fb71efbf8..cdc9a6a1c 100644 --- a/mods/ITEMS/mcl_mangrove/mod.conf +++ b/mods/ITEMS/mcl_mangrove/mod.conf @@ -1,3 +1,3 @@ name = mcl_mangrove author = thunder1035 -depends = mcl_core, mcl_doors, mcl_stairs, mcl_walls, mclx_fences, mcl_boats, mcl_flowerpots, mcl_mud, mcl_util +depends = mcl_core, mcl_doors, mcl_stairs, mcl_walls, mclx_fences, mcl_boats, mcl_flowerpots, mcl_mud, mcl_util, mcl_worlds From 0903ac60e43a6497051a23d0bbd5593367386390 Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Sun, 30 Apr 2023 19:52:43 -0600 Subject: [PATCH 122/155] Make custom sign registration not absolutely require color --- mods/ITEMS/mcl_signs/signs_api.lua | 51 ++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/mods/ITEMS/mcl_signs/signs_api.lua b/mods/ITEMS/mcl_signs/signs_api.lua index 6d902c5dd..79bc2591b 100644 --- a/mods/ITEMS/mcl_signs/signs_api.lua +++ b/mods/ITEMS/mcl_signs/signs_api.lua @@ -797,10 +797,18 @@ function mcl_signs.register_sign_custom (modname, _name, tiles, color, inventory new_sign = table.copy(mcl_signs.wall_standard) - new_sign.wield_image = "(" .. wield_image .. "^[multiply:" .. color .. ")" - new_sign.tiles = { "(" .. tiles .. "^[multiply:" .. color .. ")" } - new_sign.inventory_image = "(" .. inventory_image .. "^[multiply:" .. color .. ")" + if not color or color == nil then + new_sign.wield_image = wield_image + new_sign.tiles = { tiles } + new_sign.inventory_image = inventory_image + else + new_sign.wield_image = "(" .. wield_image .. "^[multiply:" .. color .. ")" + new_sign.tiles = { "(" .. tiles .. "^[multiply:" .. color .. ")" } + new_sign.inventory_image = "(" .. inventory_image .. "^[multiply:" .. color .. ")" + end + new_sign.description = S(ttsign) + -- currently have to do this, because of how the base node placement works. new_sign.on_place = function(itemstack, placer, pointed_thing) local above = pointed_thing.above @@ -905,9 +913,15 @@ function mcl_signs.register_sign_custom (modname, _name, tiles, color, inventory local new_sign_standing = {} new_sign_standing = table.copy(mcl_signs.standing_standard) new_sign_standing.drop = "mcl_signs:wall_sign" .. _name - new_sign_standing.wield_image = "(" .. wield_image .. "^[multiply:" .. color .. ")" - new_sign_standing.tiles = { "(" .. tiles .. "^[multiply:" .. color .. ")" } - new_sign_standing.inventory_image = "(" .. inventory_image .. "^[multiply:" .. color .. ")" + if not color or color == nil then + new_sign_standing.wield_image = wield_image + new_sign_standing.tiles = { tiles } + new_sign_standing.inventory_image = inventory_image + else + new_sign_standing.wield_image = "(" .. wield_image .. "^[multiply:" .. color .. ")" + new_sign_standing.tiles = { "(" .. tiles .. "^[multiply:" .. color .. ")" } + new_sign_standing.inventory_image = "(" .. inventory_image .. "^[multiply:" .. color .. ")" + end new_sign_standing.on_rotate = function(pos, node, user, mode) if mode == screwdriver.ROTATE_FACE then node.name = "mcl_signs:standing_sign22_5" .. _name @@ -1253,9 +1267,15 @@ function mcl_signs.reregister_sign_custom (modname, _name, tiles, color, invento new_sign = table.copy(mcl_signs.wall_standard) - new_sign.wield_image = "(" .. wield_image .. "^[multiply:" .. color .. ")" - new_sign.tiles = { "(" .. tiles .. "^[multiply:" .. color .. ")" } - new_sign.inventory_image = "(" .. inventory_image .. "^[multiply:" .. color .. ")" + if not color or color == nil then + new_sign.wield_image = wield_image + new_sign.tiles = { tiles } + new_sign.inventory_image = inventory_image + else + new_sign.wield_image = "(" .. wield_image .. "^[multiply:" .. color .. ")" + new_sign.tiles = { "(" .. tiles .. "^[multiply:" .. color .. ")" } + new_sign.inventory_image = "(" .. inventory_image .. "^[multiply:" .. color .. ")" + end new_sign.description = S(ttsign) -- currently have to do this, because of how the base node placement works. new_sign.on_place = function(itemstack, placer, pointed_thing) @@ -1360,10 +1380,15 @@ function mcl_signs.reregister_sign_custom (modname, _name, tiles, color, invento -- standing sign base. local new_sign_standing = {} new_sign_standing = table.copy(mcl_signs.standing_standard) - new_sign_standing.drop = "mcl_signs:wall_sign" .. _name - new_sign_standing.wield_image = "(" .. wield_image .. "^[multiply:" .. color .. ")" - new_sign_standing.tiles = { "(" .. tiles .. "^[multiply:" .. color .. ")" } - new_sign_standing.inventory_image = "(" .. inventory_image .. "^[multiply:" .. color .. ")" + if not color or color == nil then + new_sign_standing.wield_image = wield_image + new_sign_standing.tiles = { tiles } + new_sign_standing.inventory_image = inventory_image + else + new_sign_standing.wield_image = "(" .. wield_image .. "^[multiply:" .. color .. ")" + new_sign_standing.tiles = { "(" .. tiles .. "^[multiply:" .. color .. ")" } + new_sign_standing.inventory_image = "(" .. inventory_image .. "^[multiply:" .. color .. ")" + end new_sign_standing.on_rotate = function(pos, node, user, mode) if mode == screwdriver.ROTATE_FACE then node.name = "mcl_signs:standing_sign22_5" .. _name From 5071a7c789152e3ace0052f89675b24c73c144c0 Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Sun, 30 Apr 2023 20:26:11 -0600 Subject: [PATCH 123/155] Fix translator translating sign description api side instead of mod side --- mods/ITEMS/mcl_signs/init.lua | 18 +++++++++--------- mods/ITEMS/mcl_signs/signs_api.lua | 8 ++++---- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/mods/ITEMS/mcl_signs/init.lua b/mods/ITEMS/mcl_signs/init.lua index 6a5f01c5f..117f5665c 100644 --- a/mods/ITEMS/mcl_signs/init.lua +++ b/mods/ITEMS/mcl_signs/init.lua @@ -93,41 +93,41 @@ mcl_signs.build_signs_info() -- ---------------------------- -- -- Standard (original) Sign -mcl_signs.register_sign("mcl_core", "#ffffff", "", "Sign") +mcl_signs.register_sign("mcl_core", "#ffffff", "", S("Sign")) mcl_signs.register_sign_craft("mcl_core", "mcl_core:wood", "") -- birchwood Sign "#d5cb8d" / "#ffdba7" mcl_signs.register_sign_custom("mcl_core", "_birchwood", "mcl_signs_sign_greyscale.png","#ffdba7", "mcl_signs_default_sign_greyscale.png", - "mcl_signs_default_sign_greyscale.png", "Birch Sign" + "mcl_signs_default_sign_greyscale.png", S("Birch Sign") ) mcl_signs.register_sign_craft("mcl_core", "mcl_core:birchwood", "_birchwood") -- sprucewood Sign mcl_signs.register_sign_custom("mcl_core", "_sprucewood", "mcl_signs_sign_dark.png","#ffffff", "mcl_signs_default_sign_dark.png", - "mcl_signs_default_sign_dark.png", "Spruce Sign" + "mcl_signs_default_sign_dark.png", S("Spruce Sign") ) mcl_signs.register_sign_craft("mcl_core", "mcl_core:sprucewood", "_sprucewood") -- darkwood Sign "#291f1a" / "#856443" mcl_signs.register_sign_custom("mcl_core", "_darkwood", "mcl_signs_sign_greyscale.png","#856443", "mcl_signs_default_sign_greyscale.png", - "mcl_signs_default_sign_greyscale.png", "Dark Oak Sign" + "mcl_signs_default_sign_greyscale.png", S("Dark Oak Sign") ) mcl_signs.register_sign_craft("mcl_core", "mcl_core:darkwood", "_darkwood") -- junglewood Sign -mcl_signs.register_sign("mcl_core", "#866249", "_junglewood", "Jungle Sign") +mcl_signs.register_sign("mcl_core", "#866249", "_junglewood", S("Jungle Sign")) mcl_signs.register_sign_craft("mcl_core", "mcl_core:junglewood", "_junglewood") -- acaciawood Sign "b8693d" -mcl_signs.register_sign("mcl_core", "#ea7479", "_acaciawood", "Acacia Sign") +mcl_signs.register_sign("mcl_core", "#ea7479", "_acaciawood", S("Acacia Sign")) mcl_signs.register_sign_craft("mcl_core", "mcl_core:acaciawood", "_acaciawood") if minetest.get_modpath("mcl_mangrove") then -- mangrove_wood Sign "#c7545c" - mcl_signs.register_sign("mcl_mangrove", "#b8693d", "_mangrove_wood", "Mangrove Sign") + mcl_signs.register_sign("mcl_mangrove", "#b8693d", "_mangrove_wood", S("Mangrove Sign")) mcl_signs.register_sign_craft("mcl_mangrove", "mcl_mangrove:mangrove_wood", "_mangrove_wood") end @@ -137,13 +137,13 @@ if minetest.get_modpath("mcl_crimson") then -- warped_hyphae_wood Sign mcl_signs.register_sign_custom("mcl_crimson","_warped_hyphae_wood", "mcl_signs_sign_greyscale.png", "#9f7dcf", "mcl_signs_default_sign_greyscale.png", "mcl_signs_default_sign_greyscale.png", - "Warped Hyphae Sign") + S("Warped Hyphae Sign")) mcl_signs.register_sign_craft("mcl_crimson", "mcl_crimson:warped_hyphae_wood", "_warped_hyphae_wood") -- crimson_hyphae_wood Sign mcl_signs.register_sign_custom("mcl_crimson", "_crimson_hyphae_wood","mcl_signs_sign_greyscale.png", "#c35f51","mcl_signs_default_sign_greyscale.png", "mcl_signs_default_sign_greyscale.png", - "Crimson Hyphae Sign") + S("Crimson Hyphae Sign")) mcl_signs.register_sign_craft("mcl_crimson", "mcl_crimson:crimson_hyphae_wood", "_crimson_hyphae_wood") end diff --git a/mods/ITEMS/mcl_signs/signs_api.lua b/mods/ITEMS/mcl_signs/signs_api.lua index 79bc2591b..3d8bd3e49 100644 --- a/mods/ITEMS/mcl_signs/signs_api.lua +++ b/mods/ITEMS/mcl_signs/signs_api.lua @@ -550,7 +550,7 @@ function mcl_signs.register_sign (modname, color, _name, ttsign) end new_sign = table.copy(mcl_signs.wall_standard) - new_sign.description = S(ttsign) + new_sign.description = ttsign new_sign.wield_image = "(mcl_signs_default_sign.png^[multiply:" .. color .. ")" new_sign.tiles = { "(mcl_signs_sign.png^[multiply:" .. color .. ")" } @@ -807,7 +807,7 @@ function mcl_signs.register_sign_custom (modname, _name, tiles, color, inventory new_sign.inventory_image = "(" .. inventory_image .. "^[multiply:" .. color .. ")" end - new_sign.description = S(ttsign) + new_sign.description = ttsign -- currently have to do this, because of how the base node placement works. new_sign.on_place = function(itemstack, placer, pointed_thing) @@ -1027,7 +1027,7 @@ function mcl_signs.reregister_sign (modname, color, _name, ttsign) end new_sign = table.copy(mcl_signs.wall_standard) - new_sign.description = S(ttsign) + new_sign.description = ttsign new_sign.wield_image = "(mcl_signs_default_sign.png^[multiply:" .. color .. ")" new_sign.tiles = { "(mcl_signs_sign.png^[multiply:" .. color .. ")" } @@ -1276,7 +1276,7 @@ function mcl_signs.reregister_sign_custom (modname, _name, tiles, color, invento new_sign.tiles = { "(" .. tiles .. "^[multiply:" .. color .. ")" } new_sign.inventory_image = "(" .. inventory_image .. "^[multiply:" .. color .. ")" end - new_sign.description = S(ttsign) + new_sign.description = ttsign -- currently have to do this, because of how the base node placement works. new_sign.on_place = function(itemstack, placer, pointed_thing) local above = pointed_thing.above From e2963f88a76057345fac56b8dffc4723883a62c0 Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Fri, 12 May 2023 15:54:42 -0600 Subject: [PATCH 124/155] Update dead bush generation Removed Taiga biome and changed the generation values --- mods/MAPGEN/mcl_biomes/init.lua | 56 +++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/mods/MAPGEN/mcl_biomes/init.lua b/mods/MAPGEN/mcl_biomes/init.lua index ddb537b39..d42720d26 100644 --- a/mods/MAPGEN/mcl_biomes/init.lua +++ b/mods/MAPGEN/mcl_biomes/init.lua @@ -5391,11 +5391,11 @@ local function register_decorations() -- Dead bushes minetest.register_decoration({ deco_type = "simple", - place_on = {"group:sand", "mcl_core:podzol", "mcl_core:dirt", "mcl_core:dirt_with_grass", "mcl_core:coarse_dirt", "group:hardened_clay"}, + place_on = {"mcl_core:podzol", "mcl_core:dirt", "mcl_core:dirt_with_grass", "mcl_core:coarse_dirt", "group:hardened_clay"}, sidelen = 16, noise_params = { - offset = 0.0, - scale = 0.035, + offset = 0.01, + scale = 0.003, spread = {x = 100, y = 100, z = 100}, seed = 1972, octaves = 3, @@ -5403,7 +5403,43 @@ local function register_decorations() }, y_min = 4, y_max = mcl_vars.mg_overworld_max, - biomes = {"Desert", "Mesa", "Mesa_sandlevel", "MesaPlateauF", "MesaPlateauF_sandlevel", "MesaPlateauF_grasstop", "MesaBryce", "Taiga", "MegaTaiga"}, + biomes = {"MegaSpruceTaiga", "MegaTaiga"}, + decoration = "mcl_core:deadbush", + height = 1, + }) + minetest.register_decoration({ + deco_type = "simple", + place_on = {"group:sand", "group:hardened_clay"}, + sidelen = 16, + noise_params = { + offset = 0.01, + scale = 0.006, + spread = {x = 100, y = 100, z = 100}, + seed = 1972, + octaves = 3, + persist = 0.6 + }, + y_min = 4, + y_max = mcl_vars.mg_overworld_max, + biomes = {"Desert"}, + decoration = "mcl_core:deadbush", + height = 1, + }) + minetest.register_decoration({ + deco_type = "simple", + place_on = {"group:sand", "mcl_core:podzol", "mcl_core:dirt", "mcl_core:dirt_with_grass", "mcl_core:coarse_dirt", "group:hardened_clay"}, + sidelen = 16, + noise_params = { + offset = 0.01, + scale = 0.06, + spread = {x = 100, y = 100, z = 100}, + seed = 1972, + octaves = 3, + persist = 0.6 + }, + y_min = 4, + y_max = mcl_vars.mg_overworld_max, + biomes = {"Mesa", "Mesa_sandlevel", "MesaPlateauF", "MesaPlateauF_sandlevel", "MesaPlateauF_grasstop", "MesaBryce"}, decoration = "mcl_core:deadbush", height = 1, }) @@ -5412,8 +5448,8 @@ local function register_decorations() place_on = {"group:sand", "mcl_core:dirt", "mcl_core:dirt_with_grass", "mcl_core:coarse_dirt"}, sidelen = 16, noise_params = { - offset = 0.1, - scale = 0.035, + offset = 0.01, + scale = 0.06, spread = {x = 100, y = 100, z = 100}, seed = 1972, octaves = 3, @@ -5430,8 +5466,8 @@ local function register_decorations() place_on = {"group:sand"}, sidelen = 16, noise_params = { - offset = 0.045, - scale = 0.055, + offset = 0.01, + scale = 0.06, spread = {x = 100, y = 100, z = 100}, seed = 1972, octaves = 3, @@ -5448,8 +5484,8 @@ local function register_decorations() place_on = {"group:hardened_clay"}, sidelen = 16, noise_params = { - offset = 0.010, - scale = 0.035, + offset = 0.01, + scale = 0.06, spread = {x = 100, y = 100, z = 100}, seed = 1972, octaves = 3, From e2688c03e36f61700f2d1ede898df2fe6c152ea3 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Sun, 14 May 2023 22:48:33 +0100 Subject: [PATCH 125/155] Zombie piglin no longer prevent sleep unless hostile. --- mods/ITEMS/mcl_beds/functions.lua | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index 07ad1cba5..fdb4f8f41 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -117,19 +117,23 @@ local function lay_down(player, pos, bed_pos, state, skip) end -- No sleeping if monsters nearby. - -- The exceptions above apply. - -- Zombie piglin only prevent sleep while they are hostle. for _, obj in pairs(minetest.get_objects_inside_radius(bed_pos, 8)) do if obj and not obj:is_player() then local ent = obj:get_luaentity() local mobname = ent.name local def = minetest.registered_entities[mobname] -- Approximation of monster detection range - if def.is_mob and ((mobname ~= "mobs_mc:pigman" and def.type == "monster" and not monster_exceptions[mobname]) or (mobname == "mobs_mc:pigman" and ent.state == "attack")) then - if math.abs(bed_pos.y - obj:get_pos().y) <= 5 then - return false, S("You can't sleep now, monsters are nearby!") + if def.is_mob and (def.type == "monster" or mobname == "mobs_mc:zombified_piglin") then + if monster_exceptions[mobname] or + (mobname == "mobs_mc:zombified_piglin" and ent.state ~= "attack") then + -- Some exceptions do not prevent sleep. Zombie piglin only prevent sleep while they are hostile. + else + if math.abs(bed_pos.y - obj:get_pos().y) <= 5 then + return false, S("You can't sleep now, monsters are nearby!") + end end end + end end end From 873297d2cff7d01e1b7d34297b8023dffb0f5ec9 Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Thu, 11 May 2023 19:22:51 -0600 Subject: [PATCH 126/155] Make Piglin Brutes drop golden axes Instead of dropping crossbows --- mods/ENTITIES/mobs_mc/piglin.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mods/ENTITIES/mobs_mc/piglin.lua b/mods/ENTITIES/mobs_mc/piglin.lua index a4ac2c83f..4f701b3e9 100644 --- a/mods/ENTITIES/mobs_mc/piglin.lua +++ b/mods/ENTITIES/mobs_mc/piglin.lua @@ -370,6 +370,12 @@ piglin_brute.animation = { } piglin_brute.can_despawn = false +piglin_brute.drops = { + {name = "mcl_tools:axe_gold", + chance = 8.5, + min = 1, + max = 1,}, +} mcl_mobs.register_mob("mobs_mc:piglin_brute", piglin_brute) @@ -447,4 +453,4 @@ mcl_mobs:non_spawn_specific("mobs_mc:zombified_piglin","overworld",0,minetest.LI mcl_mobs.register_egg("mobs_mc:piglin", S("Piglin"), "#7b4a17","#d5c381", 0) mcl_mobs.register_egg("mobs_mc:piglin_brute", S("Piglin Brute"), "#562b0c","#ddc89d", 0) -mcl_mobs.register_egg("mobs_mc:zombified_piglin", S("Zombie Piglin"), "#ea9393", "#4c7129", 0) \ No newline at end of file +mcl_mobs.register_egg("mobs_mc:zombified_piglin", S("Zombie Piglin"), "#ea9393", "#4c7129", 0) From 6294a61d0d4000045fade66d651ed94ccff5a9cc Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Thu, 11 May 2023 10:45:06 -0600 Subject: [PATCH 127/155] Make end crystals explode when nearby crystals are punched and explode --- mods/CORE/mcl_explosions/init.lua | 17 +++++++++++++++++ mods/ITEMS/mcl_end/end_crystal.lua | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/mods/CORE/mcl_explosions/init.lua b/mods/CORE/mcl_explosions/init.lua index 2b8b25b1e..c6a6d192f 100644 --- a/mods/CORE/mcl_explosions/init.lua +++ b/mods/CORE/mcl_explosions/init.lua @@ -352,6 +352,23 @@ local function trace_explode(pos, strength, raydirs, radius, info, direct, sourc end end end + + -- Punch End Crystals to make them explode + if ent and ent.name == "mcl_end:crystal" then + if direct then + local puncher = direct:get_luaentity() + if puncher and puncher.name == "mcl_end:crystal" then + ent.object:punch(direct, 1.0, { -- End Crystal nearby, trigger it. + full_punch_interval = 1.0, + damage_groups = {fleshy = 1}, + }, nil, nil) + else + ent.object:remove() -- Direct Exists, but it is not an end crystal, remove crystal. + end + else + ent.object:remove() -- Node exploded the end crystal, remove it. + end + end end local airs, fires = {}, {} diff --git a/mods/ITEMS/mcl_end/end_crystal.lua b/mods/ITEMS/mcl_end/end_crystal.lua index b7882a155..78fe658b4 100644 --- a/mods/ITEMS/mcl_end/end_crystal.lua +++ b/mods/ITEMS/mcl_end/end_crystal.lua @@ -40,8 +40,8 @@ local function crystal_explode(self, puncher) mcl_damage.finish_reason(reason) source = reason.source end - mcl_explosions.explode(vector.add(self.object:get_pos(), {x = 0, y = 1.5, z = 0}), strength, {drop_chance = 1}, self.object, source) minetest.after(0, self.object.remove, self.object) + mcl_explosions.explode(vector.add(self.object:get_pos(), {x = 0, y = 1.5, z = 0}), strength, {drop_chance = 1}, self.object, source) end local function set_crystal_animation(self) From 4a7a50e78cebdef53178641f4114d69d197bcbd1 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 19 May 2023 14:55:40 +0100 Subject: [PATCH 128/155] New warped and crimson hyphae plank textures --- textures/mcl_crimson_crimson_hyphae_wood.png | Bin 217 -> 695 bytes textures/mcl_crimson_warped_hyphae_wood.png | Bin 217 -> 767 bytes textures/mcl_crimson_warped_hyphae_wood_2nd.png | Bin 264 -> 767 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/textures/mcl_crimson_crimson_hyphae_wood.png b/textures/mcl_crimson_crimson_hyphae_wood.png index 0f91c96813bf6804d97f709a861f53ad1bc92d67..0061537f0f5939f4ba9dfdaab55ca0d5306a307a 100644 GIT binary patch delta 683 zcmV;c0#yCk0k;K^7=H)`0000V^Z#K000Lx5L_t(I%RQ6LZX8t*Mo(4U+dnfsv7Hbc z33-ErSnvj6#{!8L;GNkcmIxA%u^}_oc&58=-#->TaqVhxtMr{ySAH<+cQ-q}8hTnM zq+EH`cv3B#Vn%_&T7x&dDFEk~7*oa#-toHg9AktCZ`y`Kh<_YHWQ+-K!YL;1wmtil znMz?}#p%{ydKSb~y3P z)xh1*;Z+d@Lx0FrmQ--6@LyOsERoI`0!%4$yXkn{wRk=Asx_WMB-KhRg_sMe)-}RP z*Wq=g>qMx)hv$jw*0F0m|4s`VXDqo8QlWQB=M0sC{M2f_ZalTFs+O`!Yg9SKv~Drz zR2jU3i&hiCtKfdTdy61A5k#O?Ub23!m9-3BJ|FfQs!X{cw2j~%G8UQMc8^H*Fvj?H(^QzCqiS&!x(Vy-@RF3 zTtYit9e+Qb1HU{T`1X3BGh^4R|DYCDm9_Bo)du(1Y2u5nCFX^Efwpx?l>Cwt zAl1rswK03-koWmrjOO-%qQ00008000000002e RQ;a(+MP!L003}FL_t&t9Rd3CU4q6G9Bs{R$~0F+~7MJ4P!DK+~;hU5zgDBaQ}-*nhQ40LFvItoQe9_V={? z4y7&oZo}E=1uH+Jbv1>lDD04wB0AG0n`TaC1_&X!S^mMv@CjNOI@h36L0OHsDKg((qlKdLd#ZdwNRdr*N9XqlAu-C*`xYM^MrHKA!L8qtVnjcx zE|^y5RM~{g6n_YzNGT9v;ClHxf6jj4>B%e3#xF3^B7{OpNsN&`?9oC9@$)_HT^NxZV84s-5HGp+q4ht7gXS=JJ!)Ig8CT0K0C< zy1AosHGlecb;-b1ly=0rUGUHRSNgC&@F_#CD|`xAog<{=^6m{%8FE!%b&me_>1(vI zD0yI3$`E5@vHh1fS3mLm^lPjxsIm!KSyBqP*yDZA#q=fmcKwcVd4>-?F$Dk$Tj63) zj2*kI{eS<<`P4UpdC_g!bv}>0Piz(js>}=hRRXuw!aJRj}XiJI_rR>9VVM<)+ z5YNuPOT&ChnT=7On(thVmIqxvI)=qDA@m3YM&}gvi2LmoR%QGLeU)C+nh>C`0000E lWmrjOO-%qQ00008000000002eQs1=#_R7=Hu<0002(-QrRJ000AXLP=Bz2ngHZPv8Im02NS7R7Ec)KRPi? zKr~xOL}p1mZD34)V@-$s^tpHd003}FL_t&t9Rd3CU4q6G9Bs{R$~0F+~7MJ4P!DK+~;hU5zgDBaQ}-*nhQ40LFvItoQe9_V={? z4y7&oZo}E=1uH+Jbv1>lDD04wB0AG0n`TaC1_&X!S^mMv@CjNOI@h36L0OHsDKg((qlKdLd#ZdwNRdr*N9XqlAu-C*`xYM^MrHKA!L8qtVnjcx zE|^y5RM~{g6n_YzNGT9v;ClHxf6jj4>B%e3#xF3^B7{OpNsN&`?9oC9@$)_HT^NxZV84s-5HGp+q4ht7gXS=JJ!)Ig8CT0K0C< zy1AosHGlecb;-b1ly=0rUGUHRSNgC&@F_#CD|`xAog<{=^6m{%8FE!%b&me_>1(vI zD0yI3$`E5@vHh1fS3mLm^lPjxsIm!KSyBqP*yDZA#q=fmcKwcVd4>-?F$Dk$Tj63) zj2*kI{eS<<`P4UpdC_g!bv}>0Piz(js>}=hRRXuw!aJRj}XiJI_rR>9VVM<)+ z5YNuPOT&ChnT=7On(thVmIqxvI)=qDA@m3YM&}gvi2LmoR%QGLeU)C+nh>C`0000E lWmrjOO-%qQ00008000000002eQR`z(TcVN<9d$Y?Vq;& zRq@+2UuC0R=-1htMf~|f*NZ}Hg_S(BoKE?ib&=6!F!><+aZ*bWU%05>z1qC8CtFoK pH|))kelnp*ShLq#=n=yOrGGyUNLBJX=74Nv@O1TaS?83{1OOolQw#tA From ccf063999e9d9b3ad110677e6855b55873b620f3 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 19 May 2023 14:56:22 +0100 Subject: [PATCH 129/155] New crimson fungus texture --- textures/mcl_crimson_crimson_fungus.png | Bin 304 -> 401 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/textures/mcl_crimson_crimson_fungus.png b/textures/mcl_crimson_crimson_fungus.png index 7a547ca79b156b06e66abbdfc057a301fdfa7d75..2c3d3b599f34afd61c66bfce26b3c6fcc9a1d290 100644 GIT binary patch delta 385 zcmV-{0e=3l0+9od8Gi-<001BJ|6u?C0X|7YK~y-))snqS!vGM)Ut*fn7+V^(rS+>? z0-XdEhc>e~Iq9Gv6pEvBXa5gD+;nhr5F7=yE;@*!ZY@PkF-9x2X`AF6Tr4)BX7je= z-TkPgm6lk@dC$AdTON>n>pe|ORd06Nyl2c!#q*-ieSZHLl zR7Eq&&Ekj-OPixptCQ0aBda6EmPd`Pj+$5=H?^v-ObY&=!tg(p;eQ&#|D~D#mu3E6 zp4GoH+ZpH(#*!evU2j9m;vGqcD`Gq5l;*R1F`41F6le{Dr>mdKI;Vst0CcBdasU7T From 62ca6faab1f92eaf9c64ad5cca8216aada3d2fec Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 19 May 2023 14:58:31 +0100 Subject: [PATCH 130/155] Updated credits for new assets --- CREDITS.md | 1 + mods/HUD/mcl_credits/people.lua | 1 + mods/ITEMS/mcl_crimson/README.md | 10 ++++++++++ mods/ITEMS/mcl_crimson/mod.conf | 2 +- 4 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 mods/ITEMS/mcl_crimson/README.md diff --git a/CREDITS.md b/CREDITS.md index 7296e52a7..3584cae1e 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -174,6 +174,7 @@ * cora * Faerraven / Michieal * Nicu +* Exhale ## Translations * Wuzzy diff --git a/mods/HUD/mcl_credits/people.lua b/mods/HUD/mcl_credits/people.lua index 26b80927d..660cde11e 100644 --- a/mods/HUD/mcl_credits/people.lua +++ b/mods/HUD/mcl_credits/people.lua @@ -175,6 +175,7 @@ return { "cora", "Faerraven / Michieal", "Nicu", + "Exhale", }}, {S("Translations"), 0x00FF60, { "Wuzzy", diff --git a/mods/ITEMS/mcl_crimson/README.md b/mods/ITEMS/mcl_crimson/README.md new file mode 100644 index 000000000..45c475c11 --- /dev/null +++ b/mods/ITEMS/mcl_crimson/README.md @@ -0,0 +1,10 @@ +# Mineclone Crimson originally by debiankaios. Modified by MCL2 dev team + +Textures are from PixelPerfection other than: + +Exhale (License - CC-BY-SA 4.0 https://creativecommons.org/licenses/by-sa/4.0/): + +mcl_crimson_warped_hyphae_wood.png +mcl_crimson_warped_hyphae_wood_2nd.png +mcl_crimson_crimson_hyphae_wood.png +mcl_crimson_crimson_fungus.png \ No newline at end of file diff --git a/mods/ITEMS/mcl_crimson/mod.conf b/mods/ITEMS/mcl_crimson/mod.conf index 89c60cd1e..b4303cd48 100644 --- a/mods/ITEMS/mcl_crimson/mod.conf +++ b/mods/ITEMS/mcl_crimson/mod.conf @@ -1,3 +1,3 @@ name = mcl_crimson -author = debiankaios +author = debiankaios, Exhale depends = mcl_core, mcl_stairs, mobs_mc, mcl_util, mcl_dye, mcl_flowerpots From 9c8b942e2696d06be350501deb5f7c9786546161 Mon Sep 17 00:00:00 2001 From: uqers Date: Thu, 18 May 2023 02:21:03 +0000 Subject: [PATCH 131/155] Fix a typo in Acquire Hardware achievement Fixes a minor typo with an achievement name --- mods/HUD/mcl_achievements/init.lua | 2 +- mods/HUD/mcl_achievements/locale/mcl_achievements.de.tr | 2 +- mods/HUD/mcl_achievements/locale/mcl_achievements.es.tr | 2 +- mods/HUD/mcl_achievements/locale/template.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mods/HUD/mcl_achievements/init.lua b/mods/HUD/mcl_achievements/init.lua index 518a2cfbd..016536303 100644 --- a/mods/HUD/mcl_achievements/init.lua +++ b/mods/HUD/mcl_achievements/init.lua @@ -198,7 +198,7 @@ awards.register_achievement("mcl:skysTheLimit", { -- Smelting achivements: These are awarded when picking up an item from a furnace -- output. They are given in mcl_furnaces. awards.register_achievement("mcl:acquireIron", { - title = S("Aquire Hardware"), + title = S("Acquire Hardware"), description = S("Take an iron ingot from a furnace's output slot.\nHint: To smelt an iron ingot, put a fuel (like coal) and iron ore into a furnace."), icon = "default_steel_ingot.png", type = "Advancement", diff --git a/mods/HUD/mcl_achievements/locale/mcl_achievements.de.tr b/mods/HUD/mcl_achievements/locale/mcl_achievements.de.tr index 885bf1d7e..1c6f668e5 100644 --- a/mods/HUD/mcl_achievements/locale/mcl_achievements.de.tr +++ b/mods/HUD/mcl_achievements/locale/mcl_achievements.de.tr @@ -1,5 +1,5 @@ # textdomain:mcl_achievements -Aquire Hardware=Schmied +Acquire Hardware=Schmied Bake Bread=Brot backen Benchmarking=Tischler Cow Tipper=Kuhschubser diff --git a/mods/HUD/mcl_achievements/locale/mcl_achievements.es.tr b/mods/HUD/mcl_achievements/locale/mcl_achievements.es.tr index c398bb14c..6f00d76b7 100644 --- a/mods/HUD/mcl_achievements/locale/mcl_achievements.es.tr +++ b/mods/HUD/mcl_achievements/locale/mcl_achievements.es.tr @@ -1,5 +1,5 @@ # textdomain:mcl_achievements -Aquire Hardware=Obteniendo un lingote +Acquire Hardware=Obteniendo un lingote Bake Bread=Horneando pan Benchmarking=Crea tu mesa de trabajo Cow Tipper=Consiguiendo cuero diff --git a/mods/HUD/mcl_achievements/locale/template.txt b/mods/HUD/mcl_achievements/locale/template.txt index 522b7fd09..d865b1668 100644 --- a/mods/HUD/mcl_achievements/locale/template.txt +++ b/mods/HUD/mcl_achievements/locale/template.txt @@ -1,5 +1,5 @@ # textdomain:mcl_achievements -Aquire Hardware= +Acquire Hardware= Bake Bread= Benchmarking= Cow Tipper= From a5a035d9bbadc0956a4512421924e1f3ba568390 Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Fri, 12 May 2023 17:07:25 -0600 Subject: [PATCH 132/155] Make sure dying sign text respects protection --- mods/ITEMS/mcl_signs/mod.conf | 2 +- mods/ITEMS/mcl_signs/signs_api.lua | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_signs/mod.conf b/mods/ITEMS/mcl_signs/mod.conf index ada0ae58a..e2fe9d40a 100644 --- a/mods/ITEMS/mcl_signs/mod.conf +++ b/mods/ITEMS/mcl_signs/mod.conf @@ -1,4 +1,4 @@ name = mcl_signs description = New and Improved signs - can be colored and made to glow. -depends = mcl_core, mcl_sounds, mcl_dye, mcl_colors +depends = mcl_core, mcl_sounds, mcl_dye, mcl_colors, mcl_util optional_depends = doc diff --git a/mods/ITEMS/mcl_signs/signs_api.lua b/mods/ITEMS/mcl_signs/signs_api.lua index 3d8bd3e49..7ada6a646 100644 --- a/mods/ITEMS/mcl_signs/signs_api.lua +++ b/mods/ITEMS/mcl_signs/signs_api.lua @@ -307,7 +307,9 @@ mcl_signs.wall_standard = { local item = clicker:get_wielded_item() local iname = item:get_name() - if node then + local protected = mcl_util.check_position_protection(pos, clicker) + + if node and not protected then if DEBUG then minetest.log("verbose", "[mcl_signs] Wall_Sign Right Click event on valid node.") end @@ -414,7 +416,9 @@ mcl_signs.standing_standard = { local item = clicker:get_wielded_item() local iname = item:get_name() - if node then + local protected = mcl_util.check_position_protection(pos, clicker) + + if node and not protected then -- handle glow from glow_ink_sac *first* if DEBUG then minetest.log("verbose", "[mcl_signs] Standing_Sign Right Click event on valid node.") From 10a3d06360773b2c592efd78acdbd5f66dc5e6a6 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Thu, 18 May 2023 12:52:27 +0100 Subject: [PATCH 133/155] Fix global variable references and exit mob_step if missing pos --- mods/ENTITIES/mcl_mobs/effects.lua | 4 ++-- mods/ENTITIES/mcl_mobs/physics.lua | 2 +- mods/ITEMS/mcl_barrels/init.lua | 4 ++-- mods/MAPGEN/mcl_mapgen_core/init.lua | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/effects.lua b/mods/ENTITIES/mcl_mobs/effects.lua index 1a1578834..7953e6a47 100644 --- a/mods/ENTITIES/mcl_mobs/effects.lua +++ b/mods/ENTITIES/mcl_mobs/effects.lua @@ -308,7 +308,7 @@ local function dir_to_pitch(dir) return -math.atan2(-dir.y, xz) end -local function who_are_you_looking_at (self) +local function who_are_you_looking_at (self, dtime) local pos = self.object:get_pos() local stop_look_at_player_chance = math.random(833/self.curiosity) @@ -361,7 +361,7 @@ function mob_class:check_head_swivel(dtime) if not self.head_swivel or type(self.head_swivel) ~= "string" then return end - who_are_you_looking_at (self) + who_are_you_looking_at (self, dtime) local final_rotation = vector.zero() local oldp,oldr = self.object:get_bone_position(self.head_swivel) diff --git a/mods/ENTITIES/mcl_mobs/physics.lua b/mods/ENTITIES/mcl_mobs/physics.lua index 090b921c7..1fbe1e24d 100644 --- a/mods/ENTITIES/mcl_mobs/physics.lua +++ b/mods/ENTITIES/mcl_mobs/physics.lua @@ -823,7 +823,7 @@ end function mob_class:step_damage (dtime, pos) if not self.fire_resistant then mcl_burning.tick(self.object, dtime, self) - if not self.object:get_pos() then return end -- mcl_burning.tick may remove object immediately + if not self.object:get_pos() then return true end -- mcl_burning.tick may remove object immediately if self:check_for_death("fire", {type = "fire"}) then return true diff --git a/mods/ITEMS/mcl_barrels/init.lua b/mods/ITEMS/mcl_barrels/init.lua index 3cde964d7..714a80f09 100644 --- a/mods/ITEMS/mcl_barrels/init.lua +++ b/mods/ITEMS/mcl_barrels/init.lua @@ -63,7 +63,7 @@ local function barrel_open(pos, node, clicker) minetest.swap_node(pos, { name = "mcl_barrels:barrel_open", param2 = node.param2 }) open_barrels[playername] = pos - minetest.sound_play({name="mcl_barrels_default_barrel_open", pos=node_pos, gain=0.5, max_hear_distance=16}, true) + minetest.sound_play({name="mcl_barrels_default_barrel_open", pos=pos, gain=0.5, max_hear_distance=16}, true) end local function close_forms(pos) @@ -81,7 +81,7 @@ local function update_after_close(pos) if not node then return end if node.name == "mcl_barrels:barrel_open" then minetest.swap_node(pos, {name = "mcl_barrels:barrel_closed", param2 = node.param2}) - minetest.sound_play({name="mcl_barrels_default_barrel_close", pos=node_pos, gain=0.5, max_hear_distance=16}, true) + minetest.sound_play({name="mcl_barrels_default_barrel_close", pos=pos, gain=0.5, max_hear_distance=16}, true) end end diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index e6420f91d..c3eef6a26 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -335,7 +335,7 @@ local function set_water_palette(minp,maxp,data2,area,biomemap,nodes) return lvm_used end -local function set_seagrass_param2(minp,maxp,data2,area,biomemap,nodes) +local function set_seagrass_param2(minp,maxp,data2,area,nodes) local aream = VoxelArea:new({MinEdge={x=minp.x, y=0, z=minp.z}, MaxEdge={x=maxp.x, y=0, z=maxp.z}}) local nodes = minetest.find_nodes_in_area(minp, maxp, nodes) for n=1, #nodes do @@ -440,7 +440,7 @@ local function block_fixes_seagrass(vm, data, data2, emin, emax, area, minp, max local pr = PseudoRandom(blockseed) if minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min then -- Set param2 of seagrass to 3. - lvm_used = set_seagrass_param2(minp,maxp,data2,area,biomemap,{"group:seagrass"}) + lvm_used = set_seagrass_param2(minp, maxp, data2, area, {"group:seagrass"}) end return lvm_used end From 5ed92a2695ebb9d9dd713fa3cedd47de0678cd58 Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Thu, 27 Apr 2023 17:01:32 -0600 Subject: [PATCH 134/155] Make pigs mountable without carrot on a stick, but require the carrot on a stick to actually control the pig --- mods/ENTITIES/mobs_mc/pig.lua | 47 +++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/pig.lua b/mods/ENTITIES/mobs_mc/pig.lua index 7f2ebc88d..9084c5d4d 100644 --- a/mods/ENTITIES/mobs_mc/pig.lua +++ b/mods/ENTITIES/mobs_mc/pig.lua @@ -82,7 +82,7 @@ mcl_mobs.register_mob("mobs_mc:pig", { end -- if driver present allow control of horse - if self.driver then + if self.driver and self.driver:get_wielded_item():get_name() == "mcl_mobitems:carrot_on_a_stick" then mcl_mobs.drive(self, "walk", "stand", false, dtime) @@ -149,18 +149,14 @@ mcl_mobs.register_mob("mobs_mc:pig", { return end - -- Mount or detach player - local name = clicker:get_player_name() - if self.driver and clicker == self.driver then - -- Detach if already attached - mcl_mobs.detach(clicker, {x=1, y=0, z=0}) - return - - elseif not self.driver and self.saddle == "yes" and wielditem:get_name() == "mcl_mobitems:carrot_on_a_stick" then - -- Ride pig if it has a saddle and player uses a carrot on a stick - - mcl_mobs.attach(self, clicker) - + -- Should make pig go faster when right clicked with carrot on a stick. + -- FIXME: needs work on the going faster part. + --[[if self.driver and clicker == self.driver and self.driver:get_wielded_item():get_name() == "mcl_mobitems:carrot_on_a_stick" then + if not self.v3 then + self.v3 = 0 + self.max_speed_forward = 100 + self.accel = 10 + end if not minetest.is_creative_enabled(clicker:get_player_name()) then local inv = self.driver:get_inventory() @@ -177,6 +173,19 @@ mcl_mobs.register_mob("mobs_mc:pig", { end inv:set_stack("main",self.driver:get_wield_index(), wielditem) end + end]] + + -- Mount or detach player + local name = clicker:get_player_name() + if self.driver and clicker == self.driver then -- and self.driver:get_wielded_item():get_name() ~= "mcl_mobitems:carrot_on_a_stick" then -- Note: This is for when the ability to make the pig go faster is implemented + -- Detach if already attached + mcl_mobs.detach(clicker, {x=1, y=0, z=0}) + return + + elseif not self.driver and self.saddle == "yes" then + -- Ride pig if it has a saddle + + mcl_mobs.attach(self, clicker) return -- Capture pig @@ -195,6 +204,18 @@ mcl_mobs.register_mob("mobs_mc:pig", { return false end end, + + after_activate = function(self, staticdata, def, dtime) + if self.saddle == "yes" then -- Make saddle load upon rejoin + self.base_texture = { + "mobs_mc_pig.png", -- base + "mobs_mc_pig_saddle.png", -- saddle + } + self.object:set_properties({ + textures = self.base_texture + }) + end + end, }) mcl_mobs:spawn_specific( From 1e63f3931ab549f7dffa761a7ce17b1b33e3610b Mon Sep 17 00:00:00 2001 From: MrRar Date: Wed, 26 Apr 2023 22:01:37 -0500 Subject: [PATCH 135/155] Skins update --- mods/ITEMS/mcl_armor/player.lua | 4 +- mods/PLAYER/mcl_meshhand/mod.conf | 2 +- mods/PLAYER/mcl_player/init.lua | 30 +- mods/PLAYER/mcl_player/models/character.b3d | Bin 145382 -> 0 bytes mods/PLAYER/mcl_player/models/character.blend | Bin 812908 -> 0 bytes mods/PLAYER/mcl_skins/README.md | 45 ++- mods/PLAYER/mcl_skins/edit_skin.lua | 302 ++++++++++-------- mods/PLAYER/mcl_skins/list.json | 9 +- mods/PLAYER/mcl_skins/media_credits.txt | 10 +- mods/PLAYER/mcl_skins/mesh_hand.lua | 11 +- .../mcl_skins/meta/mcl_skins_character.txt | 3 - .../mcl_skins/meta/mcl_skins_character_1.txt | 3 - mods/PLAYER/mcl_skins/simple_skins.lua | 13 +- mods/PLAYER/mcl_skins/textures/README.txt | 3 + textures/mcl_skins_bottom_1.png | Bin 226 -> 375 bytes textures/mcl_skins_bottom_1_mask.png | Bin 117 -> 142 bytes textures/mcl_skins_bottom_4.png | Bin 680 -> 749 bytes textures/mcl_skins_bottom_4_mask.png | Bin 117 -> 142 bytes textures/mcl_skins_bottom_5.png | Bin 0 -> 891 bytes textures/mcl_skins_bottom_5_mask.png | Bin 0 -> 183 bytes .../mcl_skins_character_1.png | Bin textures/mcl_skins_eye_6.png | Bin 135 -> 141 bytes textures/mcl_skins_hair_6.png | Bin 501 -> 535 bytes textures/mcl_skins_hair_6_mask.png | Bin 134 -> 168 bytes textures/mcl_skins_icons.png | Bin 0 -> 554 bytes textures/mcl_skins_mouth_3.png | Bin 124 -> 110 bytes textures/mcl_skins_top_5.png | Bin 2032 -> 1345 bytes textures/mcl_skins_top_5_mask.png | Bin 122 -> 151 bytes textures/player.png | Bin 419 -> 0 bytes textures/player_back.png | Bin 307 -> 0 bytes 30 files changed, 233 insertions(+), 202 deletions(-) delete mode 100644 mods/PLAYER/mcl_player/models/character.b3d delete mode 100644 mods/PLAYER/mcl_player/models/character.blend delete mode 100644 mods/PLAYER/mcl_skins/meta/mcl_skins_character.txt delete mode 100644 mods/PLAYER/mcl_skins/meta/mcl_skins_character_1.txt create mode 100644 mods/PLAYER/mcl_skins/textures/README.txt create mode 100644 textures/mcl_skins_bottom_5.png create mode 100644 textures/mcl_skins_bottom_5_mask.png rename {mods/PLAYER/mcl_skins/textures => textures}/mcl_skins_character_1.png (100%) create mode 100644 textures/mcl_skins_icons.png delete mode 100644 textures/player.png delete mode 100644 textures/player_back.png diff --git a/mods/ITEMS/mcl_armor/player.lua b/mods/ITEMS/mcl_armor/player.lua index 99e23efdd..281839379 100644 --- a/mods/ITEMS/mcl_armor/player.lua +++ b/mods/ITEMS/mcl_armor/player.lua @@ -158,8 +158,10 @@ minetest.register_on_player_inventory_action(function(player, action, inventory, end) minetest.register_on_joinplayer(function(player) - mcl_player.player_set_model(player, "mcl_armor_character.b3d") player:get_inventory():set_size("armor", 5) + if not minetest.global_exists("mcl_skins") then + mcl_player.player_set_model(player, "mcl_armor_character.b3d") + end minetest.after(1, function() if player:is_player() then diff --git a/mods/PLAYER/mcl_meshhand/mod.conf b/mods/PLAYER/mcl_meshhand/mod.conf index a95edb858..687932514 100644 --- a/mods/PLAYER/mcl_meshhand/mod.conf +++ b/mods/PLAYER/mcl_meshhand/mod.conf @@ -2,4 +2,4 @@ name = mcl_meshhand author = jordan4ibanez description = Applies the player skin texture to the hand. depends = mcl_tools, mcl_player -optional_depends = mcl_skins +optional_depends = mcl_skins, mcl_custom_skins diff --git a/mods/PLAYER/mcl_player/init.lua b/mods/PLAYER/mcl_player/init.lua index 6c521be72..d7ae6e81f 100644 --- a/mods/PLAYER/mcl_player/init.lua +++ b/mods/PLAYER/mcl_player/init.lua @@ -28,28 +28,6 @@ function mcl_player.player_register_model(name, def) models[name] = def end --- Default player appearance -mcl_player.player_register_model("character.b3d", { - animation_speed = 30, - textures = {"character.png", }, - animations = { - -- Standard animations. - stand = {x= 0, y= 79}, - lay = {x=162, y=166}, - walk = {x=168, y=187}, - mine = {x=189, y=198}, - walk_mine = {x=200, y=219}, - sit = {x= 81, y=160}, - sneak_stand = {x=222, y=302}, - sneak_mine = {x=346, y=366}, - sneak_walk = {x=304, y=323}, - sneak_walk_mine = {x=325, y=344}, - run_walk = {x=440, y=460}, - run_walk_mine = {x=461, y=481}, - sit_mount = {x=484, y=484}, - }, -}) - -- Player stats and animations local player_model = {} local player_textures = {} @@ -112,6 +90,7 @@ function mcl_player.player_set_model(player, model_name) if player_model[name] == model_name then return end + player_model[name] = model_name player:set_properties({ mesh = model_name, visual = "mesh", @@ -120,13 +99,7 @@ function mcl_player.player_set_model(player, model_name) }) update_player_textures(player) mcl_player.player_set_animation(player, "stand") - else - player:set_properties({ - textures = { "player.png", "player_back.png", }, - visual = "upright_sprite", - }) end - player_model[name] = model_name end function mcl_player.player_set_visibility(player, visible) @@ -180,7 +153,6 @@ minetest.register_on_joinplayer(function(player) local name = player:get_player_name() mcl_player.player_attached[name] = false player_visible[name] = true - mcl_player.player_set_model(player, "character.b3d") player_textures[name] = {"character.png", "blank.png", "blank.png"} --player:set_local_animation({x=0, y=79}, {x=168, y=187}, {x=189, y=198}, {x=200, y=219}, 30) player:set_fov(86.1) -- see >>> diff --git a/mods/PLAYER/mcl_player/models/character.b3d b/mods/PLAYER/mcl_player/models/character.b3d deleted file mode 100644 index f5482f4c748cb49b8867cd9908fbc5fde5c67cd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 145382 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 z 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
  • Nmaj(L0$D7aR%VMpIfe#x|G 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 z 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
    `eZnKfvuXZI;; zQLPu|TAJyJ-gD6Hiwn6$$lS`S(EGf|>VVO^TcXo}?+8c| zJ==XTYPdp48IYUsgUw#y=xGpJbuFwZZCCwlSoZFEXlvBWC)!E&>`KzEts`4<;rT#8 z3)yJWz8(i{XHLXm7+a5a(!P3!FqUUWeagoBv{BS+7m;qsPGL-0IWgefdGy}VJk6Z` z>uD6RJgi5RpYo|GN4P%e!EVN<-8=XEl)G+epYo`}0+DkkpYqZV(LUv&XW5_f@YL_8 zysYPMpYo9n&`-JRhZ{Vu_>^B2{qcxT`B+;&pYrj}PCw;mjUc7_Sgl--lGa63#g?pI z$Ft#O&BNtx7b}!5VP>nb97}UojpZQAxmXT*jUUUUs{HVAESKs$X^W92o@2|`8Dcy2 zZr43_Ah`p?5~;2~#o*Zhs-wTTU>z~wFnK5I8VlW&iJ9!+*5Z(&HSOx%sZx(NCAh7! zCFk95>Y&@%lol5Di1+c#6Aenr;vv;R*l}hQd)Cw7c^58;_Rrx>%tiSndVbnk5BAmN{cah3#ZsnAvyR2}5hJgQzM_d*4_c!Ht%-d_>*-FktbRwPhJFRw z>sVSA^g0}Eg8O0VinYp>Y?7;_s#CL8^%AuzmZ}_4ik%t#Mt$@-8fyn6>VS>6H?d6S zo~xV6M}E#a+C7rOotp&@)m>a6zeyLyleW;_{!N; z778`2_o6Uo~W-IzIv_u-yA3X{1mjaH^yVzrk4y7kto^Iw-3*V?M5F^om* z8A@1dRug-l-}~Gu%C$;!uT#|764@n|o)FtXpF)aqqT|#4JtLS7ApTLqMU;ykt-a1o zipz;TdLUB*IW5G7J%NhLnc^>t=-acr?ek@^*pbO{L-q*e(1NE0ekRT@Nq!vlm!vmsb`(6Tv4%K91&-VzDEu=~?xBCZdnLKaS)hk=PNiMQMEx{4+6p?Ei5TAIp^S z9KDa~CT!u!{$ZQw68lJmlc0R?#=5;nCFUck8tppwk_Eh+($J@rzo3zA(w-b&{7-Fu zq_Qf{2HSPkQaNHY&M(RFjPUbGEWw&q-UnfPk$pne|DTtw*{&<6Rb<%yf{+|jY$G2r z@xFxmd42MPnPL`!9$(PNWVV$Y5$O2^nVco9N%t2;xItMzDDVX-&%ECIv7xBMf83BF znlWF|XGl2x%Tdzi?OIsFik=!3Z{DIfZ~QawD$7|{dS4m2ImjbheS@){3hPOzEGex^ zJ$uyNG<)ws4gHAOy32Z>HF+m0(KB8G$)heNqVmQ9$DgC-!qGN~th(pb1`2=)6Z0Q_ zM>*PRO=U)o1*>AXPEyl+x~jCQtlF!#DrL0A{~EH1Ra+J56Q&~l{kS@>!pv)l6C+>Mp4eU& zQxV!v6*D4@#LCaMRE;uD8Ix3Y+hDGz;l9?c(9l+e7iwmw%E% z!LH&HOELaRiV3PtsZ)j@Hta?SGLoZW{0-o*9lJ=`RUhQ0sU!R!1!5me>ZhqN+g9|2 z7-7aK@^wm;#q4VI!B0V1)zt?J?(#1ZMiGM_5|L`D8DfaG!RoyIJQ5NnQYF^%`Hil| zQkbNg@?T^m*2L0slUn&fw$(hVVn*U-F|vQVln|HCNjFkGZu6k$%ONF#)_ z+*9`qKP@wjyi&r1U5kX&qV+F8D%@Y}Jerm5hOfAJBJ8@Mt zthD$UU8U>{+z3m){rX@Nsk#{_#Se==%{=0RK5AtWA;MH2S{G>dN5Qid-b%Y<-{iFpN z!Dz@rT%&B$jMw%s?Hi!;E4iknn$#~P^xAk$-n&wFle8AfgZPS}IWhl78Lx2-)}cr7 zcQB=5m%N~%DdF-!F6eOqR(^q_geZqXmr{qY5AQi%Yi9bGnsW;ns zo3ihz9K)>|Dvgn;g`a)Di;#T&w zq%l95rRRm=dV~;@Z1{NoN&NX4JNh8KmRgsVbIquVY+G9WYdE5UY1_q&N&GF#aCHr{ zF4udJkUCmR|Ck0_u^pklm-3%}LYrHv;|TG@By}F5`)gfnefTfsB4y;K|HdbkO;uf6 zc0+3KJlbiiMhK;zpR$owDQ$f)VHLi9wlJg=wNMP5WswQPuPpy{Z!x+O7p>J-kuJs~ z%iH`;@GYJ?Dz=$BU12Nz)!e=WPXTJByMxsoPv+9oXaG@3lLy z#YI-`5_aVePH?Gs{B_{wz|Dc11Go6vEdYBUxFJX-KyO0yCB!e04jGJ39BiUB9wq4n z>8A#Nf4e^B%+J_Kn zv8VHdOV4!%2qNVQ4D4ZO%g9wGEn`=i(U%3XLN?sPNoRI+q`*F}LIrHYf<5|~-J&P><{m4@;UrT>_!6qJVekPyEz zq&@*CFvvw&m0p#j1j|E(81fadSAxn=1rkD4>cXlcyQ+r0I@Exg#8-<_aOga^Rc&(#fprvlHPu<1THY3$^3Yx)uGy zrMltP9eSX*Ct-TQ*If4o8Jqi3FARLDAN1F0&8pk*0OA@5gWww&3`3Cl7KT#u($0s$ zaMCvdMtag2f!in;O-=$pa%9j##?V5>(n7}3LdN4i0VaazoutE>YBH_HkGh_Mo5VjA zzJu?H^M@$?d32xr5%*~@9cI8xT3V8*GPTNUmJZ`kv+L~s37}r1JC+YtM`*Apd{Un^i z{a4E9H#iMv=&`@!eiqKbdALBF7wN@+(2J$NT!PDR1+G%B*XY^Tk-Gsm;TGJ6J8&27 zfwZ6d@BsdVhqyf={9||mPvIH-h2L{{0WaYd{0-8tU&9-C3;)17_!r*82T+DX8DN49 z?BD~w-~d1H2Pe2700O}cK@bdaATGp%_>ce+LLx{ENgydCgXE9`QW_ET+t}$&g?oL< zxeg;7DPrbrVpl3PjUf$$LR!M5GfFYaT4Psw!eoFjWG8#dCnNSu2II3K<;)n(bymnm z_;ACevLl}Za^jW?azh^c^5T{c^21kL7cfeyf<|do$S6VUlW|21fTuhiZX*OVZZLknyLCYHi5aD&vvlQ`)>zZSY^k-9zrt zZIN#W56~m`nAq)9R$C6$9{&!|k+Lqy9mk))ow$xJ8wu-BopI|zI=iAjoV!wysPgpQ z!|bXXGXHJI-Er#yJ)swT4ZWcc^o4%V9|pic7=->5+!?>24ANsiOx)h_ZZQ5s;9D4q z|1cO1BVZ)5qhK`lG5C*#aWEbx;64%eNif-vGBec_>{3=!@&69Khabq_kC@Y7I?RBX zFbihu@|7~LKxs;uD>VoCxe#eoWW3I<<{9G7c#Ql4SV$aF?~5=O!xG$cBwZigMP6Lz6X z^1hoiNjdC+MTWOMNjq|=y}0dz{cr#d!cT;e`Z$D+!`P3&Q8)%aQ!c+4ZgrfpIAK)Q z^Re8dFRz}Z$b2c4I%!m822vH*s*L;9SlfHsj^r)ooRo2j>tBiIH#iMv;CDC+N%1>} zdEThboXOj--Rc7IUxYslspCrO66umMx=cJ*;40T?;TmD3Z^*bT{o^{^fSaW67URop zBRz9ihq{B?UAPBfgsY6M`n`CbNFiu54ya zG_Whg^(%BpIlM4x;TB!aJ|_1Gvo<41bQwC#I?B%sRsP@vmnmhLQ3aS%p5Ah^(kkT{ zh<-PEf*_c9<8U1pu8?*aH{#(Q9}?i^%|k-$iI7bUNtjS3g=CN%UXZVzgiAq~l#mKS zAT^|cP)G~uAU)ybev<(+3^IbO3^JK@Rc3T$F)ORAkPX5iyID)+Kqe>TqI_~g9`tk| zzPycwe^naFKv}b%DrYuP<;|w50{#`D5~N3utT(KCQ_QmFK%3cIRWVzrs%A@7&1|Kr zn;dR8+o+mmTUE#$LKg(X?@YUM0YbSyNGrkpB^G>r=DgvZH_g&W7^d?vj;Ltjpxq< zv!_RekLi7o?@f93)#;y#+;^UQO1VX_+L1JW zuig8z4(v~i{Rz`o{b2S{Kbrm2H2kFgrS6*%Hk>k>PQAJLKZABO9k-b<3ueO{mlQz|ua+}Zf0&@WRC4U2{3z_Lj9z^dT?A-T=Cm|~>oG_(N4~}6ULMs`9>kzF& z=J0Z#TZC?rjR09UEH;OzCG@AI=C{lRFUNYwh+II-bJ|ko(w6cm;pMYj^{1 z3De5>A*$Z~A+C406<|Is>G)Uc{4uIcNZWglo3wSA-=;_A1A3HAbjrNft_&M@Zmw-M zX{XcZCz7w}%!$ODq3pJq%EvZK`P$eGu({dEoTL1acY=$s0hocdxyo&eWPLAT+NmI0 zI~5FZATGp%__lc}0rCkU5n&QT65>n>tJqaYW|Lio=(Upno%#Z~_@y`m`ARMwo4x3Bmv@KKqTK965i?rs3JjmyTe30K0PXs$5-acBA zl*#&1+L!dX>(s?p=qmuSpHmRC5EQ0Nia=4@N>85cs+iVis^a*U!0!g7X7v@yf$NeG zNnMx1EDhat`N+5=eb!#L=E~^(0-rklBu|ex&1{3!XTM6|o zI)`E(hTCvR!48>M#|W-RB0ma7V;=)!A&_{#q@$IwBTC0b%3>V)#}m(lFUHLtB>t0h znq`dN=@}>ZmA5GQMCWM|<&oisl6w3pe)&e6ILM%@SI zA{Y5tIjOq?YM$+NTE!XH@IaL>mo*eXM%Hj>s&@RYo7W(?Xw-b8T%i=$s@_0?#m9W1;cVcUA{N@=urA(~0CS#1O zuWuTs*%S1xgG|=GCTm~jFP^eGjd=!sC%&_A4tUC`E};7&Y5D^$!DYAtSK*p1ow{zz zpse+)tdnG}c1GQxo^Bhz)0Sn|_jkrdYtAY4cGGqi_p{i}{>QzVp6lKsK9NhoD90=c z+d1Sy)oo86?~tYxl-pg~dGCzwxd z7u7S{AL=jUo+J0dc1gV?&#&Mt<=Q!_d=jX?ZI{(++-1+;4f1c{A9zQ&f04~kn%-l6 z0A&wVhF!{m-D~?5WwT%9d9OUnxu$&V*OjmRhH`N2XLl=qaDod0AQ0RT#M5Y*e+ApE zeU&&|%Njqf-C94!!<7A$_?QVm_Ei#M%05ma%*2ocl0q^_4l?gafteCgp)bU4jTfmg z(?BSsg>;af1ziRR!=4c`L1xGTS#i$>;n-(UBiXU%Kxa^zmX>a`mB zZMK{24_No&>bTc{*QCEDW-X`JM&}s%XpN|+<9^w8-yAL6*ZzVq3c|u0Jp~wuQ ztcTlYv;R69x!GDy?oA_*8wsOeG>n05+CZo^;5Lq^vn7;5QK_!DM8oV74;c zYO4LQ`i{81w?9F@?B~goo7w6I;`X!MqOV!{ezZSR)9in#>4cNLlNsoqNnU4hJsWcl z%!Npp2lHV8EQCd{82Kg0F2!8N^>SFj^-9vRkvLXiuEuW-tR*e$xLyzKNYe&nH^L^^ zjQj_IVEYDM|U`11=okHZP%Phy^eU$Os&c^b}O{~gZ4Il`WY3vdw~1!yaOV84Xl zWw-)YaleLn9d77x%TzaUy9Kv#yMz2)%zJPj`vZ`*_n%xpgh!aM`d&2cocm{vL zb9ezS@qdN+xBVqg8ol=&8CPZeww@Kd#{Uhxg@523{0r~l11KN4$C3xyzv06^2-v_5 zKH!VL+$$VDGWJG4a|l;5F35g6&*yxsHg?>2#oXMb{C!-?>BAWe2!KFvLl6W*9Ec0? z2q#aZh;$b@VG;|*im8&dLyHX{9~lFE!+2<4jvGb?0+aL5ih(38_A zvC8H1R^|5jhcV$FLjB_jt5hCj@@l=s7!$1W%g1$o_zGSa@3^lLFLs%;7Q~b?mc5=r z*b74u(pVIV5m#}pOF#sa1Szu%s+cO}^RFuH^Inzl`9Qh9Q)ThXM||-ZTVFsqoll4s!APHLr&JjRzKwo2G=#9Ce(u3TAxY3VZBAV>f%-p zxBAckWS^oTZjGQZG=ZkL7lZ=P3}oHdocLQnOZ;1b%<)=t-3HqF#8d5j+^RjY9k`Zf zLmi2$6Lf|y$alr;hJSbH0X?A?ZeK%h!t_C=FK+#?7oflO$9(_{$gu_^jdJfy$b4s-kIj(tAJYjl1K9|kh8sK$pJMZ6 z6c^KO%p@(d@Z%n3%qHGB^tZWON8&F1Vjkvv(!W5*Wi!_B1U-nS=?l>*_p3#ii(v^Y zMYbEyikcfu~%O+Lbr z-QyELSx7ztJ*J!4n_OG{=LJ{WeB?xcl~yZ#+#}Gj5ANx_1QVZ9`w4RZ4uY(sWDJ)* zfS-_)=Qf9YLe*iPIFw9~aYW~Z^ChH9?#oA!Ifngb!iMvl_ZRBmxKFTg!beUZSp8je z#(thwTAlQXXCx=Qto2W!L!N8Oy5U#sziHh(C&YdR`|p@%G0$P1hYQ#*V*Wv#m*6s7 zfvdP(!|yug4Y&!n;5OXxiErHXNnpt7x_ijV7;_)<0sIN==!*}LdjyZ+2|R^o@Rv_Q z9ZvGm0G{La0$#!^_?z&r;Vfyg<6j@Q@t(SUZ3{3yP+!WI`wN)9 zOc%lKYtkmT{b2V62l(OdkGm7Q3j!bz+z;1m0e%gk5j5ty2{eUf&>UJoOK1hHk!b^MvA2Wv*gIf$gig>I zxwSEz9GgiUwMX^+8B;LxrdJ+TmkMe5?0O({A|d)C5^$j(?L*Mu4{sFlkeG?ngd}R$PXX%m{(~+6s zdqK^FS-#%;b5S+hH?1+pSLRG^HP`pHiu6rq%=1mG=2MRgsGo(t>5WX(!6Nd!7?!|N zSO&{s1+0Wsu-dnpT7&#r-weh&-!NmnZ$@K-Zzf|Sew$!3Y=Nz?4Yq@vSJ{EN6Lx`| z>Do;`_P}1)LD}rX+z&61JwV$$2tOfv2=g!;!G08u`KCrf#z^*4xc&u>!wF}Cvl<2TDXnZ= zyVc*M>ovRq+4J<4W&LP&&LVn_l>9WowdHj+8AFfRxs=T;_p3+VwG1l!dHhH zp7?8G?x0Q9!mO>+AZ@FlQ3v~0@>SPS$f!qN>pKb?KAcEwfV;>wghtTVQPhyr^G&cf zg=Wwk{VgzCLM!yPhBnX^+Ch8#JK!g0b!BZXW!(|C1@xg#xSwT>Qiki!(1q)+j$%gq z&*o9)$;@#{M|VeYqlbfY*U-yR!uZ;e$>_SIb<{5IYb*V+v^I}*6OJNydWxcT+`4zCzQSJ+Ev#hZS-Bwzq zPF!lWqdX&Bc}k}|W3AkiD;R5Z+&r(qT<56xg*uS7n_R7jwz`d2>#Gfflev6a23k2^ zCG{|v`rhae{bkf9{5O;CEtqniaw}=t2J-I2cH9ynyTeh**s1GOPRCXzeU(X{oSCxD zW_7|YbBp+#oOOS;jyO+(K6!s&7dm%i-vfJzdmrp~RAsIBxv_w?39<*_Cr33SBmR$KL&EvU(P1TyzghOe?jgz<#2*H4}W5`=aFK~Yeui$TZ4R7Er`~&acU*z9orr_i=%X9SsI}gkhHz(Zc z8QJ7yv|nw*26pfPUvPjQ_=6K%5CDPTh9C%rI1m@&L3~KySI0<*?nHjvtNl!s1bb4D zb1unnOO9RkeNteigj5g$sUZ!7LRv@%=^+DzK}N^~nL+wR7QgzuL2BhCD{k4~0XL~| zOeweQn3C5Vm^mRAQDn}LM^Bbb)YWPgZj__8bTvz3{9XZG=t{Q0$M^VXbo+kEwqF7 z&;dF^C+G}apeuBP?$85zLNE9ldP5)R3;m!!41j?!2)=>AFa*AZp)d@F!w47&qhK_Q zfw3?S#=``d2$NtkOo6HJ9efWzz>hEuro#-F3A11}%z?QO3G-k+EP#cu2o}Q|d)$V(9d^J@*af>`5A20~upbV=Jck$X5?;aIehrxGFm7Nk4^`-|a_@e`+YpI?7OBU! zsXq0LH}to+@DIF$f8jlR0Oenw4a53|2{y2U5BP!u{J5t-Q&r%*3J8lI-I=G(bN$4g#Im}WD;?mn6xFqOu?HS^1NN-C;c6nP%-p-QyUPi)ag3OQwq(5cF%m(3*9dbZU$OX9}59CE(KGKyR zzJdZ!5O;Z!R|vB({zWj0LNO=~B_IO1lK7Q^(ohD|XYH?kgx~c^UG!oQ8N(!Z^- z%D**ht@iY1nftocYRY;ItcAbXYg$X&lJ>O@UF!+E0XD)W*bG}>D{O=9umjQ>9gLm+ znT%cjF16dgqp`vD6vA&f0Ike<$Mre(l&} zmp&2B+f24tY3s^5R^D#vihMWYpnrGPHH^K)eTZ^73`gK79D|?X7xW#+Kf;rr6I`E! zQ~3Q#I)5X-r~P{nPY?9=&|}3J|DHw=Z$r^Cxb8(fjLpcO1=+tihj|_@z(xH2z`O*P z8BenF_S6;s-i#l;3Ex}mlXJ{hkqhUIDj(nutKF}W4*3`<_6rf^=D1n zAG!X>buz4S>15obd~W%-H*WjKRTU^7*|)iaj=Ny(Q84ZkelyonzW1?5@YdEr|AEE> z^7*H(Teo_M`N+R7^*>0DM~~6>#J>Y;kq*S!fjDLD5m!CM{aKW5=9t)@!wZl8qnO8F z6TF01@VEar#OGG8;SIcnf8ZTRy#M+SHr~@lKKKtYI2f)BCudxogGkG_tTos>cd};$ zKH!UgdO3mN%%}XELk)jq<=qXZlV`6^rwYJ75KcOVQGUZn`!Lcj@3;=f*{yA zLhrH4dNK~zvUZH?97*1JM$2`4=P2rhGciui!$2b3toAorKTAnW9L*e}mw7Acl4pEL zF_S@Z{8GR<-e?O1W<8|AdS^W)dQw4%bGVTjnZ(Y~#s}L7BMotf5@%Ycywf_?CEwQZy)AnM88I`F?#z${vXZWB5RQ9x$l)Ag zTDouQ4 z@Gt93!`_iwmD6#%Re9ViP-YdO5>!T}3RHz^P~90%)o@NQ_K^OXT$glCG-^2~QO}&0 zB~1^hqdJs9UFT%RAD#i=Rv#KbL*yGlW9Jlo&u)TSQ)mXwp#^^TDDRe-t(;S7Cl1w` zG=%dOqO_AX$h5^z_6D{h*UtI9mT8ZB2j>rZ4c5_FS#?6DGjzedD|7={n|4Q+w68G6 zE_t6St?{F7i#_nK!B%~)oRGWrm% zuX6@E6S_sLC6ce!#5#6MoF6h;JirWM&0s z^&iR9BS%ZvTN*_=M#C6*OWBVlP4ae;oNpS3+jy7&6JZie206>zk~~boJ{7*x`Q?35 z>_3pUA7L6yhZ!&vX2EQj1M+U-T+EA@k%XNG^9h^MzR+0Ul=D)HXuFF@_o7dvn|*lV z|I|AQ3(+BIv))n2L))^-Y!PwE_`TRE`#+1RC)z74apoZfB?j2xMPsmCm<|)5Yvf(HG^p&l=|v^e-XpOGtaDD#-~{n?A9+ zlC!O-$4A}=-kN*azJog!DY;-O&GV>NKvk&yh zSg_2BTKwDIlu$$8!#xb1{pup8vrjyy-+gMBOIwHI?A?1uwz z5PpI~a2SrjQ8)%a!!K|gPJp~;E#E~rNnEGkSJL?#oOUiZ;^=(J`{!D~&(!lX2n_ z=4H}w1@kH-7YmLY71fDwMt7p!2Mp52SW|iwHdpS2L%rU?O8>GPB zj_Cuw-~d1H2Pe4T|F1sRQFrU8JC_P@tv3Q)>kPMR4ReXBoY&?&tSi(A#x0J^non}p zM8#!8P0}v!lg1;y_%63f;G!-dk;|nLLlT#qw`G6IwSn>z_l=C{VzO6-uH=vcdrC-! zJw)qgt;cm52!*t+O~fK^gl|Fz-@K7H(2<__6Y*t%46ZAj-Lm>s7-rytlk>&-jU1#gr%reD z{(WVtEEoFo8k;G@t;D;P^lv5on~dBpnLo(cV@aQNKic5GjWKH*GTV?5f2*AHxVAHw z+m8Eo+~o|j_g;W*^ydRP%PDOnKk4{N>*h=W_JXb*?0N1W><+?)szS)Vr_UEAt=H*m zGA_z9lOo7k=UwD&d3jzSV~kaHMJdN(E^pXfMv&ISJ3u!>_zYPX)}1AkUL4;a?f5KvmZs#!#!AWLzxf+Dl&* z9n4*zI>>uQvfugM+!y61P@mAI_Duc4l0&MEiV+Q`v))zfZAW4L+qcFYr>HJ_->xLF_l)_L)tJ@Hv})&TttiKh|7E=x(De6>K*7OLJb z-pMyH8Y9;PnnE*Z4lST1w1U>eBY8{D*A8qk%J8yrf;Q_dQ%NWDIi3EKtcAs0;xkoS z!necT9y&lr=medi3v>mk_in`19eO}d=mlRxZ|DPkp&#^z0j^V?xFrtmVZ<{~r}I}m z50(8Re~@!8E*M0ZZ?wP6L4NxmWKRDNGV+xMZ$7Pi>kvi{=~vQr!uf)Ow1cud8|jU^ zyw@i0vJECJ@?KkIka8VD{@a=Ir3YC{uotY`2j6PKeHis5X9I@2&KWlC@9hicX%8ar zy%t$1f04gH`|-Z#;(fp6B5AousxC4XM2{gO2xEO8hUfK^&q%_T`M zQ_wvXzJu@K2l$aN;nY@Akgr-8FwG@n6MH%MC8B0CMCFC~CShi}t{AiMJHx)tY~r57 zJ!mfOkuVSU`S5}i?4jHiP|gcomyJcPtHxs2C1Z)}nvqA(O0E&tHDjrc>$*puHBMV& zri=@wO34^DiFUUP-SSLT;#fpkT;V>yoV>0;Uw-a4>v{f}0evfRTSc0zbXo7%%Dc9! zaa#jxVI8a|T^mT}M)Ylh&A4rWt=PB0cJj2t6;JJiU9cOsJ+K${5pF*maNRHt66Pm3 zCV+4Z?^dGEV6a&=tyJZ{WKDMM>qy|3@x$GL&OFdjttU#AQ#|3AsM zL)~yaq%Vm+iJv*B>k;9setXOHn0{q_he*ygFCs6uN#`Ai;FPAUe~Z(0WgRDLy1VGU zr}Oa?zbD3h*AwFb{0R^7djyYN&lsy@9c@=nxPA)H;4jx-TA%od-oaqKdoAgD{slkz zY6$O45$_AvOV&#!`*ha+Q4aR|UQ*_-pds!XXqSHzm%JbT8uJbABWVF|2|JMS{~yZo zo$D3rRnGe3{~qozUdj2^57=uG{=Q6zco^EwlrOX}59Lsi8DP0b@Yb3QHyduUXA+mM zp2+<(uRbg8Js);GOab@Vapt7oFjJ;RS8Vfj&R3LfQf`-4H~$V2Bg&FKwH1P1xf>d`N(QLP!LOAxXe{%FX*dm=ClCJ$EvRMkVEs zd;?C-{v;!;lw)$j3`9N!W=fFpY%nsd4EgGeOQi~MsgMAZRgHBXU!I9bSv>^NC1>1I zqc;sKl^ySO39UO$l+F_9jDS1Lg-Qm*jgl*cTZw>p zQP-upE)x(x>RR5T2b8c-8zaa|kgKwYQ@^#hXW z`l*b*1_8-QH%|$%H^fZOiF4^o;@1dd{?Ho-nWy&gO-b3v8GUO`kPpAc$TSH^g$~}Y zK)1ZF-Yg(Q*ZFmAPp#A0EFg_Gn+JqyKbgPe8l7#>C0|hv z=c`20mfB%orN2z%?O)b-+CCtR{PXSvYgu{LC+`w%&2~e*=SI2z(1eLBk){ z|0;R*DD@)umhW-<0e^XyYM`^U`jIhXTEKfHZEt!&QEevDUviRjV(2D)lXTcjW?Jks z2s;yI!EBfVb0HGu!F=+*02YFr(O-nyVpziUQdma(%Sqb`SP5B4+baB5V_ySnv9E*m zuz_o-qm9@%!Di}V3v7jL0hQGD03V~Ao*QH|ci`3~pt#xzyKvtf5NYfQkY`jS)!u;2 z=04)xkB$RykaWD~J~D&7Z@Fvt)8)grV2JM!{)aJ-z)?s+Z#;(E&+rS#`wsH%gS_)_ zoa+>t6_ABoWT9JRp-)+PV2(o0tv!n8 z=y*Yz!ueVkCuG%2!o8x*EdQ*g>~Z~#%f7#4;`29;9@^1Ef>>oe{<~EGLaMKLDpnO;v*?8b%2OsbSM__iw7TIs3 zeBd5;%TDA%#umT89J>FD-%;AKe;{isxMJqSo$sav<}#BYSBmq|0k~J?YhyAm2n^(X zJ_rhwFOTv32zwlei%dL-4+*q$m-k@Ep5 z0xg{>1HUrmyLe&Ti&G&R2qBOf(m*Jrg>;Y}GC&w)M7Q2|LQe?utn|DwIW=ldUC_*o z-YkLg-l@EQYROim24$Z_*2-B4C*N+&hMARdGaNHJI&+{qC-z*Bo3zS%3VE>Sg?zA? zIZJ-bub==FghC*D?Xm|i_pHKP7Xj~k)J3rugW^yE{SiCZ9kWP7yFbb+-uZG_0q*czt$9$$x1KFBT3u;3hs0;O=J~V)aAobD+voSP* zrVvbhG(&fD^iHH#wZPsI_YKTHTVb|_HqaL24X<{X@-Dacz3%p0cOXnh!pphEPF#0} zF3=UaL3ii@J)swT4ZWcc^o4%V9|pic7=*rWU~ph*H3YuJZ72*2EUtzJ-sYWpw;F*t zGB8w)g3*Dp$0zUH-&A8Lqp_qVAM=fIm<<_g#$!$(d`;3l5pxnuM(>nB-YW@Q&ir~g zJ%2g(j{@d*f%(nv>0fW0-uJc(nLh*;GJgzot7$MjaJrfi*ig-cS;Rd%u&_A?Q=TCd zqkYOVgp|aSlCqdfJdxyMJEPG&OlikbpYyRVfQ7IKWM6$T>0Sa$No!tiXv?rKhZV3A zxAal(jI-_y%x$hF+!|OLSj1cxDBoKuYOW`~4X}}X-8Po1O@T9c4%3A7x%Hm-X8g8* zj4RnmqqK>wAm2&chPfSfz)si&yI~LPg+<8k!`u%CU@_O;chC=V{SzF5!*B$S!ZG+6 zej)ub791zN@@(=1=1KB(3Vwy(;53|p-{CBrBTNb<{hD*ETwg%XMHo-Ke_&pM%Wws* z2F_w%y@|Sp{W{!$n{W$m!yUM*8C!@y#CT=uRZg(rDugjgQdrSf@+A*65v^iIm)PxX+_UzCR@Q{U_*qD!Ps0e4#0Vk=3rA;r3Tx zNu)|L?v~W|nCH03GuRiT%i0$##eJg`{-yADtLNNzo=5qW*7uZ`gn5PTzcF89vd>_? z2`s~SU50RF2v>spUWECU^k$|{|3mn9S_k{f+|m9e%zOOgd!ZlDVa-wK0&e-vi98E0 zO`6N1hxMuZ5`Qn@d5QkvR;HWpgSxFT-R>@nTsfV$tVr-}Uo#nSI!~v4Jz;!2vc7I_ zJ{e~ycS+B4_PykL7Hos?-4Xc~3F}tm{DEyBZKT`CUlaUmXZG9QhPnLy%3MXt7B2!hz`DtD3VbC@*xl60e?rJgOv~7sOyt)T5~q}E>afKybAeDn5~Q&F?36QylG?&j=#vtd&QP)P1Zdz^Yh=lTk_cm zBkM~mOfBXc5+;RP^Z#+ud%R~LBue3(zNA~Hxa?v^^-;xJCj&Kj@M!urI56HffO}<}N|378vjYry$)px9RWIfZC zZxV&`W!NvZJ$c@0m7}D!;TL72+o|Yn}0#*0&Ecx*O9@8 z*WSL-M338T$#Xbgtj+IkYJLR;+|4N0#%4k4s}M-rm2XHC#$H61RTKJO^C%g4u2z(~ zEC!NJYuza_El8QAM|2c-i(5;bwt~o(fC$*B+nCiaiV#N*ACYV2(Qmaw>8oE8Pf6rU zMWvxN>9_P--&<$CsN-luSz7KBbiFc%BwSf^OW(8NkUUE~ZOtGpYsKT0FNeJKU1`q2 z60QQ*GUg3NU+nPhs0)e9n@-MgkxtoXt*Fz|-jk32>Wf)U9T->LsuJ;3hALo{VJ4%h zyQ68H>Fi`yb9XYUyWOe={iG(;g4$3Ax4KZz-NCGn*#H_sBWUdIY&L`g~bF)egD#?rvrWcNe3hyS>qgI6FfZ z@b39`#oi67F-{L>4%r=h59kTK$d8;m{Th33cXzXoyNB7=-P7zxdg_6kBkYekz%A#@ z+-e~44|4Z1QRJwBcbf%6w=N7wOOTZkde7I&Pk-|uXI8&QZ!VqA z4(1Pp`_Wy(nC6zVu->`N0LGpH=pTUof$UYuT3hqh6%!dW;p~z)XtMv2xVWy4ubr+)FYR|)U+_IjMIbV77Y#@AF#?M9W5jyV0 z+Rb~9kZ>a@TX}xP9yWPiLL5t}8+mVg6=7vuS>_&v%qWUvlrH~7gjtTv3XpapyVT3s7bnH9W3pxIW@eVIOHC@0W%Hh3#F`O&a{#EHo3={N%@L1Z_%LBtv0*mIi_1} zq26VCMAku4ms^qj?{m%A&og-rM_Ftq4(q*Bp2vC8UBDP;?j(<#&7{1?6W4f8TvDE_ zok(LMzK-nz`AW9@PLq`HF2XNE=WdYtlC*EYz6bWYC(;HdB0o{<+DE)+IFBsnKK5fj zK-hyioL64fUX!R(`AYR9!g%$OKQj}1tJZh%ej?w8+~du|l*Dl6NBxSQ z<$l`zJ#E4(Yn^{OgS@OkWk3HEa=*KO(D9ta{Vd3L!{vL#Rr$)drOSF&bh2AE(A z;!G26cI-YN>-*&3i`{{rANYe4To8bJAWS6RZmxr{2ZQXr#^E|H!~TB3Atgkx50HulP)Lxhjah>rE9>(#$c180i%h7xMhbNkTXbr2Zm=_xaWpEkQegdmmhPYF@dwNQqJ-nXZc2Q3H23z1&A*d z?W`d7LQoirfQ%DGF*k5_pcrOxD1mHV(i(xiBs#yv+=Xm>$oCRl2gub#+4$6a^Gp&GG5h{UoPTU#`@*266Jil2-T=LF+<)B&g z3poQHeTKdY>8Tnto0?!T00wupBaYOn1Yft8v94NBPSWB{gFK(LlXm$%DV|3W-)ZXk zj6Ux_*WAPG-^U(l)(CQ`n#5I${7GMtv-5K9vUZT1wV%WMt-2xKbJ_xRkf{sxpnlLi zvq4a#(GVJ;yD@2N0!{H-#~1bA+vb_gaBm*8fPO4)JY(Xzy|Iu!>ryR|ZADqjzH@8b z+dx~~+TkYO#cI!W2j~c$pfhwKPT9NeioF|jhaNgUN&9@p{rQXq^YvIL<9tv2dqv5~ zdfKkOM!q+C`rzIdT5v7-?uXf*>noJ^0Ma4fN*jnd2={Mr9~@+zjkrf!91^sMJn_5< zKlzQZgsg%CfHx{VanCo0;x|mUrA5SL#hZ{BmOTF%&UNpgCCob|EORO18A%+YFh|1} z7z^WIJWRl^Klkv7*k4imlL$WEfW}tO1sj=jEO} zTQU=Ahf5d-mIf^|mmzDVb%mB$9<-9R$x6bkYr?nj3MCPRmkr6L~)DUTkj0 zeG59b!nU9l=Jue~=8m8>W;nmNz#Ff`Dc_ftUtPGZcIxrW`z=Y{%Oeh%7y7V&B4fjD z(y#~i!anrL*y&{a+mHPKc+W5&3@V|1BJ3gD4ug!TN8l(NgP-9SI1VS^B%Fd@;Ws!9 zXW(}@i=G19@TDZrVLuNSf_5=B?Nk@Z+aILm5_r!{UJlw#If2ohkD65FUZG2P5r5 z>TR8_x5v247$x(eC+K^Mj%V;!(0bjco@4i+jVI(6E_|5byg)|w4qoE_DrlV-T4eT$9%m(vqkleZD*Dy9AC#O%?Z$xGYb3jSYDt-}z*&+U$ z@s~Q~oh!=j-=K}=d-QxD9rBD;-uXXbzTm5Bk;9b4WlD1Tnb|Yhv1AjllOIgcaxa=AG2Xh}` zkHCrPf&d5vHv}Qu%GgRg_f$Hbs|5##syOHno!)rjA`=hf3}$@7B!GmF2oggQND9dy zIi!G;kP1Q|HKc)1NDJv8J!F6|$OxGrGh~6RkPX6v`E9%4ZItyk%6glptgSYfgEZzO zP4b>D^zohS#g$Y=gLl*F#4gXg#b4@g593fw zH|7lJE>8U6YOhCL!ZL?|h~Rx6$y@Fszn{5qY+aULOq~bFtH{WC(wKS=>U>!4-t>9n z6x~13C%obQ>mO79Ay4|4=aAk~!7<}F{88F18PR{_KWP^?uMYNv&{Zb*s3*Lo^Do-j zGwNkKr60~Oz5KTvqy2yOrR02kJI-HtM>C z9_P+Ql|@DJD|-m#S<8g;t2S1AMnjy+QYns~-JUc~m0}RfxMf)PS17*P_zxU29vRd2Uc2oefBnjIRwb z8-b*^F?icZ6YNcKZ^pRP99lq2Xa%jI4SsE*9dhltmgo20-&{=3Sla=&j?f7@Ll@|Z ze79hEK3s)BAf4eTiG< zX+v1&)#kn|^GEADT(`}oJd^4de8=n`9AX6V6*mQPj~qZcL~bDFAovD-d5ut30M_>q z2jgaak3Ym1!gzhtd6#m&OSh#Er2!6nvD}?Vdiu`?ZBxPiMPnq=|>-HQz^1Wq#vp)E( z8cjL8*eRS=a-n4n$lAql9z|%MfO}}4)BQjc!b*{T_1_~WhU!eS8g?dbWDUvFj==v z=HH}S#;U1Ye;51&eNPDcgs?82AF}Tl+zq$K<`2OS%^!mwo6|6-2S4Qujkk`ibjy5X z20CU^x3ge2$Zs)ueAe&(2okz6RF9I#>@IU?a#k12|yZLV#;6}ac+kl5Wz3$%KKl^*LI?N7wm>TuowS*gxwDZ;2`PziL@LFE>*c?36y>G G@BaYZUAfKx diff --git a/mods/PLAYER/mcl_skins/README.md b/mods/PLAYER/mcl_skins/README.md index d05bf9a2e..e639ea93f 100644 --- a/mods/PLAYER/mcl_skins/README.md +++ b/mods/PLAYER/mcl_skins/README.md @@ -15,6 +15,7 @@ See image_credits.txt for image licensing. Register a skin item. `item` is a table with item properties listed below. ### Item properties + `type` Set the item type. Valid values are: "base", "footwear", "eye", "mouth", "bottom", "top", "hair", "headwear" @@ -34,15 +35,32 @@ If set to true the item will be default for female character. `steve` If set to true the item will be default for male character. +`rank` +This property is used to change the application order of the skin item when applied to a player. +The default ranks for each item type are: -### `mcl_skins.show_formspec(player, active_tab, page_num)` +base: 10 + +footwear: 20 + +eye: 30 + +mouth: 40 + +bottom: 50 + +top: 60 + +hair: 70 + +headwear: 80 + +Lower ranks are applied to the player first and can thus be covered by higher rank items. + + +### `mcl_skins.show_formspec(player)` Show the skin configuration screen. `player` is a player ObjectRef. -`active_tab` is the tab that will be displayed. This parameter is optional. -Can be one of: "arm", "base", "footwear", "eye", "mouth", "bottom", "top", "hair", "headwear" - -`page_num` The page number to display of there are multiple pages of items. -This parameter is optional. Must be a number. If it is not a valid page number the closest page number will be shown. ### `mcl_skins.get_skin_list()` This function is used by mods that want a list of skins to register nodes that use the player skin as a texture. @@ -50,7 +68,9 @@ Returns an array of tables containing information about each skin. Each table contains the following properties: `id`: A string representing the node ID. A node can be registered using this node ID. + `texture`: A texture string that can be used in the node defintion. + `slim_arms`: A boolean value. If true, this texture is used with the "female" player mesh. Otherwise the regular mesh is to be used. ### `mcl_skins.get_node_id_by_player(player)` @@ -71,10 +91,19 @@ These colors are separate from `mcl_skins.color` because some mods register two ### `mcl_skins.color` A table of ColorSpec integers that the player can select to color colorable skin items. -### `mcl_skins.players` +### `mcl_skins.player_skins` A table mapped by player ObjectRef containing tables holding the player's selected skin items and colors. Only stores skin information for logged in users. -### mcl_skins.compile_skin(skin) +### `mcl_skins.compile_skin(skin)` `skin` is a table with skin item properties. Returns an image string. + +### `mcl_skins.register_simple_skin(skin)` +`skin` is a table with the following properties: + +`texture` +The texture of the skin. + +`slim_arms` +A boolean value. If set to true, the slim armed player mesh will be used with this skin. diff --git a/mods/PLAYER/mcl_skins/edit_skin.lua b/mods/PLAYER/mcl_skins/edit_skin.lua index f4f6fe90f..6973a1b6e 100644 --- a/mods/PLAYER/mcl_skins/edit_skin.lua +++ b/mods/PLAYER/mcl_skins/edit_skin.lua @@ -3,8 +3,9 @@ local color_to_string = minetest.colorspec_to_colorstring mcl_skins = { simple_skins = {}, + texture_to_simple_skin = {}, item_names = {"base", "footwear", "eye", "mouth", "bottom", "top", "hair", "headwear"}, - tab_names = {"template", "base", "headwear", "hair", "eye", "mouth", "top", "arm", "bottom", "footwear"}, + tab_names = {"skin", "template", "base", "headwear", "hair", "eye", "mouth", "top", "arm", "bottom", "footwear"}, tab_descriptions = { template = S("Templates"), arm = S("Arm size"), @@ -50,7 +51,9 @@ mcl_skins = { headwear = {}, masks = {}, preview_rotations = {}, - players = {} + ranks = {}, + player_skins = {}, + player_formspecs = {}, } function mcl_skins.register_item(item) @@ -66,19 +69,28 @@ function mcl_skins.register_item(item) table.insert(mcl_skins[item.type], texture) mcl_skins.masks[texture] = item.mask - if item.preview_rotation then - mcl_skins.preview_rotations[texture] = item.preview_rotation + mcl_skins.preview_rotations[texture] = item.preview_rotation + mcl_skins.ranks[texture] = item.rank +end + +function mcl_skins.register_simple_skin(skin) + if skin.index then + mcl_skins.simple_skins[skin.index] = skin + else + table.insert(mcl_skins.simple_skins, skin) end + mcl_skins.texture_to_simple_skin[skin.texture] = skin end function mcl_skins.save(player) - local skin = mcl_skins.players[player] + local skin = mcl_skins.player_skins[player] if not skin then return end - + local meta = player:get_meta() meta:set_string("mcl_skins:skin", minetest.serialize(skin)) - - meta:set_string("mcl_skins:skin_id", tostring(skin.simple_skins_id or "")) + + -- Clear out the old way of storing the simple skin ID + meta:set_string("mcl_skins:skin_id", "") end minetest.register_chatcommand("skin", { @@ -88,25 +100,35 @@ minetest.register_chatcommand("skin", { }) function mcl_skins.compile_skin(skin) + if not skin then return "blank.png" end + if skin.simple_skins_id then - return mcl_skins.simple_skins[skin.simple_skins_id].texture + return skin.simple_skins_id end - local output = "" - for i, item in pairs(mcl_skins.item_names) do + local ranks = {} + local layers = {} + for i, item in ipairs(mcl_skins.item_names) do local texture = skin[item] + local layer = "" + local rank = mcl_skins.ranks[texture] or i * 10 if texture and texture ~= "blank.png" then - if skin[item .. "_color"] and mcl_skins.masks[texture] then - if #output > 0 then output = output .. "^" end local color = color_to_string(skin[item .. "_color"]) - output = output .. - "(" .. mcl_skins.masks[texture] .. "^[colorize:" .. color .. ":alpha)" + layer = "(" .. mcl_skins.masks[texture] .. "^[colorize:" .. color .. ":alpha)" end - if #output > 0 then output = output .. "^" end - output = output .. texture + if #layer > 0 then layer = layer .. "^" end + layer = layer .. texture + layers[rank] = layer + table.insert(ranks, rank) end end + table.sort(ranks) + local output = "" + for i, rank in ipairs(ranks) do + if #output > 0 then output = output .. "^" end + output = output .. layers[rank] + end return output end @@ -115,13 +137,13 @@ function mcl_skins.update_player_skin(player) return end - local skin = mcl_skins.players[player] + local skin = mcl_skins.player_skins[player] mcl_player.player_set_skin(player, mcl_skins.compile_skin(skin)) local slim_arms if skin.simple_skins_id then - slim_arms = mcl_skins.simple_skins[skin.simple_skins_id].slim_arms + slim_arms = mcl_skins.texture_to_simple_skin[skin.simple_skins_id].slim_arms else slim_arms = skin.slim_arms end @@ -131,33 +153,35 @@ end -- Load player skin on join minetest.register_on_joinplayer(function(player) - local function table_get_random(t) - return t[math.random(#t)] - end local skin = player:get_meta():get_string("mcl_skins:skin") if skin then skin = minetest.deserialize(skin) end if skin then - -- If the player moves a slider and then quickly exits the game, form_send_job gets saved. - -- This should never have been put in with the skin data in the first place. - skin.form_send_job = nil + if not mcl_skins.texture_to_simple_skin[skin.simple_skins_id] then + skin.simple_skins_id = nil + end - mcl_skins.players[player] = skin + mcl_skins.player_skins[player] = skin else if math.random() > 0.5 then skin = table.copy(mcl_skins.steve) else skin = table.copy(mcl_skins.alex) end - mcl_skins.players[player] = skin + mcl_skins.player_skins[player] = skin end - - mcl_skins.players[player].simple_skins_id = nil + + mcl_skins.player_formspecs[player] = { + active_tab = "skin", + page_num = 1 + } + if #mcl_skins.simple_skins > 0 then local skin_id = tonumber(player:get_meta():get_string("mcl_skins:skin_id")) if skin_id and mcl_skins.simple_skins[skin_id] then - mcl_skins.players[player].simple_skins_id = skin_id + local texture = mcl_skins.simple_skins[skin_id].texture + mcl_skins.player_skins[player].simple_skins_id = texture end end mcl_skins.save(player) @@ -165,33 +189,17 @@ minetest.register_on_joinplayer(function(player) end) minetest.register_on_leaveplayer(function(player) - mcl_skins.players[player] = nil + mcl_skins.player_skins[player] = nil + mcl_skins.player_formspecs[player] = nil end) -function mcl_skins.show_formspec(player, active_tab, page_num) - local skin = mcl_skins.players[player] - local default = #mcl_skins.simple_skins > 0 and "skin" or "template" - active_tab = active_tab or default - page_num = page_num or 1 +function mcl_skins.show_formspec(player) + local formspec_data = mcl_skins.player_formspecs[player] + local skin = mcl_skins.player_skins[player] + local active_tab = formspec_data.active_tab + local page_num = formspec_data.page_num - local page_count - if page_num < 1 then page_num = 1 end - if mcl_skins[active_tab] then - page_count = math.ceil(#mcl_skins[active_tab] / 16) - if page_num > page_count then - page_num = page_count - end - elseif active_tab == "skin" then - page_count = math.ceil((#mcl_skins.simple_skins + 2) / 8) - if page_num > page_count then - page_num = page_count - end - else - page_num = 1 - page_count = 1 - end - - local formspec = "formspec_version[3]size[13.2,11]" + local formspec = "formspec_version[3]size[14.2,11]" for i, tab in pairs(mcl_skins.tab_names) do if tab == active_tab then @@ -201,21 +209,23 @@ function mcl_skins.show_formspec(player, active_tab, page_num) local y = 0.3 + (i - 1) * 0.8 formspec = formspec .. - "button[0.3," .. y .. ";3,0.8;" .. tab .. ";" .. mcl_skins.tab_descriptions[tab] .. "]" + "style[" .. tab .. ";content_offset=16,0]" .. + "button[0.3," .. y .. ";4,0.8;" .. tab .. ";" .. mcl_skins.tab_descriptions[tab] .. "]" .. + "image[0.4," .. y + 0.1 .. ";0.6,0.6;mcl_skins_icons.png^[verticalframe:11:" .. i - 1 .. "]" if skin.simple_skins_id then break end end local slim_arms if skin.simple_skins_id then - slim_arms = mcl_skins.simple_skins[skin.simple_skins_id].slim_arms + slim_arms = mcl_skins.texture_to_simple_skin[skin.simple_skins_id].slim_arms else slim_arms = skin.slim_arms end local mesh = slim_arms and "mcl_armor_character_female.b3d" or "mcl_armor_character.b3d" formspec = formspec .. - "model[10,0.3;3,7;player_mesh;" .. mesh .. ";" .. + "model[11,0.3;3,7;player_mesh;" .. mesh .. ";" .. mcl_skins.compile_skin(skin) .. ",blank.png,blank.png;0,180;false;true;0,0]" @@ -224,23 +234,24 @@ function mcl_skins.show_formspec(player, active_tab, page_num) local page_end = math.min(page_start + 8 - 1, #mcl_skins.simple_skins) formspec = formspec .. "style_type[button;bgcolor=#00000000]" - + local skin = table.copy(skin) - local skin_id = skin.simple_skins_id or -1 + local simple_skins_id = skin.simple_skins_id skin.simple_skins_id = nil - - local skins = table.copy(mcl_skins.simple_skins) - skins[-1] = { + mcl_skins.simple_skins[-1] = { slim_arms = skin.slim_arms, texture = mcl_skins.compile_skin(skin), } + simple_skins_id = simple_skins_id or + mcl_skins.simple_skins[-1].texture for i = page_start, page_end do - local skin = skins[i] + local skin = mcl_skins.simple_skins[i] local j = i - page_start - 1 - local mesh = skin.slim_arms and "mcl_armor_character_female.b3d" or "mcl_armor_character.b3d" + local mesh = skin.slim_arms and "mcl_armor_character_female.b3d" or + "mcl_armor_character.b3d" - local x = 3.5 + (j + 1) % 4 * 1.6 + local x = 4.5 + (j + 1) % 4 * 1.6 local y = 0.3 + math.floor((j + 1) / 4) * 3.1 formspec = formspec .. @@ -248,7 +259,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num) skin.texture .. ",blank.png,blank.png;0,180;false;true;0,0]" - if skin_id == i then + if simple_skins_id == skin.texture then formspec = formspec .. "style[" .. i .. ";bgcolor=;bgimg=mcl_skins_select_overlay.png;" .. @@ -259,21 +270,21 @@ function mcl_skins.show_formspec(player, active_tab, page_num) end if page_start == -1 then - formspec = formspec .. "image[3.85,1;0.8,0.8;mcl_skins_button.png]" + formspec = formspec .. "image[4.85,1;0.8,0.8;mcl_skins_button.png]" end elseif active_tab == "template" then formspec = formspec .. - "model[4,2;2,3;player_mesh;mcl_armor_character.b3d;" .. + "model[5,2;2,3;player_mesh;mcl_armor_character.b3d;" .. mcl_skins.compile_skin(mcl_skins.steve) .. ",blank.png,blank.png;0,180;false;true;0,0]" .. - "button[4,5.2;2,0.8;steve;" .. S("Select") .. "]" .. + "button[5,5.2;2,0.8;steve;" .. S("Select") .. "]" .. - "model[6.5,2;2,3;player_mesh;mcl_armor_character_female.b3d;" .. + "model[7.5,2;2,3;player_mesh;mcl_armor_character_female.b3d;" .. mcl_skins.compile_skin(mcl_skins.alex) .. ",blank.png,blank.png;0,180;false;true;0,0]" .. - "button[6.5,5.2;2,0.8;alex;" .. S("Select") .. "]" + "button[7.5,5.2;2,0.8;alex;" .. S("Select") .. "]" elseif mcl_skins[active_tab] then formspec = formspec .. @@ -308,7 +319,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num) end i = i - 1 - local x = 3.5 + i % 4 * 1.6 + local x = 4.5 + i % 4 * 1.6 local y = 0.3 + math.floor(i / 4) * 1.6 formspec = formspec .. "model[" .. x .. "," .. y .. @@ -325,11 +336,12 @@ function mcl_skins.show_formspec(player, active_tab, page_num) formspec = formspec .. "button[" .. x .. "," .. y .. ";1.5,1.5;" .. texture .. ";]" end elseif active_tab == "arm" then - local x = skin.slim_arms and 4.7 or 3.6 + local x = skin.slim_arms and 5.7 or 4.6 formspec = formspec .. - "image_button[3.6,0.3;1,1;mcl_skins_thick_arms.png;thick_arms;]" .. - "image_button[4.7,0.3;1,1;mcl_skins_slim_arms.png;slim_arms;]" .. - "style[arm;bgcolor=;bgimg=mcl_skins_select_overlay.png;bgimg_middle=14,14;bgimg_pressed=mcl_skins_select_overlay.png]" .. + "image_button[4.6,0.3;1,1;mcl_skins_thick_arms.png;thick_arms;]" .. + "image_button[5.7,0.3;1,1;mcl_skins_slim_arms.png;slim_arms;]" .. + "style[arm;bgcolor=;bgimg=mcl_skins_select_overlay.png;" .. + "bgimg_middle=14,14;bgimg_pressed=mcl_skins_select_overlay.png]" .. "button[" .. x .. ",0.3;1,1;arm;]" end @@ -343,7 +355,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num) for i, colorspec in pairs(colors) do local color = color_to_string(colorspec) i = i - 1 - local x = 3.6 + i % 6 * 0.9 + local x = 4.6 + i % 6 * 0.9 local y = 8 + math.floor(i / 6) * 0.9 formspec = formspec .. "image_button[" .. x .. "," .. y .. @@ -353,7 +365,8 @@ function mcl_skins.show_formspec(player, active_tab, page_num) if selected_color == colorspec then formspec = formspec .. "style[" .. color .. - ";bgcolor=;bgimg=mcl_skins_select_overlay.png;bgimg_middle=14,14;bgimg_pressed=mcl_skins_select_overlay.png]" .. + ";bgcolor=;bgimg=mcl_skins_select_overlay.png;bgimg_middle=14,14;" .. + "bgimg_pressed=mcl_skins_select_overlay.png]" .. "button[" .. x .. "," .. y .. ";0.8,0.8;" .. color .. ";]" end @@ -365,7 +378,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num) local green = math.floor(selected_color / 0x100) - 0xff0000 - red * 0x100 local blue = selected_color - 0xff000000 - red * 0x10000 - green * 0x100 formspec = formspec .. - "container[9.2,8]" .. + "container[10.2,8]" .. "scrollbaroptions[min=0;max=255;smallstep=20]" .. "box[0.4,0;2.49,0.38;red]" .. @@ -386,24 +399,31 @@ function mcl_skins.show_formspec(player, active_tab, page_num) "container_end[]" end end - + + local page_count = 1 + if mcl_skins[active_tab] then + page_count = math.ceil(#mcl_skins[active_tab] / 16) + elseif active_tab == "skin" then + page_count = math.ceil((#mcl_skins.simple_skins + 2) / 8) + end + if page_num > 1 then formspec = formspec .. - "image_button[3.5,6.7;1,1;mcl_skins_arrow.png^[transformFX;previous_page;]" + "image_button[4.5,6.7;1,1;mcl_skins_arrow.png^[transformFX;previous_page;]" end if page_num < page_count then formspec = formspec .. - "image_button[8.8,6.7;1,1;mcl_skins_arrow.png;next_page;]" + "image_button[9.8,6.7;1,1;mcl_skins_arrow.png;next_page;]" end if page_count > 1 then formspec = formspec .. - "label[6.3,7.2;" .. page_num .. " / " .. page_count .. "]" + "label[7.3,7.2;" .. page_num .. " / " .. page_count .. "]" end local player_name = player:get_player_name() - minetest.show_formspec(player_name, "mcl_skins:" .. active_tab .. "_" .. page_num, formspec) + minetest.show_formspec(player_name, "mcl_skins:skins", formspec) end minetest.register_on_player_receive_fields(function(player, formname, fields) @@ -412,23 +432,15 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) return false end + if formname ~= "mcl_skins:skins" then return false end + + local formspec_data = mcl_skins.player_formspecs[player] + local active_tab = formspec_data.active_tab - if not formname:find("^mcl_skins:") then return false end - local _, _, active_tab, page_num = formname:find("^mcl_skins:(%a+)_(%d+)") - - local active_tab_found = false - for _, tab in pairs(mcl_skins.tab_names) do - if tab == active_tab then active_tab_found = true end - end - active_tab = active_tab_found and active_tab or "template" - - if not page_num or not active_tab then return true end - page_num = math.floor(tonumber(page_num) or 1) - -- Cancel formspec resend after scrollbar move - if mcl_skins.players[player].form_send_job then - mcl_skins.players[player].form_send_job:cancel() - mcl_skins.players[player].form_send_job = nil + if formspec_data.form_send_job then + formspec_data.form_send_job:cancel() + formspec_data.form_send_job = nil end if fields.quit then @@ -437,34 +449,52 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end if fields.alex then - mcl_skins.players[player] = table.copy(mcl_skins.alex) + mcl_skins.player_skins[player] = table.copy(mcl_skins.alex) mcl_skins.update_player_skin(player) - mcl_skins.show_formspec(player, active_tab, page_num) + mcl_skins.show_formspec(player) return true elseif fields.steve then - mcl_skins.players[player] = table.copy(mcl_skins.steve) + mcl_skins.player_skins[player] = table.copy(mcl_skins.steve) mcl_skins.update_player_skin(player) - mcl_skins.show_formspec(player, active_tab, page_num) + mcl_skins.show_formspec(player) return true end for i, tab in pairs(mcl_skins.tab_names) do if fields[tab] then - mcl_skins.show_formspec(player, tab, page_num) + formspec_data.active_tab = tab + formspec_data.page_num = 1 + mcl_skins.show_formspec(player) return true end end - local skin = mcl_skins.players[player] + local skin = mcl_skins.player_skins[player] if not skin then return true end if fields.next_page then + local page_num = formspec_data.page_num page_num = page_num + 1 - mcl_skins.show_formspec(player, active_tab, page_num) + + local page_count + if active_tab == "skin" then + page_count = math.ceil((#mcl_skins.simple_skins + 2) / 8) + else + page_count = math.ceil(#mcl_skins[active_tab] / 16) + end + + if page_num > page_count then + page_num = page_count + end + formspec_data.page_num = page_num + mcl_skins.show_formspec(player) return true elseif fields.previous_page then + local page_num = formspec_data.page_num page_num = page_num - 1 - mcl_skins.show_formspec(player, active_tab, page_num) + if page_num < 1 then page_num = 1 end + formspec_data.page_num = page_num + mcl_skins.show_formspec(player) return true end @@ -475,7 +505,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) skin.slim_arms = true end mcl_skins.update_player_skin(player) - mcl_skins.show_formspec(player, active_tab, page_num) + mcl_skins.show_formspec(player) return true end @@ -496,12 +526,12 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) local color = 0xff000000 + red * 0x10000 + green * 0x100 + blue if color >= 0 and color <= 0xffffffff then -- We delay resedning the form because otherwise it will break dragging scrollbars - mcl_skins.players[player].form_send_job = minetest.after(0.2, function() + formspec_data.form_send_job = minetest.after(0.2, function() if player and player:is_player() then skin[active_tab .. "_color"] = color mcl_skins.update_player_skin(player) - mcl_skins.show_formspec(player, active_tab, page_num) - mcl_skins.players[player].form_send_job = nil + mcl_skins.show_formspec(player) + formspec_data.form_send_job = nil end end) return true @@ -517,30 +547,29 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end if field and active_tab == "skin" then - local skin_id = tonumber(field) - skin_id = skin_id and math.floor(skin_id) or 0 + local index = tonumber(field) + index = index and math.floor(index) or 0 + mcl_skins.simple_skins[-1].texture = nil if #mcl_skins.simple_skins > 0 and - skin_id >= -1 and skin_id <= #mcl_skins.simple_skins + index >= -1 and index <= #mcl_skins.simple_skins then - if skin_id == -1 then skin_id = nil end - skin.simple_skins_id = skin_id + skin.simple_skins_id = mcl_skins.simple_skins[index].texture mcl_skins.update_player_skin(player) - mcl_skins.show_formspec(player, active_tab, page_num) + mcl_skins.show_formspec(player) end return true end -- See if field is a texture - if field and mcl_skins[active_tab] then - for i, texture in pairs(mcl_skins[active_tab]) do - if texture == field then - skin[active_tab] = texture - mcl_skins.update_player_skin(player) - mcl_skins.show_formspec(player, active_tab, page_num) - return true - end - end + if + field and mcl_skins[active_tab] and + table.indexof(mcl_skins[active_tab], field) ~= -1 + then + skin[active_tab] = field + mcl_skins.update_player_skin(player) + mcl_skins.show_formspec(player) + return true end -- See if field is a color @@ -550,7 +579,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if color and color >= 0 and color <= 0xffffffff then skin[active_tab .. "_color"] = color mcl_skins.update_player_skin(player) - mcl_skins.show_formspec(player, active_tab, page_num) + mcl_skins.show_formspec(player) return true end end @@ -559,15 +588,6 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end) local function init() - local function file_exists(name) - local f = io.open(name) - if not f then - return false - end - f:close() - return true - end - local f = io.open(minetest.get_modpath("mcl_skins") .. "/list.json") assert(f, "Can't open the file list.json") local data = f:read("*all") @@ -590,6 +610,16 @@ local function init() mcl_skins.alex.top_color = 0xff346840 mcl_skins.alex.bottom_color = 0xff383532 mcl_skins.alex.slim_arms = true + + mcl_skins.register_simple_skin({ + index = 0, + texture = "character.png" + }) + mcl_skins.register_simple_skin({ + index = 1, + texture = "mcl_skins_character_1.png", + slim_arms = true + }) end init() diff --git a/mods/PLAYER/mcl_skins/list.json b/mods/PLAYER/mcl_skins/list.json index 01bb622e5..8ee0aa830 100644 --- a/mods/PLAYER/mcl_skins/list.json +++ b/mods/PLAYER/mcl_skins/list.json @@ -3,7 +3,8 @@ "type": "footwear", "texture": "mcl_skins_footwear_1.png", "steve": true, - "alex": true + "alex": true, + "rank": 55 }, { "type": "footwear", @@ -198,6 +199,12 @@ "texture": "mcl_skins_bottom_4.png", "mask": "mcl_skins_bottom_4_mask.png" }, + { + "type": "bottom", + "texture": "mcl_skins_bottom_5.png", + "mask": "mcl_skins_bottom_5_mask.png", + "rank": 65 + }, { "type": "top", "texture": "mcl_skins_top_1.png", diff --git a/mods/PLAYER/mcl_skins/media_credits.txt b/mods/PLAYER/mcl_skins/media_credits.txt index cda321d60..de32368e9 100644 --- a/mods/PLAYER/mcl_skins/media_credits.txt +++ b/mods/PLAYER/mcl_skins/media_credits.txt @@ -21,6 +21,9 @@ mcl_skins_bottom_3.png mcl_skins_eye_7.png mcl_skins_mouth_7.png mcl_skins_hair_10.png +mcl_skins_hair_6.png +mcl_skins_eye_6.png +mcl_skins_bottom_5.png Original work by MrRar License: CC BY-SA 4.0 @@ -66,13 +69,6 @@ Author: hansuke123. Adapted for mcl_skins by MrRar. License: CC BY-SA 3.0 Source: http://minetest.fensta.bplaced.net/#!page:1,filtertype:Id,filter:291 -mcl_skins_hair_6.png -mcl_skins_eye_6.png -Name: Mumbo Jumbo -Author: ZestyZachary -License: CC 0 (1.0) -Source: http://minetest.fensta.bplaced.net/#!page:1,filtertype:Id,filter:2100 - mcl_skins_eye_4.png Name: lisa Author: hansuke123 diff --git a/mods/PLAYER/mcl_skins/mesh_hand.lua b/mods/PLAYER/mcl_skins/mesh_hand.lua index 28b2bab20..a1d6c0903 100644 --- a/mods/PLAYER/mcl_skins/mesh_hand.lua +++ b/mods/PLAYER/mcl_skins/mesh_hand.lua @@ -14,7 +14,9 @@ function mcl_skins.get_skin_list() for _, game_mode in pairs({"_crea", "_surv"}) do for _, base in pairs(mcl_skins.base) do for _, base_color in pairs(mcl_skins.base_color) do - local id = base:gsub(".png$", "") .. minetest.colorspec_to_colorstring(base_color):gsub("#", "") + local id = base:gsub(".png$", "") + .. minetest.colorspec_to_colorstring(base_color):gsub("#", "") + local female = { texture = make_texture(base, base_color), slim_arms = true, @@ -36,7 +38,8 @@ function mcl_skins.get_skin_list() table.insert(list, { texture = skin.texture, slim_arms = skin.slim_arms, - id = skin.texture:gsub(".png$", "") .. (skin.slim_arms and "_female" or "_male") .. game_mode, + id = skin.texture:gsub(".png$", "") + .. (skin.slim_arms and "_female" or "_male") .. game_mode, creative = game_mode == "_crea" }) end @@ -45,10 +48,10 @@ function mcl_skins.get_skin_list() end function mcl_skins.get_node_id_by_player(player) - local skin = mcl_skins.players[player] + local skin = mcl_skins.player_skins[player] local simple_skin = skin.simple_skins_id if simple_skin then - skin = mcl_skins.simple_skins[skin.simple_skins_id] + skin = mcl_skins.texture_to_simple_skin[skin.simple_skins_id] end local creative = minetest.is_creative_enabled(player:get_player_name()) local append = (skin.slim_arms and "_female" or "_male") .. (creative and "_crea" or "_surv") diff --git a/mods/PLAYER/mcl_skins/meta/mcl_skins_character.txt b/mods/PLAYER/mcl_skins/meta/mcl_skins_character.txt deleted file mode 100644 index c31bd7168..000000000 --- a/mods/PLAYER/mcl_skins/meta/mcl_skins_character.txt +++ /dev/null @@ -1,3 +0,0 @@ -name = "Steve", -author = "%TEXTURE_PACK_AUTHOR%", -gender = "male", diff --git a/mods/PLAYER/mcl_skins/meta/mcl_skins_character_1.txt b/mods/PLAYER/mcl_skins/meta/mcl_skins_character_1.txt deleted file mode 100644 index e6c90dc0f..000000000 --- a/mods/PLAYER/mcl_skins/meta/mcl_skins_character_1.txt +++ /dev/null @@ -1,3 +0,0 @@ -name = "Alex", -author = "%TEXTURE_PACK_AUTHOR%", -gender = "female", diff --git a/mods/PLAYER/mcl_skins/simple_skins.lua b/mods/PLAYER/mcl_skins/simple_skins.lua index 523832f30..3e08c0cb7 100644 --- a/mods/PLAYER/mcl_skins/simple_skins.lua +++ b/mods/PLAYER/mcl_skins/simple_skins.lua @@ -1,5 +1,5 @@ local function init_simple_skins() - local id, f, data, skin = 0 + local id, f, data, skin = 2 local mod_path = minetest.get_modpath("mcl_skins") while true do @@ -35,18 +35,13 @@ local function init_simple_skins() end -- add metadata to list - mcl_skins.simple_skins[id] = { + mcl_skins.register_simple_skin({ + index = id, texture = skin, slim_arms = data and data.gender == "female", - } + }) id = id + 1 end - - if #mcl_skins.simple_skins > 0 then - table.insert(mcl_skins.tab_names, 1, "skin") - else - mcl_skins.simple_skins = {} - end end init_simple_skins() diff --git a/mods/PLAYER/mcl_skins/textures/README.txt b/mods/PLAYER/mcl_skins/textures/README.txt new file mode 100644 index 000000000..8b50278d3 --- /dev/null +++ b/mods/PLAYER/mcl_skins/textures/README.txt @@ -0,0 +1,3 @@ +To add custom skins to the game, please use the mcl_custom_skins mod. +Download it from https://git.minetest.land/mineclone2/mcl_custom_skins +Support for adding custom skins to mcl_skins will be removed in a future MineClone2 release. diff --git a/textures/mcl_skins_bottom_1.png b/textures/mcl_skins_bottom_1.png index 733cd8aa482ca5d930bb6b5ec90f362882db3e9a..65ab46ca97e4fbc1943b37f043b60d04ebd415d5 100644 GIT binary patch delta 360 zcmV-u0hj*b0rvus7=H)`0001@oqmJ>00BNpL_t(&-tCvcZNo4O08eRGXp>JSP&GwI z$S0Yg0Xjl~JOXrt0_g#sc}~`XMtzn2`GVc$2M)lo)&oQ!QMqo&D>hZNe_0{4S(~=&=D}3dJ33^P;_CO z0=|b7pkZIzgT2-Ruq`@H$f=P1El0qt;)EAYdEs<=Vg2S0V6xoDL0Og$#uy*R06}&l z4Sdi&k0kS0D`zg>OJmkR)jEC*n|Tu@~BkFQ*>lO;u#vpby3(5-MM51ajVb=)0J zo6q;x#3^>lFz$+-9Sx+B*C1s;|IH~#;(tXmKectj+2E5vnVhyayT$BX?*3g_!xh&!RzHR cwm%Wb7T^=&3Z#KxY5LCdK#H*>$S;_|;n|HeAV=2I#W6%8 vJUKxkr9r;KP9WjWfBsM(!^ieLz1@rq55ttC%Z{mdf^>Vj`njxgN@xNAIqDp{ diff --git a/textures/mcl_skins_bottom_4.png b/textures/mcl_skins_bottom_4.png index 304a2ccb5db5d5f183d9625ff3d2cdac0bfef1e0..2911d2527b1a13d4b25bfe8c45bf5986d15fccbd 100644 GIT binary patch delta 725 zcmV;`0xJEe1?>fpB!9F?L_t(&-tCt^Od3%f$3O3R9HU!kVwi3F7+9}iAF;0SMmj*L zVe7AI*ZYIkf#@}TZyOx}@~%suRs?KUNub`0Sns_~2JuGcfbd_&^w)4uCGp!F0c8m! zft?C_*0NPDx^m$=RsFZx0Y$(Y3Wc1&9&iktS@tq+Aw*mGW@cvQvRU$n?C$P98y+4O z(P-2J4uG$^u74|rVR$Qa+6uS;0)fD(5Ta#zdb+bIl3+HQ{gh6pAM3h)v9huvbzOJ( z{eIKsayfq|3L#7>rNcB$R8>6zPM4OJj;o^NR?-5zN+c5bo}M0aVPU~nEEW~7*L$KU zij2i#Lx4|8nNt)+D2n3LH0?l2=@=g$?*-a3nN0S!=YN2WwY4=dI5^n4yu6$Vg+kxM z;c)A~z<^SgK&ez}GfmT3C=^tW$74t-kAe5+=jWMbNP;8t^Yi(>zCPyW=7JLw6F=Q< zcPXFGm&5zB5F+F8c#g)##!{N5`6H1?OIKG{$Km1Oy=E+g{)noo?W(E*u)n|W0A2$h zfT4eQynnLD`er59wrfh_a=HBGe=mdp62Mcdod?>1=fHj79iRcd)=6?R;nh(US>;>gtjyWqVv1V%$s3$ z=k2`r{tFt7Mx)VaG#ZUYqtR#{8ls798W>akB4D@qnbW{V6My@JYVA%sKsK?B-Rigd zg*Jd!E#}^I`UV&eJp`KFfa0wXXg3pT-&SE@cRB}5|6$Eo69+Y7ck>PKLZAQ~G}z0^ z)_CZ~gCE?Q?`j9sfC%6Regdb!xw3nNgb=;nAd|^d?@RtL1_uYv$H<>gwt>@D3<$ zZEcyZ>qZ*lG=BhC0CRJ5ju67Pw6rvEFC0)Vmp|IJZ6*>4V|#nspUGtU!r^e$vMm4a zL?OhrVHhUB(a}+5W@g4%US7Uwk;u9VAMkQ>bF&f(g)YhpMRg9@6YG+=E};-{>aEkq+YLk zqQwWC1%tu9R4U~L0)d`VsZ=vf^TxLAA@E%D1#o9)Z^-U$$-WHPB zlgrsoE5U!IsH(?_8drcI@C|w(S5>!0CpcA*l{$0x{sJa>juA`d6w2Fbai2Xm@wFzO%FAxUO5t<#JUa qL@64L9`5b!oz!ZzL*=kL=NAmbt_$-d!L#3^>lFz$+-9Sx+B*C1s;|IH~#;(tXmKectj+2E5vnVhyayT$BX?*3g_!xh&!RzHR cwm%Wb7T^=&3Z#KxY5LCdK#H*>$S;_|;n|HeAV=2I#W6%8 vJUKxkr9r;KP9WjWfBsM(Mdl+dn+gpX=FC=*^(|D(0_pa2^>bP0l+XkKEPWg( diff --git a/textures/mcl_skins_bottom_5.png b/textures/mcl_skins_bottom_5.png new file mode 100644 index 0000000000000000000000000000000000000000..2645d97662a1a554cde37ce7b8155c2c5d2c4f89 GIT binary patch literal 891 zcmV->1BCpEP)jyyPU}(SvtS{tqg6QX(EiK`2t8 zVx@vem5LsO3ehSpwvuYlN~)3Z@*+#vv{=Y`a36%tPQIPYyzk9?vydP`f&>W?BuJ1T zL4pJc5+wNFU=g-MKr^u5?gcaZz6QT1fIBs|0bmAbbN7#CwguP^%;fs??ryT39sfH~k;+zLoV*wR47-5&t1;Qk8k{x;&d zC0)DBtQ9B$MKenQJ48_Ih*CfS7&o(xX0~Tdb!FBOVcxB4S!7H~ZTqB(_rRNf(E~05 z6F>&&Qh;}X1>iKW4R{881N!vbB(Mw|04_xM9RMEH*oJ{yb>dhL{HU?*Raq=HS^;IC zsGVQZpH_El26!vEE&~;{WygG9c$Vw@J zl#tQ2vyR`il(S@Jr_|tN63^uE)kAzNwG0DCk7!UP^St(&bzo#OOz+LJY86{l+ z&MLX=3bA|(m0U-h1f*2|nGpNkQbDyOj*EmqJ3p)BqDr7w{iC8X>K1t^l|mG@ir8_H zyR34EO#x*ESyWP;?*3GXwn-gX5i~0zs>f$-30x0Nndg8(AaM7GA~6d4rIbO<7S#bM zmQlDxpPMyO2DlP3O=~yXLOmfJ8d?INq$%)*e4m!0UIH6{!}^}m`fAemm3RTzqq*QZ za8So#tZ##>VH5B*bl)Snw@4+wfJ;(Rb)I-E#hjN)uBqu2bmH`D-KYp2R8P1Je2DvH zXf=GTxo=nU0dU*hU+85gP%@+L-U3w2Yyt?(ERdq!sOCqs>pN6p<07o#_zf5&_~GFu Rf7Ac~002ovPDHLkV1g_1mHq$# literal 0 HcmV?d00001 diff --git a/textures/mcl_skins_bottom_5_mask.png b/textures/mcl_skins_bottom_5_mask.png new file mode 100644 index 0000000000000000000000000000000000000000..1fdd26ee645cfeba3d15e8b3f77784ebbfb23205 GIT binary patch literal 183 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQgxm#jv*QM-d;b*)u15Il4xG_ zKYX5FBfH|-u<&pH`+@>r`y^-r)d96hXRlfLc$RwBo$~cBk6Q1v+@#*Xm?D4R=Ealy zt+Si|^9Vhd%b+ji}8xFQOd!_z`(F*Ze0tI3h{Jt49U3n_R>PZ1_u%5i?Vg>Ar6cgT06_u9ohV1 ziUX$vTQBRklRhD83Z9de)URTn%No(hdt?0?Mq>lUR%aFlhJ&t*3_SXt RGl41@JYD@<);T3K0RRqK8!-R? diff --git a/textures/mcl_skins_hair_6.png b/textures/mcl_skins_hair_6.png index acd5f3ff29f24c8e3af8c9beefb248a857b6faa8..eea7a69a636aeafff078891dcae6ebe1133f1672 100644 GIT binary patch delta 521 zcmV+k0`~p&1D6Dl8Gi-<005$$euMx30p3YOK~!ko?UzAo6Hyd}znj>pN!u_WmINUb z(nV*Jm5~48#((AyDK5pm3pawe5=uZUN@<9uDJk)|IRitfCW?!h`aXEPyqWukxo7S> z?K_X>Ad6DCq*&1)czJfisIRZn^-mMNHc!h@_S) zBCp(^-s=jGbO7X%t|OuY97#I258V6@OW?|0@X$g`BjP~PQqr>V0!Ye$XYPBIRscOG zK9ke}7M?e@D1Spqd8K7QTT%`j0|WmaO3Ebd0~1O6j_=e#gaRo1qT{kJh4A=SlrbGY zqYWH;{HW|L#@K!`aNh$abyxx;;8R3QfcIYKU;V}B5i$GC{JCRxJnjH1VC@}aZ3Ddo zt}M`weFflg9RxU(bnU&q4SfE~wLOZ6?~=|VqJPUszkgYnZq-+6V}cQJBI$KRtUR7= z`0{sE!b{IxRhCEBrC&`vi-@7ei#iC<2hKJmTvYwy*0sBsR?Z3wCthxumu`(Y2;o0L z9pFPH`K3>U+fbTaF6oVTkLe#)St5~0Boc{4B9TZW5{X3OU+@!im(s|yfnXm10000< LMNUMnLIPld7qsez delta 486 zcmbQv@|AglWIZzj1H)A3zHLBiQGic~E0E6opE+X&!~g#){{R1f@PEsV|C|2*zj5#X zzW*TfU)GAjDxBf*|Kl(JU;h99C7tFxK%*@Qf&d$NX!O6+V&CScl z$1fltBrGf+kA9_bN%|`_+EJjO$|}5n% XnoHh|xG}Q;=raaSS3j3^P6LiCdDS^9C^smzyLxIQndDbj=%C@_Dvn5yVeP2{_gJ_d(P@=ez#7z&UQ(4 zOQ4QQezKUE=5oG@;#E~M%B>FlQs)F(#lVp8l4+?7ub_guVXYE~@9FC2vd$@?2>|5& BIYs~g delta 117 zcmZ3%*v2?PB9D=ofq`L0@SEd6iY>q=#1%*b!P4}d=YbSsNswPKgTu2MX+Vyir;B5V zM0j$-kMj(yQw;wxGqzmhNd1$%!aeyo Oka3=_elF{r5}E+~CnfIy diff --git a/textures/mcl_skins_icons.png b/textures/mcl_skins_icons.png new file mode 100644 index 0000000000000000000000000000000000000000..3f2241afed4cc180b438e316f329cdabcf80df7b GIT binary patch literal 554 zcmV+_0@eMAP)()YCAmlt1r{Mk<%d|@QwdU)KbX0IKnB4#q7ef#7b21x z-L$N7X3(I&EVa4uRBL99Srb~Ln}tIAwMwZ%dYQ2Tp}I2yYgAPf+OKs+U1f8ruBa`k z8LrDwfiu(b=KDzzD?|`U#{&bAhTa%LBm;@=!DIzc7!P)+K4FFJJs>OAQP2<%UfqLe zte=Vp+kVgjNpzTK-}i$9qA?vQ9qAB9`UjvIKkgfTPu_SP6k1*(Haw+8a$}y8&pfS{ zAb8O5xUW_4T2+h3eMY9vh|ih1KjSWdyMIe&ZB|(ZcOea5z(A6MHLaSlHoiohxc533 z5?}~0fpC8=8W@%#FHbz0nRW~Dq@Hh?VObK z%ft$xaEV5obt1t7)(sOQJyjG$8d$jN6a399@t0uT5~OHI5%f(6%j(_jp%7+W%j+zj z<^{~(_mRAracRxzA-J_;cJm(m!m(_H!#Wr|G4?&)tdup1PC5R(AGlw-VZ1KdnLg8% zdBVj>6#!-=uU;BifgCH)V@o(J8kZ2M&E~{tEPM#8W9KeYTMEbnM$(QI$V)8h=R)fb sP1^HT);jfkf%TcPAG36RIzNKG0DY83mM#z%X8-^I07*qoM6N<$g7`!6x&QzG literal 0 HcmV?d00001 diff --git a/textures/mcl_skins_mouth_3.png b/textures/mcl_skins_mouth_3.png index d8ceb01e76490c5332969ac20e3c0bf8b5d78aba..2249962b0d4e2fceec5762173748f9d08733aadc 100644 GIT binary patch delta 91 zcmb=)n;;R!!N$PAuxM^w3y?DPba4#HxcBywp&)|-56i)d#f@yW5)SD}3@iq3!ovU8 qumBasytVvv<$mvmD(`Y2k0CCsZ!yOef2O~mK|D`aKbLh*2~7Y{R37I5 delta 105 zcmd0+nIMtE!py+H5U@FUJCNcJ@Ck7R(o6k3foO(@Gmu=OoH-FF#9R{O7tEkrFZJxx z93WTH)5S4FLNZx`^)R1Bm%#&eEjOOU2_gc_42{zn*4*c;*b7v|;OXk;vd$@?2>|#- B9jX8T diff --git a/textures/mcl_skins_top_5.png b/textures/mcl_skins_top_5.png index 0c0ea6d19262d77d0990732a3d4a206bcd945757..716b0e3051e78a3f92ae6e69fcb1b73d9ea49a0e 100644 GIT binary patch delta 1327 zcmV+~1<=phgNvAT<(=q9Pi>gq?|xxG}-_03x=f zv~%w~&T-MHHcb;_+Nz8BttQ|6|KFK8^L^)>ftZ+>n3$NDn17g*mx)(uYu}jc1Wftt<-*XJ zC~kn7iu}VtkbeNG0a>1(|1*=!YfScmK5cH^nhk>IvRZcqS_@n2^}QD_esyno`RVWb z`!`h;7IvJvc(M6`%F2bgFnlr3G;^bRPbpJ};o~zBiR}p~1EqDVhHcU?R8FbZ>%QNa zGELVK;u)p&c26l&DYZE;jIOk04ZEKA4A53!+rvuh)_?21-wu$ntc}1nfaWu2o}2Ef zcMfMV`++K;y0g0aSXAnXr>d$x1HJ^DFlmX7E6)ScF zcLTSdTCt)HNCB0HmMnQK^3HyJ$&y!rMPt0xK*j0C#_d2cQ2BQcZ%)Ak+^EA)0UB_` zUnN-`Uc013GfPT+w9q_yZ zj%j97mbG3f)%N4y;2hI5A1qBKI}%d*Nh!A&uzxj5-TF;m-{G=!`d3?sO@Y?CuefgU z%w+Nr32g!x2!c&RzW@5%RO)h4$}PWVvt0ni$z+QghPy(g#OlvK-#pzdPZ3g#Kz!8L_yW)b%sNt6w+|=> z7Jv4PT;~JngNqj*1nwH+oeRv4ys4-SrhOOCDcjBgrBP`D1W^eR_3?ZUY@iSD$LI$W zQhJeZRBr+EFS+i_(Gt#SZ36>9=vbB?d4*vZdfZqhaNBR$Y#}fN6i#~!^w!t6BgBSK zsqO*K%NIhdDYEUCLZ!qHgM%##i;H($aev*SP^q>3x!lp4)9GKv>ZK5C@-3@VYi-O( zBw9kPcU*DZq8sw^)_&L5cVuoVb;%8ar>=S4oB5V?Jz-hv(7L<8wukyW?`by(4x~+U zct#@8((id)SF_o|TMG)-40>K?sI|E7+_{$NZh`V+nao~b7O;5N9e4BsHv#jWsDG$9 z51a=ob}m@Z3#=ZeZ*HGI|3tL%&+A>jyd(O$74Ixx-VUq+ZtAYB?Ez|l>bL6Z_D5c) zr>^ehXr&+ZRssv&9oaR?fO-E$3&>&LPmcCqbTBCeu9`xGz&$|V2$2OYjnmtDq>N_+ zR~^&L0U;3NNtpwF0+J~qT;N;49DnkCC-RnH7=Mm6f%odaau7P6$?UO(SdU?J_)1AP z2wG+&5^X8d%zknC^0T!iB|CkkY^C*v-*dTxj%jA|q+Ew#bPRf43V5t2(hmi}v(hkj z`bycp)*H0e-Pb%XJ=<{}_Lb^%gCLQVa;+4i!xqB#mD&<&-C1PY*T;JcEhuaIPeVhc lYc5=P^#A002ovPDHLkV1jO%l-d9Q delta 2019 zcmV<92ORjp3h)n*BYy|CNklu zWTrFKow>8CJ9n@4JKs6y`*zc&@+gn;D39_ekMbyw@+gn;D1VRgD39{^zaMI79FE`^ zwAf)JAAJ=+^!a}k3MUogzyr^DE6lZ8H9Cj7$4@~|OhfSv!d)?mtxukS-9HLnauFLj zU(S*Hud~@Vc~KrJ0M1Ym&hS2hFbsEe>c;>8U*(|(p3|bk_^h?{Qm}Rj@rD;+^FPJ& z4oW?*ILxqXXA?&Uc-iuiee%WWV#F0-yx;LGceD@yJU^G#vX; z42U(n^uTj!cwE+kuILN{onXeh;jfv4o;(IuYzFSwBsLp;>;B(2x!lU?k?%A$UFFsG zPyz5%6yZ-CAw?JAVupU`^Pi^EmwoZM2cPqng43e&(0{@+aE1=S8=rwAG=*^O3-DLX zLk*6u`+qmu+t2dyOHTJU`TXnub-;Fa4oY|o_P`$4JuR^NGVoT75P%up=djt8f+Mh( zlpTWI)l%A{?y{wQ5&2lxlit|0xnCyf4xYO#_wwxZOy>Nzg~IE1OXn=h z{(o{0_nnga@2q>7>jU5^z{M=sjWGt=0ay5Gcq+!B1d4Fz-3<5{D8>+f55umt!S3#a z8Xh5K4-lZdWGwbcOUoa5eMIui7dd4yAbC5RJ%7z>KoV~;z%To+cXXWL)sQSoP@8>Y zSYvSJu=$2o_lF7K?}eOl&L^#{Z}Zx~8NHp$owoL<_vs1ppR&hdMu@Y1T>xx)KeJ5= zCSRs0Nx*pqSY(DdeLJCecEBBB_Wk=HY_YpD@WckE6MV5=j zB7a=L15or{I3v>p>nLQ+a_rFc_V#nUZk3m%p;E=5A z&%ojDf{~o1vyYSVJNcU+=+Dx)4w5yyAb+Lk3sU_?CUf?0t*w_oYHlV#BLrxe*HKh7 zyg;A^DT|^R;ML~lE2J>q-M;-p$=cuB+f6xa`NaxWCE)N+fgs`Ywzl&EmdNBQvgwQV z_CGM|kYI0f5*Ty+4uSZ7jeO)BS=*2Vlt2$n={a~S4nfrim|;pFMnei5j+HX;f`8C$_5f;R1Zs#Zpb2_n-O%EP3C=Fl103NlzUXeK zl!eglvr-V|pC=wW1!u6AOzI&6O5WnHIZn5qfKgp)bncZ(nJV*MJ}>t+XJim+bOhem zv+z|P2Yuq4MPucoRO($Rp+adZXpw+!-LIv+gLB(o)9FhauL7jJzxFtFI)6v~=ipG& zh;CUxpn8_Uc0i-!Yix)d1j%U(Fz`OOA_H725}-cZBo#S9cYae0%@seypa)@dw!;vw zV5!rBJD^2|2~3|!)0=E&q#8)3R%x%W6SN1$D8&h$KQA;F5YB$k)bu_XfGdrSSFg9V zo#7fNxeGM96#`)H;qUX}{C{G8G~~A^Es@YUiwWyUK;OsUne9jsHf<+^+6y)oVRL;XU@W)5qcs=;H!`Z$uvzD=Mxv3nnVtbB7XymZDNj^Wu}#! zKNBG2|3wlvOI0Jep*C4DdZAZIA3!OPwsvg?HQ0~3#uKIiD#p|B#l`V^p)upmAZ0?& zP^njy-XJCEexa~zwWQ9f$9_$d?1#gbW(CQRMNh)%Od;0r8&;bI*rN zobotEzZii{ABK^bB!AQP$X>ey{y}r|`xY4WA8z0Np4A8?zbpYD_o2HbDTPH67Qk*x zLhDFC>tZ0|>vmxN>IKSS2o9~+WPr+V2F2Tnc>N+7L)r(Y*+b0IKSmL$Sz^Eo3}`o5 zG)$8{f-O&+qz?>1=XZj}Yzx)>$$5e`h(PTEOYjK0!D%>Yo_}_u3&G@3evnOpaycV% zV6`~MDszFIAZ~C?j8~*26+wCr*~7IJ8tfTX3$t;e9Nyma6Aa&fbhwox<`07}iBrnFk=7lS4P>{^P| zCIh`<4x9ehM_e$`!(dsu{Cn9!POz_k1xD4P8NAJSj)5oc2WBd?o0UZAZNU(fXM jyS)PgBZ~ltXi)c?bAn&sPU?z{ATvB&{an^LB{Ts5T_rWL delta 104 zcmbQvST#W+iIJIsfni4Qo8v%=Ex;$l6-WcY()69@ffQp&kY6x^!?PP{K#r29i(`mH zcyfY7O2hodyFiPERcKLU_0gD0fwasJPaag0aC9N59ol5@O1TaS?83{1OO5? BAI|^) diff --git a/textures/player.png b/textures/player.png deleted file mode 100644 index 863991b34c856cfa51c82865f56faf658515f816..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 419 zcmeAS@N?(olHy`uVBq!ia0vp^0zj<5!3-pI!a4o{Db50q$YKTtZeb8+WSBKa0w~B{ z;_2(k{*;NEL0R3#-s~4pC@{b$#1%-Zit(w63m7U&m?}#;=_|XLsCeqDgg6>RI~r!I z8fN?1R>gTXWdyhAnangbo!Oeb*wJQjdf29_5`4OSv7WG0nN!9Tr7ai3oo81qo^5dSTI*Yp-NxT{7ye#Tq1S)>(;U%dyH6iA zHE!K~wW>HcW9{}{GfRbu2deTJ83jeAHBIE1%PN?C=0vbP0 Hl+XkKs6Cjr diff --git a/textures/player_back.png b/textures/player_back.png deleted file mode 100644 index 39e143c3b7116f059245c0d0def8f7b108b5d8f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 307 zcmeAS@N?(olHy`uVBq!ia0vp^0zj<5!3-pI!a4o{Da!z#5LX~=s3;NQXyBx;9Oq-% zqGvMG)O4|NZs+FHR5J-p8L8Z?qJOObqDkh$cw0`EMQ<@efNZoYv)5g znH$Gzc)0G|aX84A{@_6D`l^Qq7HY_FFz~T3{Aavx?=YJu%WpN%%?zHdelF{r5}E)R C+i Date: Sat, 29 Apr 2023 12:27:56 -0500 Subject: [PATCH 136/155] Add mcl_custom_skins info to README --- mods/PLAYER/mcl_skins/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mods/PLAYER/mcl_skins/README.md b/mods/PLAYER/mcl_skins/README.md index e639ea93f..e5dea85e9 100644 --- a/mods/PLAYER/mcl_skins/README.md +++ b/mods/PLAYER/mcl_skins/README.md @@ -3,9 +3,11 @@ This mod allows advanced skin customization. Use the /skin command to open the skin configuration screen. +To include custom skins in MineClone2, please download [mcl_custom_skins](https://git.minetest.land/mineclone2/mcl_custom_skins) + ## License Code under MIT license -Author: TenPlus1, Zeg9, MrRar +Author: MrRar See image_credits.txt for image licensing. From f1d17e2c69eab1dfc59cee5b6b7326d2bc25b438 Mon Sep 17 00:00:00 2001 From: Johannes Fritz Date: Thu, 18 May 2023 12:48:41 -0500 Subject: [PATCH 137/155] mcl_skins: PR feedback --- mods/PLAYER/mcl_player/init.lua | 14 ++- mods/PLAYER/mcl_skins/README.md | 17 +++- mods/PLAYER/mcl_skins/edit_skin.lua | 144 ++++++++++++++-------------- mods/PLAYER/mcl_skins/list.json | 32 +++---- textures/player.png | Bin 0 -> 419 bytes textures/player_back.png | Bin 0 -> 307 bytes 6 files changed, 111 insertions(+), 96 deletions(-) create mode 100644 textures/player.png create mode 100644 textures/player_back.png diff --git a/mods/PLAYER/mcl_player/init.lua b/mods/PLAYER/mcl_player/init.lua index d7ae6e81f..084fe48a1 100644 --- a/mods/PLAYER/mcl_player/init.lua +++ b/mods/PLAYER/mcl_player/init.lua @@ -98,7 +98,19 @@ function mcl_player.player_set_model(player, model_name) damage_texture_modifier = "^[colorize:red:130", }) update_player_textures(player) - mcl_player.player_set_animation(player, "stand") + + local new_anim = "stand" + local model_animations = models[model_name].animations + local old_anim = player_anim[name] + if model_animations and old_anim and model_animations[old_anim] then + new_anim = old_anim + end + mcl_player.player_set_animation(player, new_anim) + else + player:set_properties({ + textures = { "player.png", "player_back.png", }, + visual = "upright_sprite", + }) end end diff --git a/mods/PLAYER/mcl_skins/README.md b/mods/PLAYER/mcl_skins/README.md index e5dea85e9..303dcf424 100644 --- a/mods/PLAYER/mcl_skins/README.md +++ b/mods/PLAYER/mcl_skins/README.md @@ -31,11 +31,11 @@ Coloring only works for "base", "bottom, "top", and "hair". `preview_rotation` A table containing properties x and y. x and y represent the x and y rotation of the item preview. -`alex` -If set to true the item will be default for female character. +`template2` +If set to true the item will be default for female template. -`steve` -If set to true the item will be default for male character. +`template1` +If set to true the item will be default for male template. `rank` This property is used to change the application order of the skin item when applied to a player. @@ -60,10 +60,17 @@ headwear: 80 Lower ranks are applied to the player first and can thus be covered by higher rank items. -### `mcl_skins.show_formspec(player)` +### `mcl_skins.show_formspec(player, active_tab, page_num)` Show the skin configuration screen. + `player` is a player ObjectRef. +`active_tab` is the tab that will be displayed. This parameter is optional. +Can be one of: "arm", "base", "footwear", "eye", "mouth", "bottom", "top", "hair", "headwear" + +`page_num` The page number to display of there are multiple pages of items. +This parameter is optional. Must be a number. If it is not a valid page number the closest page number will be shown. + ### `mcl_skins.get_skin_list()` This function is used by mods that want a list of skins to register nodes that use the player skin as a texture. Returns an array of tables containing information about each skin. diff --git a/mods/PLAYER/mcl_skins/edit_skin.lua b/mods/PLAYER/mcl_skins/edit_skin.lua index 6973a1b6e..706c08461 100644 --- a/mods/PLAYER/mcl_skins/edit_skin.lua +++ b/mods/PLAYER/mcl_skins/edit_skin.lua @@ -1,5 +1,6 @@ local S = minetest.get_translator("mcl_skins") local color_to_string = minetest.colorspec_to_colorstring +local EDIT_SKIN_KEY = -1 -- The key used for edit skin in the mcl_skins.simple_skins table mcl_skins = { simple_skins = {}, @@ -19,8 +20,8 @@ mcl_skins = { headwear = S("Headwears"), skin = S("Skins"), }, - steve = {}, -- Stores skin values for Steve skin - alex = {}, -- Stores skin values for Alex skin + template1 = {}, -- Stores edit skin values for template1 + template2 = {}, -- Stores edit skin values for template2 base = {}, -- List of base textures -- Base color is separate to keep the number of junk nodes registered in check @@ -59,12 +60,12 @@ mcl_skins = { function mcl_skins.register_item(item) assert(mcl_skins[item.type], "Skin item type " .. item.type .. " does not exist.") local texture = item.texture or "blank.png" - if item.steve then - mcl_skins.steve[item.type] = texture + if item.template1 then + mcl_skins.template1[item.type] = texture end - if item.alex then - mcl_skins.alex[item.type] = texture + if item.template2 then + mcl_skins.template2[item.type] = texture end table.insert(mcl_skins[item.type], texture) @@ -96,7 +97,13 @@ end minetest.register_chatcommand("skin", { description = S("Open skin configuration screen."), privs = {}, - func = function(name, param) mcl_skins.show_formspec(minetest.get_player_by_name(name)) end + func = function(name, param) + local player = minetest.get_player_by_name(name) + local formspec_data = mcl_skins.player_formspecs[player] + local active_tab = formspec_data.active_tab + local page_num = formspec_data.page_num + mcl_skins.show_formspec(player, active_tab, page_num) + end }) function mcl_skins.compile_skin(skin) @@ -165,9 +172,9 @@ minetest.register_on_joinplayer(function(player) mcl_skins.player_skins[player] = skin else if math.random() > 0.5 then - skin = table.copy(mcl_skins.steve) + skin = table.copy(mcl_skins.template1) else - skin = table.copy(mcl_skins.alex) + skin = table.copy(mcl_skins.template2) end mcl_skins.player_skins[player] = skin end @@ -193,11 +200,24 @@ minetest.register_on_leaveplayer(function(player) mcl_skins.player_formspecs[player] = nil end) -function mcl_skins.show_formspec(player) +local function calculate_page_count(tab) + if tab == "skin" then + return math.ceil((#mcl_skins.simple_skins + 2) / 8) + elseif mcl_skins[tab] then + return math.ceil(#mcl_skins[tab] / 16) + end + return 1 +end + +function mcl_skins.show_formspec(player, active_tab, page_num) local formspec_data = mcl_skins.player_formspecs[player] local skin = mcl_skins.player_skins[player] - local active_tab = formspec_data.active_tab - local page_num = formspec_data.page_num + formspec_data.active_tab = active_tab + + local page_count = calculate_page_count(active_tab) + if page_num < 1 then page_num = 1 end + if page_num > page_count then page_num = page_count end + formspec_data.page_num = page_num local formspec = "formspec_version[3]size[14.2,11]" @@ -238,12 +258,12 @@ function mcl_skins.show_formspec(player) local skin = table.copy(skin) local simple_skins_id = skin.simple_skins_id skin.simple_skins_id = nil - mcl_skins.simple_skins[-1] = { + mcl_skins.simple_skins[EDIT_SKIN_KEY] = { slim_arms = skin.slim_arms, texture = mcl_skins.compile_skin(skin), } simple_skins_id = simple_skins_id or - mcl_skins.simple_skins[-1].texture + mcl_skins.simple_skins[EDIT_SKIN_KEY].texture for i = page_start, page_end do local skin = mcl_skins.simple_skins[i] @@ -269,22 +289,22 @@ function mcl_skins.show_formspec(player) "button[" .. x .. "," .. y .. ";1.5,3;" .. i .. ";]" end - if page_start == -1 then + if page_start == EDIT_SKIN_KEY then formspec = formspec .. "image[4.85,1;0.8,0.8;mcl_skins_button.png]" end elseif active_tab == "template" then formspec = formspec .. "model[5,2;2,3;player_mesh;mcl_armor_character.b3d;" .. - mcl_skins.compile_skin(mcl_skins.steve) .. + mcl_skins.compile_skin(mcl_skins.template1) .. ",blank.png,blank.png;0,180;false;true;0,0]" .. - "button[5,5.2;2,0.8;steve;" .. S("Select") .. "]" .. + "button[5,5.2;2,0.8;template1;" .. S("Select") .. "]" .. "model[7.5,2;2,3;player_mesh;mcl_armor_character_female.b3d;" .. - mcl_skins.compile_skin(mcl_skins.alex) .. + mcl_skins.compile_skin(mcl_skins.template2) .. ",blank.png,blank.png;0,180;false;true;0,0]" .. - "button[7.5,5.2;2,0.8;alex;" .. S("Select") .. "]" + "button[7.5,5.2;2,0.8;template2;" .. S("Select") .. "]" elseif mcl_skins[active_tab] then formspec = formspec .. @@ -400,13 +420,6 @@ function mcl_skins.show_formspec(player) end end - local page_count = 1 - if mcl_skins[active_tab] then - page_count = math.ceil(#mcl_skins[active_tab] / 16) - elseif active_tab == "skin" then - page_count = math.ceil((#mcl_skins.simple_skins + 2) / 8) - end - if page_num > 1 then formspec = formspec .. "image_button[4.5,6.7;1,1;mcl_skins_arrow.png^[transformFX;previous_page;]" @@ -427,16 +440,17 @@ function mcl_skins.show_formspec(player) end minetest.register_on_player_receive_fields(function(player, formname, fields) + local formspec_data = mcl_skins.player_formspecs[player] + local active_tab = formspec_data.active_tab + local page_num = formspec_data.page_num + if fields.__mcl_skins then - mcl_skins.show_formspec(player) + mcl_skins.show_formspec(player, active_tab, page_num) return false end if formname ~= "mcl_skins:skins" then return false end - local formspec_data = mcl_skins.player_formspecs[player] - local active_tab = formspec_data.active_tab - -- Cancel formspec resend after scrollbar move if formspec_data.form_send_job then formspec_data.form_send_job:cancel() @@ -448,23 +462,21 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) return true end - if fields.alex then - mcl_skins.player_skins[player] = table.copy(mcl_skins.alex) + if fields.template2 then + mcl_skins.player_skins[player] = table.copy(mcl_skins.template2) mcl_skins.update_player_skin(player) - mcl_skins.show_formspec(player) + mcl_skins.show_formspec(player, active_tab, page_num) return true - elseif fields.steve then - mcl_skins.player_skins[player] = table.copy(mcl_skins.steve) + elseif fields.template1 then + mcl_skins.player_skins[player] = table.copy(mcl_skins.template1) mcl_skins.update_player_skin(player) - mcl_skins.show_formspec(player) + mcl_skins.show_formspec(player, active_tab, page_num) return true end for i, tab in pairs(mcl_skins.tab_names) do if fields[tab] then - formspec_data.active_tab = tab - formspec_data.page_num = 1 - mcl_skins.show_formspec(player) + mcl_skins.show_formspec(player, tab, 1) return true end end @@ -473,28 +485,12 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if not skin then return true end if fields.next_page then - local page_num = formspec_data.page_num page_num = page_num + 1 - - local page_count - if active_tab == "skin" then - page_count = math.ceil((#mcl_skins.simple_skins + 2) / 8) - else - page_count = math.ceil(#mcl_skins[active_tab] / 16) - end - - if page_num > page_count then - page_num = page_count - end - formspec_data.page_num = page_num - mcl_skins.show_formspec(player) + mcl_skins.show_formspec(player, active_tab, page_num) return true elseif fields.previous_page then - local page_num = formspec_data.page_num page_num = page_num - 1 - if page_num < 1 then page_num = 1 end - formspec_data.page_num = page_num - mcl_skins.show_formspec(player) + mcl_skins.show_formspec(player, active_tab, page_num) return true end @@ -505,7 +501,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) skin.slim_arms = true end mcl_skins.update_player_skin(player) - mcl_skins.show_formspec(player) + mcl_skins.show_formspec(player, active_tab, page_num) return true end @@ -530,7 +526,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if player and player:is_player() then skin[active_tab .. "_color"] = color mcl_skins.update_player_skin(player) - mcl_skins.show_formspec(player) + mcl_skins.show_formspec(player, active_tab, page_num) formspec_data.form_send_job = nil end end) @@ -549,14 +545,14 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if field and active_tab == "skin" then local index = tonumber(field) index = index and math.floor(index) or 0 - mcl_skins.simple_skins[-1].texture = nil + mcl_skins.simple_skins[EDIT_SKIN_KEY].texture = nil if #mcl_skins.simple_skins > 0 and - index >= -1 and index <= #mcl_skins.simple_skins + index >= EDIT_SKIN_KEY and index <= #mcl_skins.simple_skins then skin.simple_skins_id = mcl_skins.simple_skins[index].texture mcl_skins.update_player_skin(player) - mcl_skins.show_formspec(player) + mcl_skins.show_formspec(player, active_tab, page_num) end return true end @@ -568,7 +564,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) then skin[active_tab] = field mcl_skins.update_player_skin(player) - mcl_skins.show_formspec(player) + mcl_skins.show_formspec(player, active_tab, page_num) return true end @@ -579,7 +575,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if color and color >= 0 and color <= 0xffffffff then skin[active_tab .. "_color"] = color mcl_skins.update_player_skin(player) - mcl_skins.show_formspec(player) + mcl_skins.show_formspec(player, active_tab, page_num) return true end end @@ -599,17 +595,17 @@ local function init() for _, item in pairs(json) do mcl_skins.register_item(item) end - mcl_skins.steve.base_color = mcl_skins.base_color[2] - mcl_skins.steve.hair_color = 0xff5d473b - mcl_skins.steve.top_color = 0xff993535 - mcl_skins.steve.bottom_color = 0xff644939 - mcl_skins.steve.slim_arms = false + mcl_skins.template1.base_color = mcl_skins.base_color[2] + mcl_skins.template1.hair_color = 0xff5d473b + mcl_skins.template1.top_color = 0xff993535 + mcl_skins.template1.bottom_color = 0xff644939 + mcl_skins.template1.slim_arms = false - mcl_skins.alex.base_color = mcl_skins.base_color[1] - mcl_skins.alex.hair_color = 0xff715d57 - mcl_skins.alex.top_color = 0xff346840 - mcl_skins.alex.bottom_color = 0xff383532 - mcl_skins.alex.slim_arms = true + mcl_skins.template2.base_color = mcl_skins.base_color[1] + mcl_skins.template2.hair_color = 0xff715d57 + mcl_skins.template2.top_color = 0xff346840 + mcl_skins.template2.bottom_color = 0xff383532 + mcl_skins.template2.slim_arms = true mcl_skins.register_simple_skin({ index = 0, diff --git a/mods/PLAYER/mcl_skins/list.json b/mods/PLAYER/mcl_skins/list.json index 8ee0aa830..dc7afbfe1 100644 --- a/mods/PLAYER/mcl_skins/list.json +++ b/mods/PLAYER/mcl_skins/list.json @@ -2,8 +2,8 @@ { "type": "footwear", "texture": "mcl_skins_footwear_1.png", - "steve": true, - "alex": true, + "template1": true, + "template2": true, "rank": 55 }, { @@ -20,12 +20,12 @@ { "type": "eye", "texture": "mcl_skins_eye_1.png", - "alex": true + "template2": true }, { "type": "eye", "texture": "mcl_skins_eye_2.png", - "steve": true + "template1": true }, { "type": "eye", @@ -50,7 +50,7 @@ { "type": "mouth", "texture": "mcl_skins_mouth_1.png", - "steve": true + "template1": true }, { "type": "mouth", @@ -78,19 +78,19 @@ }, { "type": "mouth", - "alex": true + "template1": true }, { "type": "hair", "texture": "mcl_skins_hair_1.png", "mask": "mcl_skins_hair_1_mask.png", - "alex": true + "template2": true }, { "type": "hair", "texture": "mcl_skins_hair_2.png", "mask": "mcl_skins_hair_2_mask.png", - "steve": true + "template1": true }, { "type": "hair", @@ -147,7 +147,7 @@ { "type": "headwear", "texture": "mcl_skins_headwear_2.png", - "alex": true + "template2": true }, { "type": "headwear", @@ -175,14 +175,14 @@ }, { "type": "headwear", - "steve": true + "template1": true }, { "type": "bottom", "texture": "mcl_skins_bottom_1.png", "mask": "mcl_skins_bottom_1_mask.png", - "steve": true, - "alex": true + "template1": true, + "template2": true }, { "type": "bottom", @@ -209,8 +209,8 @@ "type": "top", "texture": "mcl_skins_top_1.png", "mask": "mcl_skins_top_1_mask.png", - "steve": true, - "alex": true + "template1": true, + "template2": true }, { "type": "top", @@ -261,7 +261,7 @@ "type": "base", "texture": "mcl_skins_base_1.png", "mask": "mcl_skins_base_1_mask.png", - "steve": true, - "alex": true + "template1": true, + "template2": true } ] diff --git a/textures/player.png b/textures/player.png new file mode 100644 index 0000000000000000000000000000000000000000..863991b34c856cfa51c82865f56faf658515f816 GIT binary patch literal 419 zcmeAS@N?(olHy`uVBq!ia0vp^0zj<5!3-pI!a4o{Db50q$YKTtZeb8+WSBKa0w~B{ z;_2(k{*;NEL0R3#-s~4pC@{b$#1%-Zit(w63m7U&m?}#;=_|XLsCeqDgg6>RI~r!I z8fN?1R>gTXWdyhAnangbo!Oeb*wJQjdf29_5`4OSv7WG0nN!9Tr7ai3oo81qo^5dSTI*Yp-NxT{7ye#Tq1S)>(;U%dyH6iA zHE!K~wW>HcW9{}{GfRbu2deTJ83jeAHBIE1%PN?C=0vbP0 Hl+XkKs6Cjr literal 0 HcmV?d00001 diff --git a/textures/player_back.png b/textures/player_back.png new file mode 100644 index 0000000000000000000000000000000000000000..39e143c3b7116f059245c0d0def8f7b108b5d8f2 GIT binary patch literal 307 zcmeAS@N?(olHy`uVBq!ia0vp^0zj<5!3-pI!a4o{Da!z#5LX~=s3;NQXyBx;9Oq-% zqGvMG)O4|NZs+FHR5J-p8L8Z?qJOObqDkh$cw0`EMQ<@efNZoYv)5g znH$Gzc)0G|aX84A{@_6D`l^Qq7HY_FFz~T3{Aavx?=YJu%WpN%%?zHdelF{r5}E)R C+i Date: Sat, 27 May 2023 01:42:59 +0000 Subject: [PATCH 138/155] Fix translations for ru, pl, ja, and fr --- mods/HUD/mcl_achievements/locale/mcl_achievements.fr.tr | 2 +- mods/HUD/mcl_achievements/locale/mcl_achievements.ja.tr | 2 +- mods/HUD/mcl_achievements/locale/mcl_achievements.pl.tr | 2 +- mods/HUD/mcl_achievements/locale/mcl_achievements.ru.tr | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mods/HUD/mcl_achievements/locale/mcl_achievements.fr.tr b/mods/HUD/mcl_achievements/locale/mcl_achievements.fr.tr index c3fe0fb00..95800d5e9 100644 --- a/mods/HUD/mcl_achievements/locale/mcl_achievements.fr.tr +++ b/mods/HUD/mcl_achievements/locale/mcl_achievements.fr.tr @@ -1,5 +1,5 @@ # textdomain:mcl_achievements -Aquire Hardware=Acquérir du matériel +Acquire Hardware=Acquérir du matériel Bake Bread=Faire du pain Benchmarking=Fabriquer Cow Tipper=Chevaucher une vache diff --git a/mods/HUD/mcl_achievements/locale/mcl_achievements.ja.tr b/mods/HUD/mcl_achievements/locale/mcl_achievements.ja.tr index 2e67d019e..bd86186e7 100644 --- a/mods/HUD/mcl_achievements/locale/mcl_achievements.ja.tr +++ b/mods/HUD/mcl_achievements/locale/mcl_achievements.ja.tr @@ -1,5 +1,5 @@ # textdomain:mcl_achievements -Aquire Hardware=金属を入手 +Acquire Hardware=金属を入手 Bake Bread=パンを焼く Benchmarking=土台作り Cow Tipper=牛転がし diff --git a/mods/HUD/mcl_achievements/locale/mcl_achievements.pl.tr b/mods/HUD/mcl_achievements/locale/mcl_achievements.pl.tr index 78ab53f82..ccb21a06f 100644 --- a/mods/HUD/mcl_achievements/locale/mcl_achievements.pl.tr +++ b/mods/HUD/mcl_achievements/locale/mcl_achievements.pl.tr @@ -1,5 +1,5 @@ # textdomain:mcl_achievements -Aquire Hardware=Zdobądź narzędzie +Acquire Hardware=Zdobądź narzędzie Bake Bread=Upiecz chleb Benchmarking=Rzemieślnictwo Cow Tipper=Raz krowie śmierć diff --git a/mods/HUD/mcl_achievements/locale/mcl_achievements.ru.tr b/mods/HUD/mcl_achievements/locale/mcl_achievements.ru.tr index 0db2ae99d..9bc23f6be 100644 --- a/mods/HUD/mcl_achievements/locale/mcl_achievements.ru.tr +++ b/mods/HUD/mcl_achievements/locale/mcl_achievements.ru.tr @@ -1,5 +1,5 @@ # textdomain:mcl_achievements -Aquire Hardware=Куй Железо +Acquire Hardware=Куй Железо Bake Bread=Хлеб всему голова Benchmarking=Верстак Cow Tipper=Кожа да кости From 06077d16335f2d0b1095e10c314e5def51339eef Mon Sep 17 00:00:00 2001 From: megustanlosfrijoles Date: Wed, 31 May 2023 21:22:49 +0000 Subject: [PATCH 139/155] Spanish translations (#3753) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tell us about your pull request! Reference related issues, if necessary ### Testing Tell us how to test your changes! Co-authored-by: José Muñoz Reviewed-on: https://git.minetest.land/MineClone2/MineClone2/pulls/3753 Reviewed-by: ancientmarinerdev Co-authored-by: megustanlosfrijoles Co-committed-by: megustanlosfrijoles --- .../mcl_falling_nodes/locale/mcl_falling_nodes.es.tr | 3 +++ mods/ITEMS/mcl_bows/locale/mcl_bows.es.tr | 9 ++++++++- mods/ITEMS/mcl_cake/locale/mcl_cake.es.tr | 2 ++ mods/ITEMS/mcl_doors/locale/mcl_doors.es.tr | 4 ++-- mods/ITEMS/mcl_tnt/locale/mcl_tnt.es.tr | 2 ++ 5 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 mods/ENTITIES/mcl_falling_nodes/locale/mcl_falling_nodes.es.tr diff --git a/mods/ENTITIES/mcl_falling_nodes/locale/mcl_falling_nodes.es.tr b/mods/ENTITIES/mcl_falling_nodes/locale/mcl_falling_nodes.es.tr new file mode 100644 index 000000000..9bf17e1bb --- /dev/null +++ b/mods/ENTITIES/mcl_falling_nodes/locale/mcl_falling_nodes.es.tr @@ -0,0 +1,3 @@ +# textdomain: mcl_falling_nodes +@1 was smashed by a falling anvil.=@1 fue aplastado por un yunque. +@1 was smashed by a falling block.=@1 fue aplastado por un bloque. diff --git a/mods/ITEMS/mcl_bows/locale/mcl_bows.es.tr b/mods/ITEMS/mcl_bows/locale/mcl_bows.es.tr index 539afdcf0..4ed4d8640 100644 --- a/mods/ITEMS/mcl_bows/locale/mcl_bows.es.tr +++ b/mods/ITEMS/mcl_bows/locale/mcl_bows.es.tr @@ -8,4 +8,11 @@ Bow=Arco Bows are ranged weapons to shoot arrows at your foes.=Los arcos son armas a distancia para disparar flechas a tus enemigos. The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 20% of a critical hit, dealing 10 damage instead.=La velocidad y el daño de la flecha aumentan cuanto más tiempo tenses. El daño regular de la flecha está entre 1 y 9. A plena carga, también hay un 20% de un golpe crítico, que en vez de eso causa 10 de daño. To use the bow, you first need to have at least one arrow anywhere in your inventory (unless in Creative Mode). Hold down the right mouse button to charge, release to shoot.=Para usar el arco, primero debes de tener al menos una flecha en cualquier parte de su inventario (a menos que esté en modo creativo). Mantenga presionado el botón derecho del mouse para tensar, suelte para disparar. -Bow=Arco \ No newline at end of file +Bow=Arco +Ammunition=Munición +Damage from bow: 1-10=Daño con arco: 1-10 +Damage from dispenser: 3=Daño por dispendsador: 3 +Launches arrows=Lanza flechas +Crossbow=Ballesta +Crossbows are ranged weapons to shoot arrows at your foes.=Las ballestas son armas a distancia para disparar flechas a tus enemigos. +To use the crossbow, you first need to have at least one arrow anywhere in your inventory (unless in Creative Mode). Hold down the right mouse button to charge, release to shoot.=Para usar la ballesta, primero debes tener por lo menos una flecha en cualquier raunura de tu inventario (excepto en modo creativo).Mantén presionado el botón derecho del ratón para cargar, suelta para disparar. diff --git a/mods/ITEMS/mcl_cake/locale/mcl_cake.es.tr b/mods/ITEMS/mcl_cake/locale/mcl_cake.es.tr index 261d581e1..3cec57b8b 100644 --- a/mods/ITEMS/mcl_cake/locale/mcl_cake.es.tr +++ b/mods/ITEMS/mcl_cake/locale/mcl_cake.es.tr @@ -8,3 +8,5 @@ Cake (4 Slices Left)=Tarta (Quedan 4 trozos) Cake (3 Slices Left)=Tarta (Quedan 3 trozos) Cake (2 Slices Left)=Tarta (Quedan 2 trozos) Cake (1 Slice Left)=Tarta (Queda 1 trozo) +With 7 tasty slices!=¡Con 7 deliciosas rebanadas! +Hunger points: +@1 per slice=Puntos de hambre: +@1 por rebanada diff --git a/mods/ITEMS/mcl_doors/locale/mcl_doors.es.tr b/mods/ITEMS/mcl_doors/locale/mcl_doors.es.tr index 8b22d354c..eca8efab4 100644 --- a/mods/ITEMS/mcl_doors/locale/mcl_doors.es.tr +++ b/mods/ITEMS/mcl_doors/locale/mcl_doors.es.tr @@ -20,5 +20,5 @@ Wooden trapdoors are horizontal barriers which can be opened and closed by hand To open or close the trapdoor, rightclick it or send a redstone signal to it.=Para abrir o cerrar la trampilla, haga clic derecho o envíele una señal de redstone. Iron Trapdoor=Trampilla de hierro Iron trapdoors are horizontal barriers which can only be opened and closed by redstone signals, but not by hand. They occupy the upper or lower part of a block, depending on how they have been placed. When open, they can be climbed like a ladder.=Las trampillas de hierro son barreras horizontales que solo pueden abrirse y cerrarse mediante señales de redstone, no a mano. Ocupan la parte superior o inferior de un bloque, dependiendo de cómo se hayan colocado. Cuando están abiertos, se pueden subir como una escalera. -Openable by players and redstone power=Puede ser abierta por jugadores y señales de redstone -Openable by redstone power=Puede ser abierta por señales de redstone +Openable by players and redstone power=Puede ser abierta por jugadores y energía de redstone +Openable by redstone power=Puede ser abierta por energía de redstone diff --git a/mods/ITEMS/mcl_tnt/locale/mcl_tnt.es.tr b/mods/ITEMS/mcl_tnt/locale/mcl_tnt.es.tr index 81d30dcd7..a226b5bcb 100644 --- a/mods/ITEMS/mcl_tnt/locale/mcl_tnt.es.tr +++ b/mods/ITEMS/mcl_tnt/locale/mcl_tnt.es.tr @@ -3,3 +3,5 @@ TNT=Dinamita An explosive device. When it explodes, it will hurt living beings and destroy blocks around it. TNT has an explosion radius of @1. With a small chance, blocks may drop as an item (as if being mined) rather than being destroyed. TNT can be ignited by tools, explosions, fire, lava and redstone signals.=Un artefacto explosivo. Cuando explota, dañará a los seres vivos y destruirá los bloques a su alrededor. La dinamita tiene un radio de explosión de @1. Con una pequeña posibilidad, los bloques pueden caer como un elemento (como si se extrajera) en lugar de ser destruidos. La dinamita puede encenderse con herramientas, explosiones, fuego, lava y señales de redstone. Place the TNT and ignite it with one of the methods above. Quickly get in safe distance. The TNT will start to be affected by gravity and explodes in 4 seconds.=Coloque el dinamita y enciéndalo con uno de los métodos anteriores. Aléjese rápidamente a una distancia segura. La dinamita comenzará a verse afectada por la gravedad y explotará en 4 segundos. +Ignited by tools, explosions, fire, lava, redstone power=Encendida por herramientas, explosiones, fuego, lava, y energía de redstone +Explosion radius: @1=Radio de exposión: @1 From adee1a49afc306f48554c82f3fa0f24a7dbfc74f Mon Sep 17 00:00:00 2001 From: SmokeyDope Date: Tue, 30 May 2023 13:14:02 +0000 Subject: [PATCH 140/155] Add max_hear_distance flag to composter sounds --- mods/ITEMS/mcl_composters/init.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_composters/init.lua b/mods/ITEMS/mcl_composters/init.lua index 51c887531..08125cbbe 100644 --- a/mods/ITEMS/mcl_composters/init.lua +++ b/mods/ITEMS/mcl_composters/init.lua @@ -76,7 +76,7 @@ local function composter_add_item(pos, node, player, itemstack, pointed_thing) if chance > 0 then if not is_creative_enabled(player:get_player_name()) then itemstack:take_item() - minetest.sound_play({name="default_gravel_dug", pos=pos, gain=1}, true) + minetest.sound_play({name="default_gravel_dug", pos=pos, gain=1, max_hear_distance=16}, true) end -- calculate leveling up chance local rand = math.random(0,100) @@ -92,7 +92,7 @@ local function composter_add_item(pos, node, player, itemstack, pointed_thing) level = "ready" end swap_node(pos, {name = "mcl_composters:composter_" .. level}) - minetest.sound_play({name="default_grass_footstep", pos=pos, gain=0.4}, true) + minetest.sound_play({name="default_grass_footstep", pos=pos, gain=0.4, max_hear_distance=16}, true) -- a full composter becomes ready for harvest after one second -- the block will get updated by the node timer callback set in node reg def if level == 7 then @@ -115,7 +115,7 @@ end local function composter_ready(pos) swap_node(pos, {name = "mcl_composters:composter_ready"}) -- maybe spawn particles again? - minetest.sound_play({name="default_dig_snappy", pos=above, gain=1}, true) + minetest.sound_play({name="default_dig_snappy", pos=above, gain=1, max_hear_distance=16}, true) return false end From 428ae9ac0db1bbdd26ca99d5f7beb775a311ddfa Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Wed, 31 May 2023 23:08:31 +0100 Subject: [PATCH 141/155] Fix positional sounds based on mt docs. --- mods/ITEMS/mcl_composters/init.lua | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_composters/init.lua b/mods/ITEMS/mcl_composters/init.lua index 08125cbbe..223771148 100644 --- a/mods/ITEMS/mcl_composters/init.lua +++ b/mods/ITEMS/mcl_composters/init.lua @@ -76,7 +76,10 @@ local function composter_add_item(pos, node, player, itemstack, pointed_thing) if chance > 0 then if not is_creative_enabled(player:get_player_name()) then itemstack:take_item() - minetest.sound_play({name="default_gravel_dug", pos=pos, gain=1, max_hear_distance=16}, true) + minetest.sound_play({name="default_gravel_dug", gain=1, max_hear_distance=16}, { + pos = pos, + max_hear_distance = 32, + }, true) end -- calculate leveling up chance local rand = math.random(0,100) @@ -92,7 +95,11 @@ local function composter_add_item(pos, node, player, itemstack, pointed_thing) level = "ready" end swap_node(pos, {name = "mcl_composters:composter_" .. level}) - minetest.sound_play({name="default_grass_footstep", pos=pos, gain=0.4, max_hear_distance=16}, true) + minetest.sound_play({name="default_grass_footstep", gain=0.4}, { + pos = pos, + gain= 0.4, + max_hear_distance = 16, + }, true) -- a full composter becomes ready for harvest after one second -- the block will get updated by the node timer callback set in node reg def if level == 7 then @@ -115,7 +122,10 @@ end local function composter_ready(pos) swap_node(pos, {name = "mcl_composters:composter_ready"}) -- maybe spawn particles again? - minetest.sound_play({name="default_dig_snappy", pos=above, gain=1, max_hear_distance=16}, true) + minetest.sound_play({name="default_dig_snappy", gain=1}, { + pos = pos, + max_hear_distance = 16, + }, true) return false end From 90842c5f251943a4bf21ff64c63317b6a728c39c Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Wed, 31 May 2023 23:18:15 +0100 Subject: [PATCH 142/155] Fixed slight error. --- mods/ITEMS/mcl_composters/init.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_composters/init.lua b/mods/ITEMS/mcl_composters/init.lua index 223771148..d60422afd 100644 --- a/mods/ITEMS/mcl_composters/init.lua +++ b/mods/ITEMS/mcl_composters/init.lua @@ -76,9 +76,9 @@ local function composter_add_item(pos, node, player, itemstack, pointed_thing) if chance > 0 then if not is_creative_enabled(player:get_player_name()) then itemstack:take_item() - minetest.sound_play({name="default_gravel_dug", gain=1, max_hear_distance=16}, { + minetest.sound_play({name="default_gravel_dug", gain=1}, { pos = pos, - max_hear_distance = 32, + max_hear_distance = 16, }, true) end -- calculate leveling up chance From ae32ce4a0a41dde8d07d181b3e39a748e9a6ea31 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 29 May 2023 19:26:43 +0100 Subject: [PATCH 143/155] Split hostile and non-hostile mob caps --- mods/ENTITIES/mcl_mobs/spawning.lua | 105 ++++++++++++++++++---------- settingtypes.txt | 8 ++- 2 files changed, 76 insertions(+), 37 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index adff1a918..4a9f6d736 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -27,8 +27,11 @@ local table_remove = table.remove local pairs = pairs local LOGGING_ON = minetest.settings:get_bool("mcl_logging_mobs_spawning", false) -local function mcl_log (message) +local function mcl_log (message, property) if LOGGING_ON then + if property then + message = message .. ": " .. dump(property) + end mcl_util.mcl_log (message, "[Mobs spawn]", true) end end @@ -52,7 +55,7 @@ local MOB_CAP_INNER_RADIUS = 32 local aoc_range = 136 local MISSING_CAP_DEFAULT = 15 -local MOBS_CAP_CLOSE = 5 +local MOBS_CAP_CLOSE = 10 local SPAWN_MAPGEN_LIMIT = mcl_vars.mapgen_limit - 150 @@ -63,6 +66,8 @@ local mob_cap = { water = tonumber(minetest.settings:get("mcl_mob_cap_water")) or 8, water_ambient = tonumber(minetest.settings:get("mcl_mob_cap_water_ambient")) or 20, --currently unused player = tonumber(minetest.settings:get("mcl_mob_cap_player")) or 75, + global_hostile = tonumber(minetest.settings:get("mcl_mob_cap_hostile")) or 300, + global_non_hostile = tonumber(minetest.settings:get("mcl_mob_cap_non_hostile")) or 300, total = tonumber(minetest.settings:get("mcl_mob_cap_total")) or 500, } @@ -340,15 +345,32 @@ local function count_mobs_all(categorise_by, pos) end local function count_mobs_total_cap(mob_type) + local total = 0 local num = 0 + local hostile = 0 + local non_hostile = 0 for _,l in pairs(minetest.luaentities) do if l.is_mob then - if ( mob_type == nil or l.type == mob_type ) and l.can_despawn and not l.nametag then + total = total + 1 + local nametagged = l.nametag and l.nametag ~= "" + if ( mob_type == nil or l.type == mob_type ) and not nametagged then + if l.spawn_class == "hostile" then + hostile = hostile + 1 + else + non_hostile = non_hostile + 1 + end num = num + 1 + else + mcl_log("l.nametag", l.name) + mcl_log("l.nametag", l.nametag) + end end end - return num + mcl_log("Total mobs", total) + mcl_log("hostile", hostile) + mcl_log("non_hostile", non_hostile) + return num, non_hostile, hostile end local function output_mob_stats(mob_counts, total_mobs, chat_display) @@ -704,13 +726,13 @@ local function spawn_check(pos, spawn_def) --mcl_log("Level 3 spawn check passed") return true else - mcl_log("Spawn check level 3 failed") + --mcl_log("Spawn check level 3 failed") end else - mcl_log("Spawn check level 2 failed") + --mcl_log("Spawn check level 2 failed") end else - mcl_log("Spawn check level 1 failed") + --mcl_log("Spawn check level 1 failed") end return false end @@ -831,7 +853,7 @@ if mobs_spawn then -- Get pos to spawn, x and z are randomised, y is range - local function mob_cap_space (pos, mob_type, mob_counts_close, mob_counts_wide) + local function mob_cap_space (pos, mob_type, mob_counts_close, mob_counts_wide, cap_space_hostile, cap_space_non_hostile) -- Some mob examples --type = "monster", spawn_class = "hostile", @@ -847,10 +869,20 @@ if mobs_spawn then mob_total_wide = 0 end - local cap_space_wide = type_cap - mob_total_wide - if cap_space_wide < 1 then - cap_space_wide = 0 + local cap_space_wide = math.max(type_cap - mob_total_wide, 0) + + local cap_space_available = 0 + if mob_type == "hostile" then + mcl_log("cap_space_global", cap_space_hostile) + cap_space_available = math.min(cap_space_hostile, cap_space_wide) + else + mcl_log("cap_space_global", cap_space_non_hostile) + cap_space_available = math.min(cap_space_non_hostile, cap_space_wide) end + mcl_log("mob_type", mob_type) + mcl_log("cap_space_wide", cap_space_wide) + --mcl_log("cap_space_available", cap_space_available) + local mob_total_close = mob_counts_close[mob_type] if not mob_total_close then @@ -858,12 +890,12 @@ if mobs_spawn then mob_total_close = 0 end - local cap_space_close = close_zone_cap - mob_total_close - if cap_space_close < 1 then - cap_space_close = 0 - end + local cap_space_close = math.max(close_zone_cap - mob_total_close, 0) + mcl_log("cap_space_close", cap_space_close) + + cap_space_available = math.min(cap_space_available, cap_space_close) + mcl_log("cap_space_available", cap_space_available) - --mcl_log("spawn_class: " .. spawn_class) if false and mob_type == "water" then mcl_log("mob_type: " .. mob_type .. " and pos: " .. minetest.pos_to_string(pos)) @@ -873,7 +905,7 @@ if mobs_spawn then mcl_log("cap_space_close: " .. cap_space_close) end - return cap_space_wide, cap_space_close + return cap_space_available end local function find_spawning_position(pos, max_times) @@ -884,7 +916,7 @@ if mobs_spawn then local y_min, y_max = decypher_limits(pos.y) - mcl_log("mapgen_limit: " .. SPAWN_MAPGEN_LIMIT) + --mcl_log("mapgen_limit: " .. SPAWN_MAPGEN_LIMIT) local i = 0 repeat local goal_pos = get_next_mob_spawn_pos(pos) @@ -916,7 +948,7 @@ if mobs_spawn then return spawning_position end - local function spawn_a_mob(pos) + local function spawn_a_mob(pos, cap_space_hostile, cap_space_non_hostile) --create a disconnected clone of the spawn dictionary, prevents memory leak local mob_library_worker_table = table_copy(spawn_dictionary) @@ -954,22 +986,20 @@ if mobs_spawn then if mob_def and mob_def.name and minetest.registered_entities[mob_def.name] then local mob_def_ent = minetest.registered_entities[mob_def.name] - --local mob_type = mob_def_ent.type - local mob_spawn_class = mob_def_ent.spawn_class + local mob_spawn_class = mob_def_ent.spawn_class --mcl_log("mob_spawn_class: " .. mob_spawn_class) - local cap_space_wide, cap_space_close = mob_cap_space (spawning_position, mob_spawn_class, mob_counts_close, mob_counts_wide) + local cap_space_available = mob_cap_space (spawning_position, mob_spawn_class, mob_counts_close, mob_counts_wide, cap_space_hostile, cap_space_non_hostile) - - if cap_space_close > 0 and cap_space_wide > 0 then + if cap_space_available > 0 then --mcl_log("Cap space available") -- Spawn caps for animals and water creatures fill up rapidly. Need to throttle this somewhat -- for performance and for early game challenge. We don't want to reduce hostiles though. local spawn_hostile = (mob_spawn_class == "hostile") local spawn_passive = (mob_spawn_class ~= "hostile") and math.random(100) < peaceful_percentage_spawned - -- or not hostile + --mcl_log("Spawn_passive: " .. tostring(spawn_passive)) --mcl_log("Spawn_hostile: " .. tostring(spawn_hostile)) @@ -1000,13 +1030,10 @@ if mobs_spawn then local group_min = mob_def_ent.spawn_in_group_min or 1 if not group_min then group_min = 1 end - local amount_to_spawn = math.random(group_min,spawn_in_group) - - if amount_to_spawn > cap_space_wide then - mcl_log("Spawning quantity: " .. amount_to_spawn) - mcl_log("Throttle amount to cap space: " .. cap_space_wide) - amount_to_spawn = cap_space_wide - end + local amount_to_spawn = math.random(group_min, spawn_in_group) + mcl_log("Spawning quantity: " .. amount_to_spawn) + amount_to_spawn = math.min(amount_to_spawn, cap_space_available) + mcl_log("throttled spawning quantity: " .. amount_to_spawn) if logging then minetest.log("action", "[mcl_mobs] A group of " ..amount_to_spawn .. " " .. mob_def.name .. " mob spawns on " ..minetest.get_node(vector.offset(spawning_position,0,-1,0)).name .." at " .. minetest.pos_to_string(spawning_position, 1)) @@ -1021,7 +1048,7 @@ if mobs_spawn then if spawned then --mcl_log("We have spawned") - mob_counts_close, mob_counts_wide, total_mobs = count_mobs_all("type", pos) + mob_counts_close, mob_counts_wide, total_mobs = count_mobs_all("spawn_class", pos) local new_spawning_position = find_spawning_position(pos, FIND_SPAWN_POS_RETRIES_SUCCESS_RESPIN) if new_spawning_position then mcl_log("Setting new spawning position") @@ -1034,7 +1061,7 @@ if mobs_spawn then --mcl_log("Spawn check failed") end else - mcl_log("Cap space full") + --mcl_log("Cap space full") end end @@ -1054,7 +1081,13 @@ if mobs_spawn then timer = 0 local players = get_connected_players() - local total_mobs = count_mobs_total_cap() + local total_mobs, total_non_hostile, total_hostile = count_mobs_total_cap() + + local cap_space_hostile = math.max(mob_cap.global_hostile - total_hostile, 0) + local cap_space_non_hostile = math.max(mob_cap.global_non_hostile - total_non_hostile, 0) + mcl_log("global cap_space_hostile", cap_space_hostile) + mcl_log("global cap_space_non_hostile", cap_space_non_hostile) + if total_mobs > mob_cap.total or total_mobs > #players * mob_cap.player then minetest.log("action","[mcl_mobs] global mob cap reached. no cycle spawning.") return @@ -1065,7 +1098,7 @@ if mobs_spawn then local dimension = mcl_worlds.pos_to_dimension(pos) -- ignore void and unloaded area if dimension ~= "void" and dimension ~= "default" then - spawn_a_mob(pos) + spawn_a_mob(pos, cap_space_hostile, cap_space_non_hostile) end end end) diff --git a/settingtypes.txt b/settingtypes.txt index 00235e79d..fde9582d8 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -130,9 +130,15 @@ mcl_mob_peaceful_group_percentage_spawned (Peaceful group percentage) int 15 0 1 #Percentage of hostile spawn attempts that are group spawns (default:20) mcl_mob_hostile_group_percentage_spawned (Hostile group percentage) int 20 0 100 -#Maximum amount mobs (default:500) +#Maximum amount of mobs (default:500) mcl_mob_cap_total (Global mob cap) int 500 0 2048 +#Maximum amount of hostile mobs (default:300) +mcl_mob_cap_hostile (Global hostile mob cap) int 300 0 2048 + +#Maximum amount of non-hostile mobs (default:300) +mcl_mob_cap_non_hostile (Global non-hostile mob cap) int 300 0 2048 + #Maximum amount of mobs per player (default:75) mcl_mob_cap_player (Mob cap per player) int 75 0 2048 From 4d3e8e25e51527a09dc8b3a59f16340cf5a0908b Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 29 May 2023 20:06:03 +0100 Subject: [PATCH 144/155] Add water_ambient cap --- mods/ENTITIES/mobs_mc/cod.lua | 2 +- mods/ENTITIES/mobs_mc/salmon.lua | 2 +- mods/ENTITIES/mobs_mc/tropical_fish.lua | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/cod.lua b/mods/ENTITIES/mobs_mc/cod.lua index 9e8b62269..656b2c14c 100644 --- a/mods/ENTITIES/mobs_mc/cod.lua +++ b/mods/ENTITIES/mobs_mc/cod.lua @@ -31,7 +31,7 @@ local S = minetest.get_translator(minetest.get_current_modname()) local cod = { type = "animal", - spawn_class = "water", + spawn_class = "water_ambient", can_despawn = true, passive = true, hp_min = 3, diff --git a/mods/ENTITIES/mobs_mc/salmon.lua b/mods/ENTITIES/mobs_mc/salmon.lua index 19c935389..f8e0c4e02 100644 --- a/mods/ENTITIES/mobs_mc/salmon.lua +++ b/mods/ENTITIES/mobs_mc/salmon.lua @@ -11,7 +11,7 @@ local S = minetest.get_translator(minetest.get_current_modname()) local salmon = { type = "animal", - spawn_class = "water", + spawn_class = "water_ambient", can_despawn = true, passive = true, hp_min = 3, diff --git a/mods/ENTITIES/mobs_mc/tropical_fish.lua b/mods/ENTITIES/mobs_mc/tropical_fish.lua index 702c692b8..79b32bb8b 100644 --- a/mods/ENTITIES/mobs_mc/tropical_fish.lua +++ b/mods/ENTITIES/mobs_mc/tropical_fish.lua @@ -59,7 +59,7 @@ end local tropical_fish = { type = "animal", - spawn_class = "water", + spawn_class = "water_ambient", can_despawn = true, passive = true, hp_min = 3, From afb4540408cfcbf88cae289cb22f8020af61b95e Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 29 May 2023 20:08:44 +0100 Subject: [PATCH 145/155] Clean up --- mods/ENTITIES/mcl_mobs/spawning.lua | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index 4a9f6d736..10379a6fa 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -64,7 +64,7 @@ local mob_cap = { passive = tonumber(minetest.settings:get("mcl_mob_cap_animal")) or 13, ambient = tonumber(minetest.settings:get("mcl_mob_cap_ambient")) or 15, water = tonumber(minetest.settings:get("mcl_mob_cap_water")) or 8, - water_ambient = tonumber(minetest.settings:get("mcl_mob_cap_water_ambient")) or 20, --currently unused + water_ambient = tonumber(minetest.settings:get("mcl_mob_cap_water_ambient")) or 20, player = tonumber(minetest.settings:get("mcl_mob_cap_player")) or 75, global_hostile = tonumber(minetest.settings:get("mcl_mob_cap_hostile")) or 300, global_non_hostile = tonumber(minetest.settings:get("mcl_mob_cap_non_hostile")) or 300, @@ -361,7 +361,7 @@ local function count_mobs_total_cap(mob_type) end num = num + 1 else - mcl_log("l.nametag", l.name) + mcl_log("l.name", l.name) mcl_log("l.nametag", l.nametag) end @@ -871,6 +871,9 @@ if mobs_spawn then local cap_space_wide = math.max(type_cap - mob_total_wide, 0) + mcl_log("mob_type", mob_type) + mcl_log("cap_space_wide", cap_space_wide) + local cap_space_available = 0 if mob_type == "hostile" then mcl_log("cap_space_global", cap_space_hostile) @@ -879,10 +882,6 @@ if mobs_spawn then mcl_log("cap_space_global", cap_space_non_hostile) cap_space_available = math.min(cap_space_non_hostile, cap_space_wide) end - mcl_log("mob_type", mob_type) - mcl_log("cap_space_wide", cap_space_wide) - --mcl_log("cap_space_available", cap_space_available) - local mob_total_close = mob_counts_close[mob_type] if not mob_total_close then @@ -891,11 +890,10 @@ if mobs_spawn then end local cap_space_close = math.max(close_zone_cap - mob_total_close, 0) - mcl_log("cap_space_close", cap_space_close) - cap_space_available = math.min(cap_space_available, cap_space_close) - mcl_log("cap_space_available", cap_space_available) + mcl_log("cap_space_close", cap_space_close) + mcl_log("cap_space_available", cap_space_available) if false and mob_type == "water" then mcl_log("mob_type: " .. mob_type .. " and pos: " .. minetest.pos_to_string(pos)) @@ -986,9 +984,7 @@ if mobs_spawn then if mob_def and mob_def.name and minetest.registered_entities[mob_def.name] then local mob_def_ent = minetest.registered_entities[mob_def.name] - local mob_spawn_class = mob_def_ent.spawn_class - --mcl_log("mob_spawn_class: " .. mob_spawn_class) local cap_space_available = mob_cap_space (spawning_position, mob_spawn_class, mob_counts_close, mob_counts_wide, cap_space_hostile, cap_space_non_hostile) From 812269264bf4dbb0244ddf4ed3c107b8ffb655bb Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 29 May 2023 20:43:15 +0100 Subject: [PATCH 146/155] Add in caps for underground water and axolotl --- mods/ENTITIES/mcl_mobs/spawning.lua | 2 ++ mods/ENTITIES/mobs_mc/axolotl.lua | 2 +- mods/ENTITIES/mobs_mc/glow_squid.lua | 2 +- settingtypes.txt | 9 +++++++++ 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index 10379a6fa..f1f00a6a8 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -65,6 +65,8 @@ local mob_cap = { ambient = tonumber(minetest.settings:get("mcl_mob_cap_ambient")) or 15, water = tonumber(minetest.settings:get("mcl_mob_cap_water")) or 8, water_ambient = tonumber(minetest.settings:get("mcl_mob_cap_water_ambient")) or 20, + water_underground = tonumber(minetest.settings:get("mcl_mob_cap_water_underground")) or 5, + axolotl = tonumber(minetest.settings:get("mcl_mob_cap_axolotl")) or 2, -- TODO should be 5 when lush caves added player = tonumber(minetest.settings:get("mcl_mob_cap_player")) or 75, global_hostile = tonumber(minetest.settings:get("mcl_mob_cap_hostile")) or 300, global_non_hostile = tonumber(minetest.settings:get("mcl_mob_cap_non_hostile")) or 300, diff --git a/mods/ENTITIES/mobs_mc/axolotl.lua b/mods/ENTITIES/mobs_mc/axolotl.lua index 124f6bd3a..087f201c7 100644 --- a/mods/ENTITIES/mobs_mc/axolotl.lua +++ b/mods/ENTITIES/mobs_mc/axolotl.lua @@ -2,7 +2,7 @@ local S = minetest.get_translator(minetest.get_current_modname()) local axolotl = { type = "animal", - spawn_class = "water", + spawn_class = "axolotl", can_despawn = true, passive = false, hp_min = 14, diff --git a/mods/ENTITIES/mobs_mc/glow_squid.lua b/mods/ENTITIES/mobs_mc/glow_squid.lua index 5975671b1..2d3f19270 100644 --- a/mods/ENTITIES/mobs_mc/glow_squid.lua +++ b/mods/ENTITIES/mobs_mc/glow_squid.lua @@ -31,7 +31,7 @@ end mcl_mobs.register_mob("mobs_mc:glow_squid", { type = "animal", - spawn_class = "water", + spawn_class = "water_underground", can_despawn = true, passive = true, hp_min = 10, diff --git a/settingtypes.txt b/settingtypes.txt index fde9582d8..eb91b8414 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -151,6 +151,15 @@ mcl_mob_cap_animal (Mob cap animals) int 13 0 1024 #Maximum amount of water mobs that will spawn near a player (default:8) mcl_mob_cap_water (Mob cap water) int 8 0 1024 +#Maximum amount of ambient water mobs that will spawn near a player (default:20) +mcl_mob_cap_water_ambient (Mob cap ambient water) int 20 0 1024 + +#Maximum amount of underground water mobs that will spawn near a player (default:5) +mcl_mob_cap_water_underground (Mob cap underground water) int 5 0 1024 + +#Maximum amount of axolotl mobs that will spawn near a player (default:5) +mcl_mob_cap_axolotl (Mob cap axolotl) int 5 0 1024 + #Maximum amount of ambient mobs that will spawn near a player (default:15) mcl_mob_cap_ambient (Mob cap ambient mobs) int 15 0 1024 From c65f8c9e5161a8494d6d3b575e44362dd7570fcd Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 29 May 2023 21:43:27 +0100 Subject: [PATCH 147/155] Improved early game spawn balance --- mods/ENTITIES/mcl_mobs/spawning.lua | 4 ++-- settingtypes.txt | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index f1f00a6a8..c677aeacf 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -61,7 +61,7 @@ local SPAWN_MAPGEN_LIMIT = mcl_vars.mapgen_limit - 150 local mob_cap = { hostile = tonumber(minetest.settings:get("mcl_mob_cap_monster")) or 70, - passive = tonumber(minetest.settings:get("mcl_mob_cap_animal")) or 13, + passive = tonumber(minetest.settings:get("mcl_mob_cap_animal")) or 10, ambient = tonumber(minetest.settings:get("mcl_mob_cap_ambient")) or 15, water = tonumber(minetest.settings:get("mcl_mob_cap_water")) or 8, water_ambient = tonumber(minetest.settings:get("mcl_mob_cap_water_ambient")) or 20, @@ -73,7 +73,7 @@ local mob_cap = { total = tonumber(minetest.settings:get("mcl_mob_cap_total")) or 500, } -local peaceful_percentage_spawned = tonumber(minetest.settings:get("mcl_mob_peaceful_percentage_spawned")) or 35 +local peaceful_percentage_spawned = tonumber(minetest.settings:get("mcl_mob_peaceful_percentage_spawned")) or 30 local peaceful_group_percentage_spawned = tonumber(minetest.settings:get("mcl_mob_peaceful_group_percentage_spawned")) or 15 local hostile_group_percentage_spawned = tonumber(minetest.settings:get("mcl_mob_hostile_group_percentage_spawned")) or 20 diff --git a/settingtypes.txt b/settingtypes.txt index eb91b8414..c5d5d32c1 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -121,8 +121,8 @@ mobs_griefing (Mobs change blocks) bool true # If enabled, mobs won't damage particles when they got hurt. mobs_disable_blood (Disable mob damage particles) bool false -#Percentage of peaceful spawn attempts that succeed (default:35) -mcl_mob_peaceful_percentage_spawned (Peaceful percentage success) int 35 0 100 +#Percentage of peaceful spawn attempts that succeed (default:30) +mcl_mob_peaceful_percentage_spawned (Peaceful percentage success) int 30 0 100 #Percentage of peaceful spawn attempts that are group spawns (default:15) mcl_mob_peaceful_group_percentage_spawned (Peaceful group percentage) int 15 0 100 @@ -145,8 +145,8 @@ mcl_mob_cap_player (Mob cap per player) int 75 0 2048 #Maximum amount of monsters that will spawn near a player (default:70) mcl_mob_cap_monster (Mob cap monsters) int 70 0 2048 -#Maximum amount of animals that will spawn near a player (default:13) -mcl_mob_cap_animal (Mob cap animals) int 13 0 1024 +#Maximum amount of animals that will spawn near a player (default:10) +mcl_mob_cap_animal (Mob cap animals) int 10 0 1024 #Maximum amount of water mobs that will spawn near a player (default:8) mcl_mob_cap_water (Mob cap water) int 8 0 1024 From 4287a261c8df88a7c7fb5b08a748d9f829698dcf Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 2 Jun 2023 21:14:52 +0100 Subject: [PATCH 148/155] Change order of numbers passed into random that crash on some Lua versions --- mods/ENTITIES/mobs_mc/villager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mobs_mc/villager.lua b/mods/ENTITIES/mobs_mc/villager.lua index db44843f2..8fc18ccab 100644 --- a/mods/ENTITIES/mobs_mc/villager.lua +++ b/mods/ENTITIES/mobs_mc/villager.lua @@ -137,7 +137,7 @@ local professions = { { { { "mcl_fishing:fish_raw", 6, 6, "mcl_core:emerald", 1, 1 },{ "mcl_fishing:fish_cooked", 6, 6 } }, { { "mcl_mobitems:string", 15, 20 }, E1 }, - { { "mcl_core:coal_lump", 15, 10 }, E1 }, + { { "mcl_core:coal_lump", 10, 15 }, E1 }, -- FIXME missing: bucket of cod + fish should be cod. }, { From 4b9fc7046bcc09f8980d8f27a6ca4e84fc27cdd4 Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Fri, 19 May 2023 20:24:13 -0600 Subject: [PATCH 149/155] Add Oxidization API --- mods/CORE/mcl_oxidation/README.md | 14 +++++++++++++ mods/CORE/mcl_oxidation/init.lua | 12 +++++++++++ mods/CORE/mcl_oxidation/mod.conf | 4 ++++ mods/ITEMS/mcl_copper/functions.lua | 12 ----------- mods/ITEMS/mcl_copper/nodes.lua | 32 ++++++++++++++--------------- 5 files changed, 46 insertions(+), 28 deletions(-) create mode 100644 mods/CORE/mcl_oxidation/README.md create mode 100644 mods/CORE/mcl_oxidation/init.lua create mode 100644 mods/CORE/mcl_oxidation/mod.conf diff --git a/mods/CORE/mcl_oxidation/README.md b/mods/CORE/mcl_oxidation/README.md new file mode 100644 index 000000000..70d9c24fe --- /dev/null +++ b/mods/CORE/mcl_oxidation/README.md @@ -0,0 +1,14 @@ +# Oxidization API for MineClone 2 +This mods adds the oxidization api, so that modders can easily use the same features that copper uses. + +## API +To take advantage of the actual oxidization, put `oxidizable = 1` into the list of groups for the oxidizable node. +You would also need to put `_mcl_oxidized_variant = itemstring of node this node will oxidize into` into the node definition. +For example, a copper block oxidizes into exposed copper, so the defintion would be `_mcl_oxidized_variant = "mcl_copper:block_exposed"`. + +To utilize the ability to wax the block for protection from oxidization, put `mcl_waxed_varient = item string of waxed varient of node` into the node definition table. +For example, Copper Blocks have the definition arguement of `_mcl_waxed_variant = "mcl_copper:waxed_block"`. + +For waxed nodes, scraping is easy. Start by putting `waxed = 1` into the list of groups of the waxed node. +Next put `_mcl_stripped_variant = item string of the unwaxed varient of the node` into the defintion table. +Wxaed Copper Blocks can be scrapped into normal Copper Blocks because of the definition `_mcl_stripped_variant = "mcl_copper:block"`. diff --git a/mods/CORE/mcl_oxidation/init.lua b/mods/CORE/mcl_oxidation/init.lua new file mode 100644 index 000000000..f0e8a37e6 --- /dev/null +++ b/mods/CORE/mcl_oxidation/init.lua @@ -0,0 +1,12 @@ +minetest.register_abm({ + label = "Oxidatize Nodes", + nodenames = { "group:oxidizable" }, + interval = 500, + chance = 3, + action = function(pos, node) + local def = minetest.registered_nodes[node] + if def and def._mcl_oxidized_variant then + minetest.swap_node(pos, { name = def._mcl_oxidized_varient, param2 = node.param2 }) + end + end, +}) diff --git a/mods/CORE/mcl_oxidation/mod.conf b/mods/CORE/mcl_oxidation/mod.conf new file mode 100644 index 000000000..7ab7eeffe --- /dev/null +++ b/mods/CORE/mcl_oxidation/mod.conf @@ -0,0 +1,4 @@ +name = mcl_oxidation +title = Oxidation API for MineClone 2 +author = PrairieWind, N011, Michael +description = API to allow oxidizing different nodes. diff --git a/mods/ITEMS/mcl_copper/functions.lua b/mods/ITEMS/mcl_copper/functions.lua index db756e425..8410526ac 100644 --- a/mods/ITEMS/mcl_copper/functions.lua +++ b/mods/ITEMS/mcl_copper/functions.lua @@ -1,17 +1,5 @@ --local deepslate_mod = minetest.get_modpath("mcl_deepslate") -local function register_oxidation_abm(abm_name, node_name, oxidized_variant) - minetest.register_abm({ - label = abm_name, - nodenames = { node_name }, - interval = 500, - chance = 3, - action = function(pos, node) - minetest.swap_node(pos, { name = oxidized_variant, param2 = node.param2 }) - end, - }) -end - --[[ local stairs = { {"stair", "exposed", "_inner", "cut_inner"}, diff --git a/mods/ITEMS/mcl_copper/nodes.lua b/mods/ITEMS/mcl_copper/nodes.lua index c8bb139cf..4bf5fd534 100644 --- a/mods/ITEMS/mcl_copper/nodes.lua +++ b/mods/ITEMS/mcl_copper/nodes.lua @@ -30,7 +30,7 @@ minetest.register_node("mcl_copper:block", { _doc_items_longdesc = S("A block of copper is mostly a decorative block."), tiles = {"mcl_copper_block.png"}, is_ground_content = false, - groups = {pickaxey = 2, building_block = 1}, + groups = {pickaxey = 2, building_block = 1, oxidizable = 1}, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 3, @@ -54,7 +54,7 @@ minetest.register_node("mcl_copper:block_exposed", { _doc_items_longdesc = S("Exposed copper is a decorative block."), tiles = {"mcl_copper_exposed.png"}, is_ground_content = false, - groups = {pickaxey = 2, building_block = 1}, + groups = {pickaxey = 2, building_block = 1, oxidizable = 1}, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, @@ -79,7 +79,7 @@ minetest.register_node("mcl_copper:block_weathered", { _doc_items_longdesc = S("Weathered copper is a decorative block."), tiles = {"mcl_copper_weathered.png"}, is_ground_content = false, - groups = {pickaxey = 2, building_block = 1}, + groups = {pickaxey = 2, building_block = 1, oxidizable = 1}, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, @@ -104,7 +104,7 @@ minetest.register_node("mcl_copper:block_oxidized", { _doc_items_longdesc = S("Oxidized copper is a decorative block."), tiles = {"mcl_copper_oxidized.png"}, is_ground_content = false, - groups = {pickaxey = 2, building_block = 1}, + groups = {pickaxey = 2, building_block = 1, oxidizable = 1}, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, @@ -129,7 +129,7 @@ minetest.register_node("mcl_copper:block_cut", { _doc_items_longdesc = S("Cut copper is a decorative block."), tiles = {"mcl_copper_block_cut.png"}, is_ground_content = false, - groups = {pickaxey = 2, building_block = 1}, + groups = {pickaxey = 2, building_block = 1, oxidizable = 1}, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, @@ -153,7 +153,7 @@ minetest.register_node("mcl_copper:block_exposed_cut", { _doc_items_longdesc = S("Exposed cut copper is a decorative block."), tiles = {"mcl_copper_exposed_cut.png"}, is_ground_content = false, - groups = {pickaxey = 2, building_block = 1}, + groups = {pickaxey = 2, building_block = 1, oxidizable = 1}, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, @@ -178,7 +178,7 @@ minetest.register_node("mcl_copper:block_weathered_cut", { _doc_items_longdesc = S("Weathered cut copper is a decorative block."), tiles = {"mcl_copper_weathered_cut.png"}, is_ground_content = false, - groups = {pickaxey = 2, building_block = 1}, + groups = {pickaxey = 2, building_block = 1, oxidizable = 1}, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, @@ -203,7 +203,7 @@ minetest.register_node("mcl_copper:block_oxidized_cut", { _doc_items_longdesc = S("Oxidized cut copper is a decorative block."), tiles = {"mcl_copper_oxidized_cut.png"}, is_ground_content = false, - groups = {pickaxey = 2, building_block = 1}, + groups = {pickaxey = 2, building_block = 1, oxidizable = 1}, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, @@ -224,7 +224,7 @@ minetest.register_node("mcl_copper:waxed_block_oxidized_cut", { }) mcl_stairs.register_slab("copper_cut", "mcl_copper:block_cut", - {pickaxey = 2}, + {pickaxey = 2, oxidizable = 1}, {"mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png"}, S("Slab of Cut Copper"), nil, nil, nil, @@ -238,7 +238,7 @@ mcl_stairs.register_slab("waxed_copper_cut", "mcl_copper:waxed_block_cut", S("Waxed Double Slab of Cut Copper")) mcl_stairs.register_slab("copper_exposed_cut", "mcl_copper:block_exposed_cut", - {pickaxey = 2}, + {pickaxey = 2, oxidizable = 1}, {"mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png"}, S("Slab of Exposed Cut Copper"), nil, nil, nil, @@ -252,7 +252,7 @@ mcl_stairs.register_slab("waxed_copper_exposed_cut", "mcl_copper:waxed_block_exp S("Waxed Double Slab of Exposed Cut Copper")) mcl_stairs.register_slab("copper_weathered_cut", "mcl_copper:block_weathered_cut", - {pickaxey = 2}, + {pickaxey = 2, oxidizable = 1}, {"mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png"}, S("Slab of Weathered Cut Copper"), nil, nil, nil, @@ -266,7 +266,7 @@ mcl_stairs.register_slab("waxed_copper_weathered_cut", "mcl_copper:waxed_block_w S("Waxed Double Slab of Weathered Cut Copper")) mcl_stairs.register_slab("copper_oxidized_cut", "mcl_copper:block_oxidized_cut", - {pickaxey = 2}, + {pickaxey = 2, oxidizable = 1}, {"mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png"}, S("Slab of Oxidized Cut Copper"), nil, nil, nil, @@ -280,7 +280,7 @@ mcl_stairs.register_slab("waxed_copper_oxidized_cut", "mcl_copper:waxed_block_ox S("Waxed Double Slab of Oxidized Cut Copper")) mcl_stairs.register_stair("copper_cut", "mcl_copper:block_cut", - {pickaxey = 2}, + {pickaxey = 2, oxidizable = 1}, {"mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png"}, S("Stairs of Cut Copper"), nil, 6, nil, @@ -294,7 +294,7 @@ mcl_stairs.register_stair("waxed_copper_cut", "mcl_copper:waxed_block_cut", "woodlike") mcl_stairs.register_stair("copper_exposed_cut", "mcl_copper:block_exposed_cut", - {pickaxey = 2}, + {pickaxey = 2, oxidizable = 1}, {"mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png"}, S("Stairs of Exposed Cut Copper"), nil, 6, nil, @@ -308,7 +308,7 @@ mcl_stairs.register_stair("waxed_copper_exposed_cut", "mcl_copper:waxed_block_ex "woodlike") mcl_stairs.register_stair("copper_weathered_cut", "mcl_copper:block_weathered_cut", - {pickaxey = 2}, + {pickaxey = 2, oxidizable = 1}, {"mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png"}, S("Stairs of Weathered Cut Copper"), nil, 6, nil, @@ -322,7 +322,7 @@ mcl_stairs.register_stair("waxed_copper_weathered_cut", "mcl_copper:waxed_block_ "woodlike") mcl_stairs.register_stair("copper_oxidized_cut", "mcl_copper:block_oxidized_cut", - {pickaxey = 2}, + {pickaxey = 2, oxidizable = 1}, {"mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png"}, S("Stairs of Oxidized Cut Copper"), nil, 6, nil, From 9e5a45e3fd991f2a7be1094e3c39df4011117457 Mon Sep 17 00:00:00 2001 From: Michieal Date: Wed, 15 Feb 2023 13:41:43 -0500 Subject: [PATCH 150/155] Rebased; Changed the way that the abm handles being called. Still have to make the scraped variants of the stairs & slabs. --- mods/ITEMS/mcl_copper/functions.lua | 57 ++++++++++++++++++++--------- mods/ITEMS/mcl_copper/nodes.lua | 6 +++ 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/mods/ITEMS/mcl_copper/functions.lua b/mods/ITEMS/mcl_copper/functions.lua index 8410526ac..c3b97fd4c 100644 --- a/mods/ITEMS/mcl_copper/functions.lua +++ b/mods/ITEMS/mcl_copper/functions.lua @@ -32,32 +32,55 @@ local block_oxidation = { } local stair_oxidation = { - { "slab", "cut", "exposed_cut" }, - { "slab", "exposed_cut", "weathered_cut" }, - { "slab", "weathered_cut", "oxidized_cut" }, - { "slab", "cut_top", "exposed_cut_top" }, - { "slab", "exposed_cut_top", "weathered_cut_top" }, - { "slab", "weathered_cut_top", "oxidized_cut_double" }, - { "slab", "cut_double", "exposed_cut_double" }, - { "slab", "exposed_cut_double", "weathered_cut_double" }, - { "slab", "weathered_cut_double", "oxidized_cut_double" }, { "stair", "cut", "exposed_cut" }, - { "stair", "exposed_cut", "weathered_cut" }, - { "stair", "weathered_cut", "oxidized_cut" }, { "stair", "cut_inner", "exposed_cut_inner" }, - { "stair", "exposed_cut_inner", "weathered_cut_inner" }, - { "stair", "weathered_cut_inner", "oxidized_cut_inner" }, { "stair", "cut_outer", "exposed_cut_outer" }, + { "stair", "exposed_cut", "weathered_cut" }, + { "stair", "exposed_cut_inner", "weathered_cut_inner" }, { "stair", "exposed_cut_outer", "weathered_cut_outer" }, + { "stair", "weathered_cut", "oxidized_cut" }, + { "stair", "weathered_cut_inner", "oxidized_cut_inner" }, { "stair", "weathered_cut_outer", "oxidized_cut_outer" } } +local slab_oxidization = { + { "slab", "cut", "exposed_cut" }, + { "slab", "cut_top", "exposed_cut_top" }, + { "slab", "cut_double", "exposed_cut_double" }, + { "slab", "exposed_cut", "weathered_cut" }, + { "slab", "exposed_cut_top", "weathered_cut_top" }, + { "slab", "exposed_cut_double", "weathered_cut_double" }, + { "slab", "weathered_cut", "oxidized_cut" }, + { "slab", "weathered_cut_top", "oxidized_cut_double" }, + { "slab", "weathered_cut_double", "oxidized_cut_double" }, +} + for _, b in pairs(block_oxidation) do - register_oxidation_abm("Copper oxidation", "mcl_copper:block" .. b[1], "mcl_copper:block" .. b[2]) + register_oxidation_abm("mcl_copper:block" .. b[1]) end +local def +local def_variant_oxidized +local def_variant_waxed +-- local def_variant_scraped + for _, s in pairs(stair_oxidation) do - register_oxidation_abm("Copper oxidation", "mcl_stairs:" .. s[1] .. "_copper_" .. s[2], "mcl_stairs:" .. s[1] .. "_copper_" .. s[3]) - -- TODO: Make stairs and slabs be waxable / scrapable. Place the Node overrides here, just like they are on the copper nodes, and it will work properly. May need to update mcl_honey to call the waxing function for stairs and slabs. -end + register_oxidation_abm("Copper oxidation", "mcl_stairs:" .. s[1] .. "_copper_" .. s[2]) + def = "mcl_stairs:" .. s[1] .. "_copper_" .. s[2] + def_variant_oxidized = "mcl_stairs:" .. s[1] .. "_copper_" .. s[3] + minetest.override_item(def, { _mcl_oxidized_variant = def_variant_oxidized }) + + def_variant_waxed = "mcl_stairs:" .. s[1] .. "_copper_" .. s[2] .. "_waxed" + minetest.override_item(def, { _mcl_copper_waxed_variant = def_variant_waxed }) +end +for _, s in pairs(slab_oxidization) do + register_oxidation_abm("Copper oxidation", "mcl_stairs:" .. s[1] .. "_copper_" .. s[2]) + def = "mcl_stairs:" .. s[1] .. "_copper_" .. s[2] + def_variant_oxidized = "mcl_stairs:" .. s[1] .. "_copper_" .. s[3] + minetest.override_item(def, { _mcl_oxidized_variant = def_variant_oxidized }) + + def_variant_waxed = "mcl_stairs:" .. s[1] .. "_copper_" .. s[2] .. "_waxed" + minetest.override_item(def, { _mcl_copper_waxed_variant = def_variant_waxed }) +end +-- TODO: Do Scraped (mcl_stripped_variant) for stairs and slabs. diff --git a/mods/ITEMS/mcl_copper/nodes.lua b/mods/ITEMS/mcl_copper/nodes.lua index 4bf5fd534..b4768e4cc 100644 --- a/mods/ITEMS/mcl_copper/nodes.lua +++ b/mods/ITEMS/mcl_copper/nodes.lua @@ -34,6 +34,7 @@ minetest.register_node("mcl_copper:block", { sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 3, + _mcl_oxidized_variant = "mcl_copper:block_exposed", _mcl_copper_waxed_variant = "mcl_copper:waxed_block", }) @@ -58,6 +59,7 @@ minetest.register_node("mcl_copper:block_exposed", { sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, + _mcl_oxidized_variant = "mcl_copper:block_weathered", _mcl_copper_waxed_variant = "mcl_copper:waxed_block_exposed", _mcl_stripped_variant = "mcl_copper:block", }) @@ -83,6 +85,7 @@ minetest.register_node("mcl_copper:block_weathered", { sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, + _mcl_oxidized_variant = "mcl_copper:block_oxidized", _mcl_copper_waxed_variant = "mcl_copper:waxed_block_weathered", _mcl_stripped_variant = "mcl_copper:block_exposed", }) @@ -133,6 +136,7 @@ minetest.register_node("mcl_copper:block_cut", { sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, + _mcl_oxidized_variant = "mcl_copper:block_cut_exposed", _mcl_copper_waxed_variant = "mcl_copper:waxed_block_cut", }) @@ -158,6 +162,7 @@ minetest.register_node("mcl_copper:block_exposed_cut", { _mcl_blast_resistance = 6, _mcl_hardness = 5, _mcl_copper_waxed_variant = "mcl_copper:waxed_block_exposed_cut", + _mcl_oxidized_variant = "mcl_copper:block_cut_weathered", _mcl_stripped_variant = "mcl_copper:block_cut", }) @@ -183,6 +188,7 @@ minetest.register_node("mcl_copper:block_weathered_cut", { _mcl_blast_resistance = 6, _mcl_hardness = 5, _mcl_stripped_variant = "mcl_copper:block_exposed_cut", + _mcl_oxidized_variant = "mcl_copper:block_cut_oxidized", _mcl_copper_waxed_variant = "mcl_copper:waxed_block_weathered_cut", }) From d6858b7e2a8f9f241a2a5379a9231ae8cb5691d9 Mon Sep 17 00:00:00 2001 From: Michieal Date: Wed, 15 Feb 2023 13:59:39 -0500 Subject: [PATCH 151/155] Made the scraped variants of the stairs & slabs. Cleaned up commented out code. --- mods/ITEMS/mcl_copper/functions.lua | 73 ++++++++++------------------- 1 file changed, 26 insertions(+), 47 deletions(-) diff --git a/mods/ITEMS/mcl_copper/functions.lua b/mods/ITEMS/mcl_copper/functions.lua index c3b97fd4c..6d4451484 100644 --- a/mods/ITEMS/mcl_copper/functions.lua +++ b/mods/ITEMS/mcl_copper/functions.lua @@ -1,36 +1,3 @@ ---local deepslate_mod = minetest.get_modpath("mcl_deepslate") - ---[[ -local stairs = { - {"stair", "exposed", "_inner", "cut_inner"}, - {"stair", "weathered", "_inner", "exposed_cut_inner"}, - {"stair", "exposed", "_outer", "cut_outer"}, - {"stair", "weathered", "_outer", "exposed_cut_outer"}, - {"stair", "oxidized", "_outer", "weathered_cut_outer"}, - {"stair", "oxidized", "_inner", "weathered_cut_inner"}, - {"slab", "exposed", "","cut"}, - {"slab", "oxidized", "","weathered_cut"}, - {"slab", "weathered", "","exposed_cut"}, - {"slab", "exposed", "_top","cut_top"}, - {"slab", "oxidized", "_top", "weathered_cut_top"}, - {"slab", "weathered", "_top","exposed_cut_top"}, - {"slab", "exposed", "_double","cut_double"}, - {"slab", "oxidized", "_double","weathered_cut_double"}, - {"slab", "weathered", "_double","exposed_cut_double"}, - {"stair", "exposed", "","cut"}, - {"stair", "oxidized", "", "weathered_cut"}, - {"stair", "weathered", "", "exposed_cut"}, -}]] - -local block_oxidation = { - { "", "_exposed" }, - { "_cut", "_exposed_cut" }, - { "_exposed", "_weathered" }, - { "_exposed_cut", "_weathered_cut" }, - { "_weathered", "_oxidized" }, - { "_weathered_cut", "_oxidized_cut" } -} - local stair_oxidation = { { "stair", "cut", "exposed_cut" }, { "stair", "cut_inner", "exposed_cut_inner" }, @@ -55,17 +22,19 @@ local slab_oxidization = { { "slab", "weathered_cut_double", "oxidized_cut_double" }, } -for _, b in pairs(block_oxidation) do - register_oxidation_abm("mcl_copper:block" .. b[1]) -end - local def local def_variant_oxidized local def_variant_waxed --- local def_variant_scraped +local def_variant_scraped +-- register abm, then set up oxidized and waxed variants. for _, s in pairs(stair_oxidation) do - register_oxidation_abm("Copper oxidation", "mcl_stairs:" .. s[1] .. "_copper_" .. s[2]) + def = "mcl_stairs:" .. s[1] .. "_copper_" .. s[2] + def_variant_oxidized = "mcl_stairs:" .. s[1] .. "_copper_" .. s[3] + minetest.override_item(def, { _mcl_oxidized_variant = def_variant_oxidized }) + + def_variant_waxed = "mcl_stairs:" .. s[1] .. "_copper_" .. s[2] .. "_waxed" + minetest.override_item(def, { _mcl_copper_waxed_variant = def_variant_waxed }) def = "mcl_stairs:" .. s[1] .. "_copper_" .. s[2] def_variant_oxidized = "mcl_stairs:" .. s[1] .. "_copper_" .. s[3] minetest.override_item(def, { _mcl_oxidized_variant = def_variant_oxidized }) @@ -73,14 +42,24 @@ for _, s in pairs(stair_oxidation) do def_variant_waxed = "mcl_stairs:" .. s[1] .. "_copper_" .. s[2] .. "_waxed" minetest.override_item(def, { _mcl_copper_waxed_variant = def_variant_waxed }) end -for _, s in pairs(slab_oxidization) do - register_oxidation_abm("Copper oxidation", "mcl_stairs:" .. s[1] .. "_copper_" .. s[2]) - def = "mcl_stairs:" .. s[1] .. "_copper_" .. s[2] - def_variant_oxidized = "mcl_stairs:" .. s[1] .. "_copper_" .. s[3] - minetest.override_item(def, { _mcl_oxidized_variant = def_variant_oxidized }) - def_variant_waxed = "mcl_stairs:" .. s[1] .. "_copper_" .. s[2] .. "_waxed" - minetest.override_item(def, { _mcl_copper_waxed_variant = def_variant_waxed }) +-- Set up scraped variants. +for i=1, #stair_oxidation do + if i > 3 then + def = "mcl_stairs:" .. stair_oxidation[i][1] .. "_copper_" .. stair_oxidation[i][2] + def_variant_scraped="mcl_stairs:" .. stair_oxidation[i-3][1] .. "_copper_" .. stair_oxidation[i-3][2] + minetest.override_item(def, { _mcl_stripped_variant = def_variant_scraped }) + def = "mcl_stairs:" .. slab_oxidization[i][1] .. "_copper_" .. slab_oxidization[i][2] + def_variant_scraped="mcl_stairs:" .. slab_oxidization[i-3][1] .. "_copper_" .. slab_oxidization[i-3][2] + minetest.override_item(def, { _mcl_stripped_variant = def_variant_scraped }) + end + if i>6 then + def = "mcl_stairs:" .. stair_oxidation[i][1] .. "_copper_" .. stair_oxidation[i][3] + def_variant_scraped="mcl_stairs:" .. stair_oxidation[i][1] .. "_copper_" .. stair_oxidation[i][2] + minetest.override_item(def, { _mcl_stripped_variant = def_variant_scraped }) + def = "mcl_stairs:" .. slab_oxidization[i][1] .. "_copper_" .. slab_oxidization[i][3] + def_variant_scraped="mcl_stairs:" .. slab_oxidization[i][1] .. "_copper_" .. slab_oxidization[i][2] + minetest.override_item(def, { _mcl_stripped_variant = def_variant_scraped }) + end end --- TODO: Do Scraped (mcl_stripped_variant) for stairs and slabs. From 7c4682695809ce63e2e60be05ce77232199e6f86 Mon Sep 17 00:00:00 2001 From: Michieal Date: Wed, 15 Feb 2023 14:55:41 -0500 Subject: [PATCH 152/155] Did what I should have done to begin with: changed _mcl_copper_waxed_variant to _mcl_waxed_variant so that it intuitively applies to more than just copper. --- mods/ITEMS/mcl_copper/functions.lua | 121 +++++++++++++++++++--------- mods/ITEMS/mcl_copper/init.lua | 2 +- mods/ITEMS/mcl_copper/mod.conf | 2 +- mods/ITEMS/mcl_copper/nodes.lua | 24 +++--- mods/ITEMS/mcl_honey/init.lua | 4 +- 5 files changed, 99 insertions(+), 54 deletions(-) diff --git a/mods/ITEMS/mcl_copper/functions.lua b/mods/ITEMS/mcl_copper/functions.lua index 6d4451484..43fee2db7 100644 --- a/mods/ITEMS/mcl_copper/functions.lua +++ b/mods/ITEMS/mcl_copper/functions.lua @@ -1,25 +1,25 @@ -local stair_oxidation = { - { "stair", "cut", "exposed_cut" }, - { "stair", "cut_inner", "exposed_cut_inner" }, - { "stair", "cut_outer", "exposed_cut_outer" }, - { "stair", "exposed_cut", "weathered_cut" }, - { "stair", "exposed_cut_inner", "weathered_cut_inner" }, - { "stair", "exposed_cut_outer", "weathered_cut_outer" }, - { "stair", "weathered_cut", "oxidized_cut" }, - { "stair", "weathered_cut_inner", "oxidized_cut_inner" }, - { "stair", "weathered_cut_outer", "oxidized_cut_outer" } +local stair_oxidization = { + { "cut", "exposed_cut" }, + { "cut_inner", "exposed_cut_inner" }, + { "cut_outer", "exposed_cut_outer" }, + { "exposed_cut", "weathered_cut" }, + { "exposed_cut_inner", "weathered_cut_inner" }, + { "exposed_cut_outer", "weathered_cut_outer" }, + { "weathered_cut", "oxidized_cut" }, + { "weathered_cut_inner", "oxidized_cut_inner" }, + { "weathered_cut_outer", "oxidized_cut_outer" } } local slab_oxidization = { - { "slab", "cut", "exposed_cut" }, - { "slab", "cut_top", "exposed_cut_top" }, - { "slab", "cut_double", "exposed_cut_double" }, - { "slab", "exposed_cut", "weathered_cut" }, - { "slab", "exposed_cut_top", "weathered_cut_top" }, - { "slab", "exposed_cut_double", "weathered_cut_double" }, - { "slab", "weathered_cut", "oxidized_cut" }, - { "slab", "weathered_cut_top", "oxidized_cut_double" }, - { "slab", "weathered_cut_double", "oxidized_cut_double" }, + { "cut", "exposed_cut" }, + { "cut_top", "exposed_cut_top" }, + { "cut_double", "exposed_cut_double" }, + { "exposed_cut", "weathered_cut" }, + { "exposed_cut_top", "weathered_cut_top" }, + { "exposed_cut_double", "weathered_cut_double" }, + { "weathered_cut", "oxidized_cut" }, + { "weathered_cut_top", "oxidized_cut_double" }, + { "weathered_cut_double", "oxidized_cut_double" }, } local def @@ -27,39 +27,82 @@ local def_variant_oxidized local def_variant_waxed local def_variant_scraped --- register abm, then set up oxidized and waxed variants. -for _, s in pairs(stair_oxidation) do - def = "mcl_stairs:" .. s[1] .. "_copper_" .. s[2] - def_variant_oxidized = "mcl_stairs:" .. s[1] .. "_copper_" .. s[3] +-- set up oxidized and waxed variants. +for i = 1, #stair_oxidization do + -- stairs + def = "mcl_stairs:stair_copper_" .. stair_oxidization[i][1] + def_variant_oxidized = "mcl_stairs:stair_copper_" .. stair_oxidization[i][2] minetest.override_item(def, { _mcl_oxidized_variant = def_variant_oxidized }) - def_variant_waxed = "mcl_stairs:" .. s[1] .. "_copper_" .. s[2] .. "_waxed" - minetest.override_item(def, { _mcl_copper_waxed_variant = def_variant_waxed }) - def = "mcl_stairs:" .. s[1] .. "_copper_" .. s[2] - def_variant_oxidized = "mcl_stairs:" .. s[1] .. "_copper_" .. s[3] + def_variant_waxed = "mcl_stairs:stair_waxed_copper_" .. stair_oxidization[i][2] + minetest.override_item(def, { _mcl_waxed_variant = def_variant_waxed }) + + -- slabs + def = "mcl_stairs:slab_copper_" .. slab_oxidization[i][1] + def_variant_oxidized = "mcl_stairs:slab_copper_" .. slab_oxidization[i][2] minetest.override_item(def, { _mcl_oxidized_variant = def_variant_oxidized }) - def_variant_waxed = "mcl_stairs:" .. s[1] .. "_copper_" .. s[2] .. "_waxed" - minetest.override_item(def, { _mcl_copper_waxed_variant = def_variant_waxed }) + def_variant_waxed = "mcl_stairs:slab_waxed_copper_" .. slab_oxidization[i][1] + minetest.override_item(def, { _mcl_waxed_variant = def_variant_waxed }) end -- Set up scraped variants. -for i=1, #stair_oxidation do +for i = 1, #stair_oxidization do + -- does both stairs and slabs. if i > 3 then - def = "mcl_stairs:" .. stair_oxidation[i][1] .. "_copper_" .. stair_oxidation[i][2] - def_variant_scraped="mcl_stairs:" .. stair_oxidation[i-3][1] .. "_copper_" .. stair_oxidation[i-3][2] + def = "mcl_stairs:stair_copper_" .. stair_oxidization[i][1] + def_variant_scraped = "mcl_stairs:stair_copper_" .. stair_oxidization[i - 3][1] minetest.override_item(def, { _mcl_stripped_variant = def_variant_scraped }) - def = "mcl_stairs:" .. slab_oxidization[i][1] .. "_copper_" .. slab_oxidization[i][2] - def_variant_scraped="mcl_stairs:" .. slab_oxidization[i-3][1] .. "_copper_" .. slab_oxidization[i-3][2] + + def = "mcl_stairs:slab_copper_" .. slab_oxidization[i][1] + def_variant_scraped = "mcl_stairs:slab_copper_" .. slab_oxidization[i - 3][1] minetest.override_item(def, { _mcl_stripped_variant = def_variant_scraped }) end - if i>6 then - def = "mcl_stairs:" .. stair_oxidation[i][1] .. "_copper_" .. stair_oxidation[i][3] - def_variant_scraped="mcl_stairs:" .. stair_oxidation[i][1] .. "_copper_" .. stair_oxidation[i][2] + if i > 6 then + def = "mcl_stairs:stair_copper_" .. stair_oxidization[i][2] + def_variant_scraped = "mcl_stairs:stair_copper_" .. stair_oxidization[i][1] minetest.override_item(def, { _mcl_stripped_variant = def_variant_scraped }) - def = "mcl_stairs:" .. slab_oxidization[i][1] .. "_copper_" .. slab_oxidization[i][3] - def_variant_scraped="mcl_stairs:" .. slab_oxidization[i][1] .. "_copper_" .. slab_oxidization[i][2] + + def = "mcl_stairs:slab_copper_" .. slab_oxidization[i][2] + def_variant_scraped = "mcl_stairs:slab_copper_" .. slab_oxidization[i][1] minetest.override_item(def, { _mcl_stripped_variant = def_variant_scraped }) end end +-- Set up scraped variants for waxed stairs. +local waxed_variants = { + { "waxed_copper_cut", "copper_cut" }, + { "waxed_copper_exposed_cut", "copper_exposed_cut" }, + { "waxed_copper_weathered_cut", "copper_weathered_cut" }, + { "waxed_copper_oxidized_cut", "copper_oxidized_cut" }, +} + +for i = 1, #waxed_variants do + -- stairs + def = "mcl_stairs:stair_" .. waxed_variants[i][1] + def_variant_scraped = "mcl_stairs:stair_" .. waxed_variants[i][2] + minetest.override_item(def, { _mcl_stripped_variant = def_variant_scraped }) + + def = "mcl_stairs:stair_" .. waxed_variants[i][1] .. "_inner" + def_variant_scraped = "mcl_stairs:stair_" .. waxed_variants[i][2] .. "_inner" + minetest.override_item(def, { _mcl_stripped_variant = def_variant_scraped }) + + def = "mcl_stairs:stair_" .. waxed_variants[i][1] .. "_outer" + def_variant_scraped = "mcl_stairs:stair_" .. waxed_variants[i][2] .. "_outer" + minetest.override_item(def, { _mcl_stripped_variant = def_variant_scraped }) + + -- slab + def = "mcl_stairs:slab_" .. waxed_variants[i][1] + def_variant_scraped = "mcl_stairs:slab_" .. waxed_variants[i][2] + minetest.override_item(def, { _mcl_stripped_variant = def_variant_scraped }) + + def = "mcl_stairs:slab_" .. waxed_variants[i][1] .. "_top" + def_variant_scraped = "mcl_stairs:slab_" .. waxed_variants[i][2] .. "_top" + minetest.override_item(def, { _mcl_stripped_variant = def_variant_scraped }) + + def = "mcl_stairs:slab_" .. waxed_variants[i][1] .. "_double" + def_variant_scraped = "mcl_stairs:slab_" .. waxed_variants[i][2] .. "_double" + minetest.override_item(def, { _mcl_stripped_variant = def_variant_scraped }) + +end + diff --git a/mods/ITEMS/mcl_copper/init.lua b/mods/ITEMS/mcl_copper/init.lua index 937d262e2..01ece6d54 100644 --- a/mods/ITEMS/mcl_copper/init.lua +++ b/mods/ITEMS/mcl_copper/init.lua @@ -2,7 +2,7 @@ local path = minetest.get_modpath("mcl_copper") mcl_copper = {} -- initialize global variable. -dofile(path .. "/functions.lua") dofile(path .. "/nodes.lua") dofile(path .. "/items.lua") dofile(path .. "/crafting.lua") +dofile(path .. "/functions.lua") diff --git a/mods/ITEMS/mcl_copper/mod.conf b/mods/ITEMS/mcl_copper/mod.conf index 8cf5fd579..a48ee56f7 100644 --- a/mods/ITEMS/mcl_copper/mod.conf +++ b/mods/ITEMS/mcl_copper/mod.conf @@ -1,4 +1,4 @@ name = mcl_copper author = NO11 -depends = mcl_core, mcl_sounds, mcl_stairs, mcl_util +depends = mcl_core, mcl_sounds, mcl_stairs, mcl_util, mcl_oxidation description = Adds Copper Ore, blocks and items. diff --git a/mods/ITEMS/mcl_copper/nodes.lua b/mods/ITEMS/mcl_copper/nodes.lua index b4768e4cc..66f42ff41 100644 --- a/mods/ITEMS/mcl_copper/nodes.lua +++ b/mods/ITEMS/mcl_copper/nodes.lua @@ -35,7 +35,7 @@ minetest.register_node("mcl_copper:block", { _mcl_blast_resistance = 6, _mcl_hardness = 3, _mcl_oxidized_variant = "mcl_copper:block_exposed", - _mcl_copper_waxed_variant = "mcl_copper:waxed_block", + _mcl_waxed_variant = "mcl_copper:waxed_block", }) minetest.register_node("mcl_copper:waxed_block", { @@ -60,7 +60,7 @@ minetest.register_node("mcl_copper:block_exposed", { _mcl_blast_resistance = 6, _mcl_hardness = 5, _mcl_oxidized_variant = "mcl_copper:block_weathered", - _mcl_copper_waxed_variant = "mcl_copper:waxed_block_exposed", + _mcl_waxed_variant = "mcl_copper:waxed_block_exposed", _mcl_stripped_variant = "mcl_copper:block", }) @@ -86,7 +86,7 @@ minetest.register_node("mcl_copper:block_weathered", { _mcl_blast_resistance = 6, _mcl_hardness = 5, _mcl_oxidized_variant = "mcl_copper:block_oxidized", - _mcl_copper_waxed_variant = "mcl_copper:waxed_block_weathered", + _mcl_waxed_variant = "mcl_copper:waxed_block_weathered", _mcl_stripped_variant = "mcl_copper:block_exposed", }) @@ -107,11 +107,11 @@ minetest.register_node("mcl_copper:block_oxidized", { _doc_items_longdesc = S("Oxidized copper is a decorative block."), tiles = {"mcl_copper_oxidized.png"}, is_ground_content = false, - groups = {pickaxey = 2, building_block = 1, oxidizable = 1}, + groups = {pickaxey = 2, building_block = 1}, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, - _mcl_copper_waxed_variant = "mcl_copper:waxed_block_oxidized", + _mcl_waxed_variant = "mcl_copper:waxed_block_oxidized", _mcl_stripped_variant = "mcl_copper:block_weathered", }) @@ -137,7 +137,7 @@ minetest.register_node("mcl_copper:block_cut", { _mcl_blast_resistance = 6, _mcl_hardness = 5, _mcl_oxidized_variant = "mcl_copper:block_cut_exposed", - _mcl_copper_waxed_variant = "mcl_copper:waxed_block_cut", + _mcl_waxed_variant = "mcl_copper:waxed_block_cut", }) minetest.register_node("mcl_copper:waxed_block_cut", { @@ -161,7 +161,7 @@ minetest.register_node("mcl_copper:block_exposed_cut", { sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, - _mcl_copper_waxed_variant = "mcl_copper:waxed_block_exposed_cut", + _mcl_waxed_variant = "mcl_copper:waxed_block_exposed_cut", _mcl_oxidized_variant = "mcl_copper:block_cut_weathered", _mcl_stripped_variant = "mcl_copper:block_cut", }) @@ -189,7 +189,7 @@ minetest.register_node("mcl_copper:block_weathered_cut", { _mcl_hardness = 5, _mcl_stripped_variant = "mcl_copper:block_exposed_cut", _mcl_oxidized_variant = "mcl_copper:block_cut_oxidized", - _mcl_copper_waxed_variant = "mcl_copper:waxed_block_weathered_cut", + _mcl_waxed_variant = "mcl_copper:waxed_block_weathered_cut", }) minetest.register_node("mcl_copper:waxed_block_weathered_cut", { @@ -209,12 +209,12 @@ minetest.register_node("mcl_copper:block_oxidized_cut", { _doc_items_longdesc = S("Oxidized cut copper is a decorative block."), tiles = {"mcl_copper_oxidized_cut.png"}, is_ground_content = false, - groups = {pickaxey = 2, building_block = 1, oxidizable = 1}, + groups = {pickaxey = 2, building_block = 1}, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, _mcl_stripped_variant = "mcl_copper:block_weathered_cut", - _mcl_copper_waxed_variant = "mcl_copper:waxed_block_oxidized_cut", + _mcl_waxed_variant = "mcl_copper:waxed_block_oxidized_cut", }) minetest.register_node("mcl_copper:waxed_block_oxidized_cut", { @@ -272,7 +272,7 @@ mcl_stairs.register_slab("waxed_copper_weathered_cut", "mcl_copper:waxed_block_w S("Waxed Double Slab of Weathered Cut Copper")) mcl_stairs.register_slab("copper_oxidized_cut", "mcl_copper:block_oxidized_cut", - {pickaxey = 2, oxidizable = 1}, + {pickaxey = 2}, {"mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png"}, S("Slab of Oxidized Cut Copper"), nil, nil, nil, @@ -328,7 +328,7 @@ mcl_stairs.register_stair("waxed_copper_weathered_cut", "mcl_copper:waxed_block_ "woodlike") mcl_stairs.register_stair("copper_oxidized_cut", "mcl_copper:block_oxidized_cut", - {pickaxey = 2, oxidizable = 1}, + {pickaxey = 2}, {"mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png"}, S("Stairs of Oxidized Cut Copper"), nil, 6, nil, diff --git a/mods/ITEMS/mcl_honey/init.lua b/mods/ITEMS/mcl_honey/init.lua index e3b958a7d..54a431924 100644 --- a/mods/ITEMS/mcl_honey/init.lua +++ b/mods/ITEMS/mcl_honey/init.lua @@ -16,7 +16,9 @@ function mcl_honey.wax_block(pos, node, player, itemstack) local def = minetest.registered_nodes[node.name] - if not def or not def._mcl_copper_waxed_variant then + if def and def._mcl_waxed_variant then + node.name = def._mcl_waxed_variant + else return end From 0fba7eaed4ef4c90748f6e9d3b1599fce15cc00b Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Sat, 20 May 2023 09:59:28 -0600 Subject: [PATCH 153/155] Fix a few crashes, make the abm work, and revive the wax off advancement --- mods/CORE/mcl_oxidation/init.lua | 4 +-- mods/ITEMS/mcl_copper/functions.lua | 2 +- mods/ITEMS/mcl_copper/nodes.lua | 38 ++++++++++++++--------------- mods/ITEMS/mcl_honey/init.lua | 2 +- mods/ITEMS/mcl_tools/init.lua | 3 +++ 5 files changed, 26 insertions(+), 23 deletions(-) diff --git a/mods/CORE/mcl_oxidation/init.lua b/mods/CORE/mcl_oxidation/init.lua index f0e8a37e6..201d0260a 100644 --- a/mods/CORE/mcl_oxidation/init.lua +++ b/mods/CORE/mcl_oxidation/init.lua @@ -4,9 +4,9 @@ minetest.register_abm({ interval = 500, chance = 3, action = function(pos, node) - local def = minetest.registered_nodes[node] + local def = minetest.registered_nodes[node.name] if def and def._mcl_oxidized_variant then - minetest.swap_node(pos, { name = def._mcl_oxidized_varient, param2 = node.param2 }) + minetest.set_node(pos, { name = def._mcl_oxidized_variant, param2 = node.param2 }) end end, }) diff --git a/mods/ITEMS/mcl_copper/functions.lua b/mods/ITEMS/mcl_copper/functions.lua index 43fee2db7..0de387df4 100644 --- a/mods/ITEMS/mcl_copper/functions.lua +++ b/mods/ITEMS/mcl_copper/functions.lua @@ -34,7 +34,7 @@ for i = 1, #stair_oxidization do def_variant_oxidized = "mcl_stairs:stair_copper_" .. stair_oxidization[i][2] minetest.override_item(def, { _mcl_oxidized_variant = def_variant_oxidized }) - def_variant_waxed = "mcl_stairs:stair_waxed_copper_" .. stair_oxidization[i][2] + def_variant_waxed = "mcl_stairs:stair_waxed_copper_" .. stair_oxidization[i][1] minetest.override_item(def, { _mcl_waxed_variant = def_variant_waxed }) -- slabs diff --git a/mods/ITEMS/mcl_copper/nodes.lua b/mods/ITEMS/mcl_copper/nodes.lua index 66f42ff41..b8fa12e4d 100644 --- a/mods/ITEMS/mcl_copper/nodes.lua +++ b/mods/ITEMS/mcl_copper/nodes.lua @@ -43,7 +43,7 @@ minetest.register_node("mcl_copper:waxed_block", { _doc_items_longdesc = S("A block of copper is mostly a decorative block."), tiles = {"mcl_copper_block.png"}, is_ground_content = false, - groups = {pickaxey = 2, building_block = 1}, + groups = {pickaxey = 2, building_block = 1, waxed = 1}, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 3, @@ -69,7 +69,7 @@ minetest.register_node("mcl_copper:waxed_block_exposed", { _doc_items_longdesc = S("Exposed copper is a decorative block."), tiles = {"mcl_copper_exposed.png"}, is_ground_content = false, - groups = {pickaxey = 2, building_block = 1}, + groups = {pickaxey = 2, building_block = 1, waxed = 1}, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, @@ -95,7 +95,7 @@ minetest.register_node("mcl_copper:waxed_block_weathered", { _doc_items_longdesc = S("Weathered copper is a decorative block."), tiles = {"mcl_copper_weathered.png"}, is_ground_content = false, - groups = {pickaxey = 2, building_block = 1}, + groups = {pickaxey = 2, building_block = 1, waxed = 1}, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, @@ -120,7 +120,7 @@ minetest.register_node("mcl_copper:waxed_block_oxidized", { _doc_items_longdesc = S("Oxidized copper is a decorative block."), tiles = {"mcl_copper_oxidized.png"}, is_ground_content = false, - groups = {pickaxey = 2, building_block = 1}, + groups = {pickaxey = 2, building_block = 1, waxed = 1}, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, @@ -136,7 +136,7 @@ minetest.register_node("mcl_copper:block_cut", { sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, - _mcl_oxidized_variant = "mcl_copper:block_cut_exposed", + _mcl_oxidized_variant = "mcl_copper:block_exposed_cut", _mcl_waxed_variant = "mcl_copper:waxed_block_cut", }) @@ -145,7 +145,7 @@ minetest.register_node("mcl_copper:waxed_block_cut", { _doc_items_longdesc = S("Cut copper is a decorative block."), tiles = {"mcl_copper_block_cut.png"}, is_ground_content = false, - groups = {pickaxey = 2, building_block = 1}, + groups = {pickaxey = 2, building_block = 1, waxed = 1}, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, @@ -162,7 +162,7 @@ minetest.register_node("mcl_copper:block_exposed_cut", { _mcl_blast_resistance = 6, _mcl_hardness = 5, _mcl_waxed_variant = "mcl_copper:waxed_block_exposed_cut", - _mcl_oxidized_variant = "mcl_copper:block_cut_weathered", + _mcl_oxidized_variant = "mcl_copper:block_weathered_cut", _mcl_stripped_variant = "mcl_copper:block_cut", }) @@ -171,7 +171,7 @@ minetest.register_node("mcl_copper:waxed_block_exposed_cut", { _doc_items_longdesc = S("Exposed cut copper is a decorative block."), tiles = {"mcl_copper_exposed_cut.png"}, is_ground_content = false, - groups = {pickaxey = 2, building_block = 1}, + groups = {pickaxey = 2, building_block = 1, waxed = 1}, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, @@ -188,7 +188,7 @@ minetest.register_node("mcl_copper:block_weathered_cut", { _mcl_blast_resistance = 6, _mcl_hardness = 5, _mcl_stripped_variant = "mcl_copper:block_exposed_cut", - _mcl_oxidized_variant = "mcl_copper:block_cut_oxidized", + _mcl_oxidized_variant = "mcl_copper:block_oxidized_cut", _mcl_waxed_variant = "mcl_copper:waxed_block_weathered_cut", }) @@ -197,7 +197,7 @@ minetest.register_node("mcl_copper:waxed_block_weathered_cut", { _doc_items_longdesc = S("Weathered cut copper is a decorative block."), tiles = {"mcl_copper_weathered_cut.png"}, is_ground_content = false, - groups = {pickaxey = 2, building_block = 1}, + groups = {pickaxey = 2, building_block = 1, waxed = 1}, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, @@ -222,7 +222,7 @@ minetest.register_node("mcl_copper:waxed_block_oxidized_cut", { _doc_items_longdesc = S("Oxidized cut copper is a decorative block."), tiles = {"mcl_copper_oxidized_cut.png"}, is_ground_content = false, - groups = {pickaxey = 2, building_block = 1}, + groups = {pickaxey = 2, building_block = 1, waxed = 1}, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, @@ -237,7 +237,7 @@ mcl_stairs.register_slab("copper_cut", "mcl_copper:block_cut", S("Double Slab of Cut Copper")) mcl_stairs.register_slab("waxed_copper_cut", "mcl_copper:waxed_block_cut", - {pickaxey = 2}, + {pickaxey = 2, waxed = 1}, {"mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png"}, S("Waxed Slab of Cut Copper"), nil, nil, nil, @@ -251,7 +251,7 @@ mcl_stairs.register_slab("copper_exposed_cut", "mcl_copper:block_exposed_cut", S("Double Slab of Exposed Cut Copper")) mcl_stairs.register_slab("waxed_copper_exposed_cut", "mcl_copper:waxed_block_exposed_cut", - {pickaxey = 2}, + {pickaxey = 2, waxed = 1}, {"mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png"}, S("Waxed Slab of Exposed Cut Copper"), nil, nil, nil, @@ -265,7 +265,7 @@ mcl_stairs.register_slab("copper_weathered_cut", "mcl_copper:block_weathered_cut S("Double Slab of Weathered Cut Copper")) mcl_stairs.register_slab("waxed_copper_weathered_cut", "mcl_copper:waxed_block_weathered_cut", - {pickaxey = 2}, + {pickaxey = 2, waxed = 1}, {"mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png"}, S("Waxed Slab of Weathered Cut Copper"), nil, nil, nil, @@ -279,7 +279,7 @@ mcl_stairs.register_slab("copper_oxidized_cut", "mcl_copper:block_oxidized_cut", S("Double Slab of Oxidized Cut Copper")) mcl_stairs.register_slab("waxed_copper_oxidized_cut", "mcl_copper:waxed_block_oxidized_cut", - {pickaxey = 2}, + {pickaxey = 2, waxed = 1}, {"mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png"}, S("Waxed Slab of Oxidized Cut Copper"), nil, nil, nil, @@ -293,7 +293,7 @@ mcl_stairs.register_stair("copper_cut", "mcl_copper:block_cut", "woodlike") mcl_stairs.register_stair("waxed_copper_cut", "mcl_copper:waxed_block_cut", - {pickaxey = 2}, + {pickaxey = 2, waxed = 1}, {"mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png"}, S("Waxed Stairs of Cut Copper"), nil, 6, nil, @@ -307,7 +307,7 @@ mcl_stairs.register_stair("copper_exposed_cut", "mcl_copper:block_exposed_cut", "woodlike") mcl_stairs.register_stair("waxed_copper_exposed_cut", "mcl_copper:waxed_block_exposed_cut", - {pickaxey = 2}, + {pickaxey = 2, waxed = 1}, {"mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png"}, S("Waxed Stairs of Exposed Cut Copper"), nil, 6, nil, @@ -321,7 +321,7 @@ mcl_stairs.register_stair("copper_weathered_cut", "mcl_copper:block_weathered_cu "woodlike") mcl_stairs.register_stair("waxed_copper_weathered_cut", "mcl_copper:waxed_block_weathered_cut", - {pickaxey = 2}, + {pickaxey = 2, waxed = 1}, {"mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png"}, S("Waxed Stairs of Weathered Cut Copper"), nil, 6, nil, @@ -335,7 +335,7 @@ mcl_stairs.register_stair("copper_oxidized_cut", "mcl_copper:block_oxidized_cut" "woodlike") mcl_stairs.register_stair("waxed_copper_oxidized_cut", "mcl_copper:waxed_block_oxidized_cut", - {pickaxey = 2}, + {pickaxey = 2, waxed = 1}, {"mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png"}, S("Waxed Stairs of Oxidized Cut Copper"), nil, 6, nil, diff --git a/mods/ITEMS/mcl_honey/init.lua b/mods/ITEMS/mcl_honey/init.lua index 54a431924..ad507439e 100644 --- a/mods/ITEMS/mcl_honey/init.lua +++ b/mods/ITEMS/mcl_honey/init.lua @@ -22,7 +22,7 @@ function mcl_honey.wax_block(pos, node, player, itemstack) return end - node.name = def._mcl_copper_waxed_variant + node.name = def._mcl_waxed_variant minetest.set_node(pos, node) awards.unlock(player:get_player_name(), "mcl:wax_on") if not minetest.is_creative_enabled(player:get_player_name()) then diff --git a/mods/ITEMS/mcl_tools/init.lua b/mods/ITEMS/mcl_tools/init.lua index de0ea6261..5f96fa3fa 100644 --- a/mods/ITEMS/mcl_tools/init.lua +++ b/mods/ITEMS/mcl_tools/init.lua @@ -387,6 +387,9 @@ local function make_stripped_trunk(itemstack, placer, pointed_thing) return itemstack else minetest.swap_node(pointed_thing.under, {name=noddef._mcl_stripped_variant, param2=node.param2}) + if minetest.get_item_group(node_name, "waxed") ~= 0 then + awards.unlock(placer:get_player_name(), "mcl:wax_off") + end if not minetest.is_creative_enabled(placer:get_player_name()) then -- Add wear (as if digging a axey node) local toolname = itemstack:get_name() From 46f6731cf51c36ff4e1befe97020c6dc883de117 Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Sat, 20 May 2023 10:44:54 -0600 Subject: [PATCH 154/155] Make oxidized slabs and stairs waxable, and fix the copper oxidation dupe --- mods/ITEMS/mcl_copper/functions.lua | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_copper/functions.lua b/mods/ITEMS/mcl_copper/functions.lua index 0de387df4..bd289f60f 100644 --- a/mods/ITEMS/mcl_copper/functions.lua +++ b/mods/ITEMS/mcl_copper/functions.lua @@ -18,7 +18,7 @@ local slab_oxidization = { { "exposed_cut_top", "weathered_cut_top" }, { "exposed_cut_double", "weathered_cut_double" }, { "weathered_cut", "oxidized_cut" }, - { "weathered_cut_top", "oxidized_cut_double" }, + { "weathered_cut_top", "oxidized_cut_top" }, { "weathered_cut_double", "oxidized_cut_double" }, } @@ -106,3 +106,27 @@ for i = 1, #waxed_variants do end +-- Waxed Oxidized Slabs and Stairs +local oxidized_slabs = { + "oxidized_cut", + "oxidized_cut_double", + "oxidized_cut_top" +} + +for i = 1, #oxidized_slabs do + def = "mcl_stairs:slab_copper_" .. oxidized_slabs[i] + def_variant_waxed = "mcl_stairs:slab_waxed_copper_" .. oxidized_slabs[i] + minetest.override_item(def, { _mcl_waxed_variant = def_variant_waxed }) +end + +local oxidized_stairs = { + "oxidized_cut", + "oxidized_cut_inner", + "oxidized_cut_outer" +} + +for i = 1, #oxidized_stairs do + def = "mcl_stairs:stair_copper_" .. oxidized_stairs[i] + def_variant_waxed = "mcl_stairs:stair_waxed_copper_" .. oxidized_stairs[i] + minetest.override_item(def, { _mcl_waxed_variant = def_variant_waxed }) +end From 75e4000b308cdd488a96dfb0e962dd5a2cc69792 Mon Sep 17 00:00:00 2001 From: PrairieWind Date: Thu, 1 Jun 2023 10:18:36 -0600 Subject: [PATCH 155/155] Fix the scraped variants of certain waxed copper blocks Also fix some wording in the oxidation api documentation --- mods/CORE/mcl_oxidation/README.md | 4 ++-- mods/ITEMS/mcl_copper/nodes.lua | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/mods/CORE/mcl_oxidation/README.md b/mods/CORE/mcl_oxidation/README.md index 70d9c24fe..3f3291b19 100644 --- a/mods/CORE/mcl_oxidation/README.md +++ b/mods/CORE/mcl_oxidation/README.md @@ -6,9 +6,9 @@ To take advantage of the actual oxidization, put `oxidizable = 1` into the list You would also need to put `_mcl_oxidized_variant = itemstring of node this node will oxidize into` into the node definition. For example, a copper block oxidizes into exposed copper, so the defintion would be `_mcl_oxidized_variant = "mcl_copper:block_exposed"`. -To utilize the ability to wax the block for protection from oxidization, put `mcl_waxed_varient = item string of waxed varient of node` into the node definition table. +To utilize the ability to wax the block for protection from oxidization, put `mcl_waxed_variant = item string of waxed variant of node` into the node definition table. For example, Copper Blocks have the definition arguement of `_mcl_waxed_variant = "mcl_copper:waxed_block"`. For waxed nodes, scraping is easy. Start by putting `waxed = 1` into the list of groups of the waxed node. -Next put `_mcl_stripped_variant = item string of the unwaxed varient of the node` into the defintion table. +Next put `_mcl_stripped_variant = item string of the unwaxed variant of the node` into the defintion table. Wxaed Copper Blocks can be scrapped into normal Copper Blocks because of the definition `_mcl_stripped_variant = "mcl_copper:block"`. diff --git a/mods/ITEMS/mcl_copper/nodes.lua b/mods/ITEMS/mcl_copper/nodes.lua index b8fa12e4d..af5a49a1c 100644 --- a/mods/ITEMS/mcl_copper/nodes.lua +++ b/mods/ITEMS/mcl_copper/nodes.lua @@ -73,7 +73,7 @@ minetest.register_node("mcl_copper:waxed_block_exposed", { sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, - _mcl_stripped_variant = "mcl_copper:block", + _mcl_stripped_variant = "mcl_copper:block_exposed", }) minetest.register_node("mcl_copper:block_weathered", { @@ -99,7 +99,7 @@ minetest.register_node("mcl_copper:waxed_block_weathered", { sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, - _mcl_stripped_variant = "mcl_copper:block_exposed", + _mcl_stripped_variant = "mcl_copper:block_weathered", }) minetest.register_node("mcl_copper:block_oxidized", { @@ -124,7 +124,7 @@ minetest.register_node("mcl_copper:waxed_block_oxidized", { sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, - _mcl_stripped_variant = "mcl_copper:block_weathered", + _mcl_stripped_variant = "mcl_copper:block_oxidized", }) minetest.register_node("mcl_copper:block_cut", { @@ -175,7 +175,7 @@ minetest.register_node("mcl_copper:waxed_block_exposed_cut", { sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, - _mcl_stripped_variant = "mcl_copper:block_cut", + _mcl_stripped_variant = "mcl_copper:block_exposed_cut", }) minetest.register_node("mcl_copper:block_weathered_cut", { @@ -201,7 +201,7 @@ minetest.register_node("mcl_copper:waxed_block_weathered_cut", { sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, - _mcl_stripped_variant = "mcl_copper:block_exposed_cut", + _mcl_stripped_variant = "mcl_copper:block_weathered_cut", }) minetest.register_node("mcl_copper:block_oxidized_cut", { @@ -226,7 +226,7 @@ minetest.register_node("mcl_copper:waxed_block_oxidized_cut", { sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, - _mcl_stripped_variant = "mcl_copper:block_weathered_cut", + _mcl_stripped_variant = "mcl_copper:block_oxidized_cut", }) mcl_stairs.register_slab("copper_cut", "mcl_copper:block_cut",