Merge branch 'master' into emerald-desc

This commit is contained in:
ztianyang 2021-09-20 01:54:00 +00:00
commit ac8383dd4b
62 changed files with 1002 additions and 398 deletions

@ -52,17 +52,17 @@ Each mod must provide `mod.conf`.
Each mod which add API functions should store functions inside a global table named like the mod.
Public functions should not use self references but rather just access the table directly.
Functions should be defined in this way:
```
```lua
function mcl_xyz.stuff(param) end
```
Insteed of this way:
```
```lua
mcl_xyz.stuff = function(param) end
```
Indentation must be unified, more likely with tabs.
Time sensitive mods should make a local copy of most used API functions to improve performances.
```
```lua
local vector = vector
local get_node = minetest.get_node
```

@ -84,7 +84,7 @@ local function attach_object(self, obj)
end
end, name)
obj:set_look_horizontal(yaw)
mcl_tmp_message.message(obj, S("Sneak to dismount"))
mcl_title.set(obj, "actionbar", {text=S("Sneak to dismount"), color="white", stay=60})
else
obj:get_luaentity()._old_visual_size = visual_size
end

@ -6,6 +6,7 @@ Boats are used to travel on the surface of water.=Les bateaux sont utilisés pou
Dark Oak Boat=Bateau en Chêne Noir
Jungle Boat=Bateau en Acajou
Oak Boat=Bateau en Chêne
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Rightclick the boat again to leave it, punch the boat to make it drop as an item.=Faites un clic droit sur une source d'eau pour placer le bateau. Faites un clic droit sur le bateau pour y entrer. Utilisez [Gauche] et [Droite] pour diriger, [Avant] pour accélérer et [Arrière] pour ralentir ou reculer. Cliquez de nouveau avec le bouton droit sur le bateau pour le quitter, frappez le bateau pour le faire tomber en tant qu'objet.
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Faites un clic droit sur une source d'eau pour placer le bateau. Faites un clic droit sur le bateau pour y entrer. Utilisez [Gauche] et [Droite] pour diriger, [Avant] pour accélérer et [Arrière] pour ralentir ou reculer. Utilisez [Sneak] pour le quitter, frappez le bateau pour le faire tomber en tant qu'objet.
Spruce Boat=Bateau en Sapin
Water vehicle=Véhicule aquatique
Water vehicle=Véhicule aquatique
Sneak to dismount=

@ -1,7 +1,7 @@
name = mcl_boats
author = PilzAdam
description = Adds drivable boats.
depends = mcl_player, flowlib
depends = mcl_player, flowlib, mcl_title
optional_depends = mcl_core, doc_identifier

@ -67,14 +67,9 @@ function mcl_burning.set_on_fire(obj, burn_time)
end
if not storage.burn_time or burn_time >= storage.burn_time then
if obj:is_player() and not storage.fire_hud_id then
storage.fire_hud_id = obj:hud_add({
hud_elem_type = "image",
position = {x = 0.5, y = 0.5},
scale = {x = -100, y = -100},
text = "mcl_burning_entity_flame_animated.png^[opacity:180^[verticalframe:" .. mcl_burning.animation_frames .. ":" .. 1,
z_index = 1000,
})
if obj:is_player() then
mcl_burning.channels[obj]:send_all(tostring(mcl_burning.animation_frames))
mcl_burning.channels[obj]:send_all("start")
end
storage.burn_time = burn_time
storage.fire_damage_timer = 0
@ -95,7 +90,6 @@ function mcl_burning.set_on_fire(obj, burn_time)
fire_entity:set_properties({visual_size = size})
fire_entity:set_attach(obj, "", offset, {x = 0, y = 0, z = 0})
local fire_luaentity = fire_entity:get_luaentity()
fire_luaentity:update_frame(obj, storage)
for _, other in pairs(minetest.get_objects_inside_radius(fire_entity:get_pos(), 0)) do
local other_luaentity = other:get_luaentity()
@ -111,9 +105,7 @@ function mcl_burning.extinguish(obj)
if mcl_burning.is_burning(obj) then
local storage = mcl_burning.get_storage(obj)
if obj:is_player() then
if storage.fire_hud_id then
obj:hud_remove(storage.fire_hud_id)
end
mcl_burning.channels[obj]:send_all("stop")
mcl_burning.storage[obj] = {}
else
storage.burn_time = nil
@ -143,4 +135,4 @@ function mcl_burning.tick(obj, dtime, storage)
end
end
end
end
end

@ -7,6 +7,7 @@ local get_item_group = minetest.get_item_group
mcl_burning = {
storage = {},
channels = {},
animation_frames = tonumber(minetest.settings:get("fire_animation_frames")) or 8
}
@ -54,12 +55,11 @@ minetest.register_on_joinplayer(function(player)
end
mcl_burning.storage[player] = storage
mcl_burning.channels[player] = minetest.mod_channel_join("mcl_burning:" .. player:get_player_name())
end)
minetest.register_on_leaveplayer(function(player)
local storage = mcl_burning.storage[player]
storage.fire_hud_id = nil
player:get_meta():set_string("mcl_burning:data", minetest.serialize(storage))
player:get_meta():set_string("mcl_burning:data", minetest.serialize(mcl_burning.storage[player]))
mcl_burning.storage[player] = nil
end)
@ -68,27 +68,28 @@ minetest.register_entity("mcl_burning:fire", {
initial_properties = {
physical = false,
collisionbox = {0, 0, 0, 0, 0, 0},
visual = "cube",
visual = "upright_sprite",
textures = {
name = "mcl_burning_entity_flame_animated.png",
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 1.0,
},
},
spritediv = {x = 1, y = mcl_burning.animation_frames},
pointable = false,
glow = -1,
backface_culling = false,
},
animation_frame = 0,
animation_timer = 0,
on_step = function(self, dtime)
local parent, storage = self:sanity_check()
if parent then
self.animation_timer = self.animation_timer + dtime
if self.animation_timer >= 0.1 then
self.animation_timer = 0
self.animation_frame = self.animation_frame + 1
if self.animation_frame > mcl_burning.animation_frames - 1 then
self.animation_frame = 0
end
self:update_frame(parent, storage)
end
else
on_activate = function(self)
self.object:set_sprite({x = 0, y = 0}, mcl_burning.animation_frames, 1.0 / mcl_burning.animation_frames)
end,
on_step = function(self)
if not self:sanity_check() then
self.object:remove()
end
end,
@ -96,23 +97,15 @@ minetest.register_entity("mcl_burning:fire", {
local parent = self.object:get_attach()
if not parent then
return
return false
end
local storage = mcl_burning.get_storage(parent)
if not storage or not storage.burn_time then
return
return false
end
return parent, storage
end,
update_frame = function(self, parent, storage)
local frame_overlay = "^[opacity:180^[verticalframe:" .. mcl_burning.animation_frames .. ":" .. self.animation_frame
local fire_texture = "mcl_burning_entity_flame_animated.png" .. frame_overlay
self.object:set_properties({textures = {"blank.png", "blank.png", fire_texture, fire_texture, fire_texture, fire_texture}})
if parent:is_player() then
parent:hud_change(storage.fire_hud_id, "text", "mcl_burning_hud_flame_animated.png" .. frame_overlay)
end
return true
end,
})

@ -480,7 +480,7 @@ minetest.register_entity(":__builtin:item", {
end,
get_staticdata = function(self)
return minetest.serialize({
local data = minetest.serialize({
itemstring = self.itemstring,
always_collect = self.always_collect,
age = self.age,
@ -488,6 +488,39 @@ minetest.register_entity(":__builtin:item", {
_flowing = self._flowing,
_removed = self._removed,
})
-- sfan5 guessed that the biggest serializable item
-- entity would have a size of 65530 bytes. This has
-- been experimentally verified to be still too large.
--
-- anon5 has calculated that the biggest serializable
-- item entity has a size of exactly 65487 bytes:
--
-- 1. serializeString16 can handle max. 65535 bytes.
-- 2. The following engine metadata is always saved:
-- • 1 byte (version)
-- • 2 byte (length prefix)
-- • 14 byte “__builtin:item”
-- • 4 byte (length prefix)
-- • 2 byte (health)
-- • 3 × 4 byte = 12 byte (position)
-- • 4 byte (yaw)
-- • 1 byte (version 2)
-- • 2 × 4 byte = 8 byte (pitch and roll)
-- 3. This leaves 65487 bytes for the serialization.
if #data > 65487 then -- would crash the engine
local stack = ItemStack(self.itemstring)
stack:get_meta():from_table(nil)
self.itemstring = stack:to_string()
minetest.log(
"warning",
"Overlong item entity metadata removed: “" ..
self.itemstring ..
"” had serialized length of " ..
#data
)
return self:get_staticdata()
end
return data
end,
on_activate = function(self, staticdata, dtime_s)
@ -575,7 +608,7 @@ minetest.register_entity(":__builtin:item", {
return true
end,
on_step = function(self, dtime)
on_step = function(self, dtime, moveresult)
if self._removed then
self.object:set_properties({
physical = false
@ -642,6 +675,18 @@ minetest.register_entity(":__builtin:item", {
end
end
-- Destroy item when it collides with a cactus
if moveresult and moveresult.collides then
for _, collision in pairs(moveresult.collisions) do
local pos = collision.node_pos
if collision.type == "node" and minetest.get_node(pos).name == "mcl_core:cactus" then
self._removed = true
self.object:remove()
return
end
end
end
-- Push item out when stuck inside solid opaque node
if def and def.walkable and def.groups and def.groups.opaque == 1 then
local shootdir

@ -646,7 +646,7 @@ register_minecart(
if player then
mcl_player.player_set_animation(player, "sit" , 30)
player:set_eye_offset({x=0, y=-5.5, z=0},{x=0, y=-4, z=0})
mcl_tmp_message.message(clicker, S("Sneak to dismount"))
mcl_title.set(clicker, "actionbar", {text=S("Sneak to dismount"), color="white", stay=60})
end
end, name)
end

@ -33,3 +33,4 @@ Activates minecarts when powered=Active les wagonnets lorsqu'il est alimenté
Emits redstone power when a minecart is detected=Émet de l'énergie redstone lorsqu'un wagonnet est détecté
Vehicle for fast travel on rails=Véhicule pour voyager rapidement sur rails
Can be ignited by tools or powered activator rail=Peut être allumé par des outils ou un rail d'activation motorisé
Sneak to dismount=

@ -1,6 +1,6 @@
name = mcl_minecarts
author = Krock
description = Minecarts are vehicles to move players quickly on rails.
depends = mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons
depends = mcl_title, mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons
optional_depends = doc_identifier, mcl_wip

@ -28,6 +28,7 @@ Pig=
Polar Bear=
Rabbit=
Killer Bunny=
The Killer Bunny=
Sheep=
Shulker=
Silverfish=

@ -233,4 +233,4 @@ mobs:spawn(spawn_grass)
mobs:register_egg("mobs_mc:rabbit", S("Rabbit"), "mobs_mc_spawn_icon_rabbit.png", 0)
-- Note: This spawn egg does not exist in Minecraft
mobs:register_egg("mobs_mc:killer_bunny", S("Killer Bunny"), "mobs_mc_spawn_icon_rabbit.png^[colorize:#FF0000:192", 0) -- TODO: Update inventory image
mobs:register_egg("mobs_mc:killer_bunny", S("Killer Bunny"), "mobs_mc_spawn_icon_rabbit_caerbannog.png", 0)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

@ -2,7 +2,7 @@
Using it as fuel turns it into: @1.=L'utiliser comme combustible le transforme en : @1.
@1 seconds=@1 secondes
# Item count times item name
%@1×@2=%@1×@
@1×@2=@1×@
# Itemname (25%)
@1 (@2%)=@1 (@2%)
# Itemname (<0.5%)

@ -0,0 +1,24 @@
# mcl_item_id
Show the item ID of an item in the description.
With this API, you can register a different name space than "mineclone" for your mod.
## mcl_item_id.set_mod_namespace(modname, namespace)
Set a name space for all items in a mod.
* param1: the modname
* param2: (optional) string of the desired name space, if nil, it is the name of the mod
## mcl_item_id.get_mod_namespace(modname)
Get the name space of a mod registered with mcl_item_id.set_mod_namespace(modname, namespace).
* param1: the modname
### Examples:
The name of the mod is "mod" which registered an item called "mod:itemname".
* mcl_item_id.set_mod_namespace("mod", "mymod") will show "mymod:itemname" in the description of "mod:itemname"
* mcl_item_id.set_mod_namespace(minetest.get_current_modname()) will show "mod:itemname" in the description of "mod:itemname"
* mcl_item_id.get_mod_namespace(minetest.get_current_modname()) will return "mod"
(If no namespace is set by a mod, mcl_item_id.get_mod_namespace(minetest.get_current_modname()) will return "mineclone")

@ -0,0 +1,62 @@
mcl_item_id = {
mod_namespaces = {},
}
local game = "mineclone"
function mcl_item_id.set_mod_namespace(modname, namespace)
local namespace = namespace or modname
mcl_item_id.mod_namespaces[modname] = namespace
end
function mcl_item_id.get_mod_namespace(modname)
local namespace = mcl_item_id.mod_namespaces[modname]
if namespace then
return namespace
else
return game
end
end
local same_id = {
enchanting = { "table" },
experience = { "bottle" },
heads = { "skeleton", "zombie", "creeper", "wither_skeleton" },
mobitems = { "rabbit", "chicken" },
walls = {
"andesite", "brick", "cobble", "diorite", "endbricks",
"granite", "mossycobble", "netherbrick", "prismarine",
"rednetherbrick", "redsandstone", "sandstone",
"stonebrick", "stonebrickmossy",
},
wool = {
"black", "blue", "brown", "cyan", "green",
"grey", "light_blue", "lime", "magenta", "orange",
"pink", "purple", "red", "silver", "white", "yellow",
},
}
tt.register_snippet(function(itemstring)
local def = minetest.registered_items[itemstring]
local item_split = itemstring:find(":")
local id_string = itemstring:sub(item_split)
local id_modname = itemstring:sub(1, item_split - 1)
local new_id = game .. id_string
local mod_namespace = mcl_item_id.get_mod_namespace(id_modname)
for mod, ids in pairs(same_id) do
for _, id in pairs(ids) do
if itemstring == "mcl_" .. mod .. ":" .. id then
new_id = game .. ":" .. id .. "_" .. mod:gsub("s", "")
end
end
end
if mod_namespace ~= game then
new_id = mod_namespace .. id_string
end
if mod_namespace ~= id_modname then
minetest.register_alias_force(new_id, itemstring)
end
if minetest.settings:get_bool("mcl_item_id_debug", false) then
return new_id, "#555555"
end
end)

@ -0,0 +1,3 @@
name = mcl_item_id
author = NO11
depends = tt

@ -45,3 +45,4 @@ Mining durability: @1=Grabehaltbarkeit: @1
Block breaking strength: @1=Blockbruchstärke: @1
@1 uses=@1 Verwendungen
Unlimited uses=Unbegrenzte Verwendungen
Durability: @1=Haltbarkeit: @1

@ -45,3 +45,4 @@ Mining durability: @1=
Block breaking strength: @1=
@1 uses=
Unlimited uses=
Durability: @1=

@ -107,3 +107,8 @@ tt.register_snippet(function(itemstring)
end
end)
tt.register_snippet(function(itemstring, _, itemstack)
if itemstring:sub(1, 23) == "mcl_fishing:fishing_rod" or itemstring:sub(1, 12) == "mcl_bows:bow" then
return S("Durability: @1", S("@1 uses", mcl_util.calculate_durability(itemstack or ItemStack(itemstring))))
end
end)

@ -425,6 +425,7 @@ function hb.hide_hudbar(player, identifier)
local name = player:get_player_name()
local hudtable = hb.get_hudtable(identifier)
if hudtable == nil then return false end
if hudtable.hudstate[name].hidden == true then return true end
if hb.settings.bar_type == "progress_bar" then
if hudtable.hudids[name].icon then
player:hud_change(hudtable.hudids[name].icon, "scale", {x=0,y=0})
@ -443,6 +444,7 @@ function hb.unhide_hudbar(player, identifier)
local name = player:get_player_name()
local hudtable = hb.get_hudtable(identifier)
if hudtable == nil then return false end
if hudtable.hudstate[name].hidden == false then return true end
local value = hudtable.hudstate[name].value
local max = hudtable.hudstate[name].max
if hb.settings.bar_type == "progress_bar" then

@ -7,6 +7,7 @@ Creator of MineClone2=Schöpfer von MineClone2
Developers=Entwickler
Jump to speed up (additionally sprint)=Springen, um zu beschleunigen (zusätzlich sprinten)
Maintainers=Betreuer
MineClone5=MineClone5
Original Mod Authors=Original-Mod-Autoren
Sneak to skip=Schleichen zum Überspringen
Textures=Texturen

@ -0,0 +1,14 @@
# textdomain: mcl_credits
3D Models=
A faithful Open Source clone of Minecraft=
Contributors=
Creator of MineClone=
Creator of MineClone2=
Developers=
Jump to speed up (additionally sprint)=
Maintainers=
MineClone5=
Original Mod Authors=
Sneak to skip=
Textures=
Translations=

@ -0,0 +1,14 @@
# textdomain: mcl_credits
3D Models=Modèles 3D
A faithful Open Source clone of Minecraft=Un clone open source de Minecraft
Contributors=Contributeurs
Creator of MineClone=Créateur de MineClone
Creator of MineClone2=Créateur de MineClone2
Developers=Développeurs
Jump to speed up (additionally sprint)=Saut pour accélérer (peut être combiné avec sprint)
Maintainers=Mainteneurs
MineClone5=MineClone5
Original Mod Authors=Auteurs des mods originaux
Sneak to skip=Shift pour passer
Textures=Textures
Translations=Traductions

@ -0,0 +1,14 @@
# textdomain: mcl_credits
3D Models=
A faithful Open Source clone of Minecraft=
Contributors=
Creator of MineClone=
Creator of MineClone2=
Developers=
Jump to speed up (additionally sprint)=
Maintainers=
MineClone5=
Original Mod Authors=
Sneak to skip=
Textures=
Translations=

@ -0,0 +1,14 @@
# textdomain: mcl_credits
3D Models=
A faithful Open Source clone of Minecraft=
Contributors=
Creator of MineClone=
Creator of MineClone2=
Developers=
Jump to speed up (additionally sprint)=
Maintainers=
MineClone5=
Original Mod Authors=
Sneak to skip=
Textures=
Translations=

50
mods/HUD/mcl_title/API.md Normal file

@ -0,0 +1,50 @@
# mcl_title
Allow mods to show messages in the hud of players.
## mcl_title.set(player, type, data)
Show a hud message of `type` to player `player` with `data` as params.
The element will stay for the per-player param `stay` or `data.stay` (in gametick which is 1/20 second).
Here is a usage exemple:
```lua
--show a title in the HUD with minecraft color "gold"
mcl_title.set(player, "title", {text="dummy text", color="gold"})
--show a subtitle in the HUD with hex color "#612D2D"
mcl_title.set(player, "subtitle", {text="dummy subtitle", color="#612D2D"})
--show an actionbar in the HUD (above the hotbar) with minecraft color "red"
mcl_title.set(player, "subtitle", {text="dummy actionbar", color="red"})
--show a title in the HUD with minecraft color "gold" staying for 3 seconds (override stay setting)
mcl_title.set(player, "title", {text="dummy text", color="gold", stay=60})
```
## mcl_title.remove(player, type)
Hide HUD element of type `type` for player `player`.
## mcl_title.clear(player)
Remove every title/subtitle/actionbar from a player.
Basicaly run `mcl_title.remove(player, type)` for every type.
## mcl_title.params_set(player, params)
Allow mods to set `stay` and upcomming `fadeIn`/`fadeOut` params.
```lua
mcl_title.params_set(player, {stay = 600}) --elements with no 'data.stay' field will stay during 30s (600/20)
```
## mcl_title.params_get(player)
Get `stay` and upcomming `fadeIn` and `fadeOut` params of a player as a table.
```lua
mcl_title.params_get(player)
```

236
mods/HUD/mcl_title/init.lua Normal file

@ -0,0 +1,236 @@
--Based on:
--https://www.digminecraft.com/game_commands/title_command.php
--https://youtu.be/oVrtQRO2hpY
--TODO: use SSCSM to reduce lag and network trafic (just send modchannel messages)
--TODO: fadeIn and fadeOut animation (needs engine change: SSCSM or native support)
--TODO: allow obfuscating text (needs engine change: SSCSM or native support)
--TODO: allow colorizing and styling of part of the text (NEEDS ENGINE CHANGE!!!)
--TODO: exactly mc like layout
--Note that the table storing timeouts use playername as index insteed of player objects (faster)
--This is intended in order to speedup the process of removing HUD elements the the timeout is up
local huds_idx = {}
local hud_hide_timeouts = {}
hud_hide_timeouts.title = {}
hud_hide_timeouts.subtitle = {}
hud_hide_timeouts.actionbar = {}
huds_idx.title = {}
huds_idx.subtitle = {}
huds_idx.actionbar = {}
mcl_title = {}
mcl_title.defaults = {fadein = 10, stay = 70, fadeout = 20}
mcl_title.layout = {}
mcl_title.layout.title = {position = {x = 0.5, y = 0.5}, alignment = {x = 0, y = -1.3}, size = 7}
mcl_title.layout.subtitle = {position = {x = 0.5, y = 0.5}, alignment = {x = 0, y = 1.7}, size = 4}
mcl_title.layout.actionbar = {position = {x = 0.5, y = 1}, alignment = {x = 0, y = 0}, size = 1}
local get_color = mcl_util.get_color
--local string = string
local pairs = pairs
local function gametick_to_secondes(gametick)
if gametick then
return gametick / 20
else
return nil
end
end
--https://github.com/minetest/minetest/blob/b3b075ea02034306256b486dd45410aa765f035a/doc/lua_api.txt#L8477
--[[
local function style_to_bits(bold, italic)
if bold then
if italic then
return 3
else
return 1
end
else
if italic then
return 2
else
return 0
end
end
end
]]
--PARAMS SYSTEM
local player_params = {}
minetest.register_on_joinplayer(function(player)
--local playername = player:get_player_name()
player_params[player] = {
stay = mcl_title.defaults.stay,
--fadeIn = mcl_title.defaults.fadein,
--fadeOut = mcl_title.defaults.fadeout,
}
local _, hex_color = get_color("white")
huds_idx.title[player] = player:hud_add({
hud_elem_type = "text",
position = mcl_title.layout.title.position,
alignment = mcl_title.layout.title.alignment,
text = "",
--style = 0,
size = {x = mcl_title.layout.title.size},
number = hex_color,
z_index = 100,
})
huds_idx.subtitle[player] = player:hud_add({
hud_elem_type = "text",
position = mcl_title.layout.subtitle.position,
alignment = mcl_title.layout.subtitle.alignment,
text = "",
--style = 0,
size = {x = mcl_title.layout.subtitle.size},
number = hex_color,
z_index = 100,
})
huds_idx.actionbar[player] = player:hud_add({
hud_elem_type = "text",
position = mcl_title.layout.actionbar.position,
offset = {x = 0, y = -210},
alignment = mcl_title.layout.actionbar.alignment,
--style = 0,
text = "",
size = {x = mcl_title.layout.actionbar.size},
number = hex_color,
z_index = 100,
})
end)
minetest.register_on_leaveplayer(function(player)
local playername = player:get_player_name()
--remove player params from the list
player_params[player] = nil
--remove HUD idx from the list (HUD elements are removed by the engine)
huds_idx.title[player] = nil
huds_idx.subtitle[player] = nil
huds_idx.actionbar[player] = nil
--remove timers from list
hud_hide_timeouts.title[playername] = nil
hud_hide_timeouts.subtitle[playername] = nil
hud_hide_timeouts.actionbar[playername] = nil
end)
function mcl_title.params_set(player, data)
player_params[player] = {
stay = data.stay or mcl_title.defaults.stay,
--fadeIn = data.fadeIn or mcl_title.defaults.fadein,
--fadeOut = data.fadeOut or mcl_title.defaults.fadeout,
}
end
function mcl_title.params_get(player)
return player_params[player]
end
--API FUNCTIONS
function mcl_title.set(player, type, data)
if not data.color then
data.color = "white"
end
local _, hex_color = get_color(data.color)
if not hex_color then
return false
end
player:hud_change(huds_idx[type][player], "text", data.text)
player:hud_change(huds_idx[type][player], "number", hex_color)
--apply bold and italic
--player:hud_change(huds_idx[type][player], "style", style_to_bits(data.bold, data.italic))
hud_hide_timeouts[type][player:get_player_name()] = gametick_to_secondes(data.stay) or gametick_to_secondes(mcl_title.params_get(player).stay)
return true
end
function mcl_title.remove(player, type)
if player then
player:hud_change(huds_idx[type][player], "text", "")
--player:hud_change(huds_idx[type][player], "style", 0) --no styling
end
end
function mcl_title.clear(player)
mcl_title.remove(player, "title")
mcl_title.remove(player, "subtitle")
mcl_title.remove(player, "actionbar")
end
minetest.register_on_dieplayer(function(player)
mcl_title.clear(player)
end)
minetest.register_globalstep(function(dtime)
local new_timeouts = {
title = {},
subtitle = {},
actionbar = {},
}
for element, content in pairs(hud_hide_timeouts) do
for name, timeout in pairs(content) do
timeout = timeout - dtime
if timeout <= 0 then
local player = minetest.get_player_by_name(name)
mcl_title.remove(player, element)
else
new_timeouts[element][name] = timeout
end
end
end
hud_hide_timeouts = new_timeouts
end)
--DEBUG STUFF!!
--[[
minetest.register_chatcommand("title", {
func = function(name, param)
local player = minetest.get_player_by_name(name)
mcl_title.set(player, "title", {text=param, color="gold", bold=true, italic=true})
end,
})
minetest.register_chatcommand("subtitle", {
func = function(name, param)
local player = minetest.get_player_by_name(name)
mcl_title.set(player, "subtitle", {text=param, color="gold"})
end,
})
minetest.register_chatcommand("actionbar", {
func = function(name, param)
local player = minetest.get_player_by_name(name)
mcl_title.set(player, "actionbar", {text=param, color="gold"})
end,
})
minetest.register_chatcommand("timeout", {
func = function(name, param)
local player = minetest.get_player_by_name(name)
mcl_title.params_set(player, {stay = 600})
end,
})
minetest.register_chatcommand("all", {
func = function(name, param)
local player = minetest.get_player_by_name(name)
mcl_title.params_set(player, {stay = 600})
mcl_title.set(player, "title", {text=param, color="gold"})
mcl_title.set(player, "subtitle", {text=param, color="gold"})
mcl_title.set(player, "actionbar", {text=param, color="gold"})
end,
})
]]

@ -0,0 +1,4 @@
name = mcl_title
description = Add an API to add in HUD title
depends = mcl_colors
author = AFCMS

@ -1,7 +0,0 @@
# mcl_temp_message
Allow mods to show short messages in the hud of players.
## mcl_tmp_message.message(player, message)
Show above the hotbar a hud message <message> to player <player>.

@ -1,44 +0,0 @@
mcl_tmp_message = {}
local huds = {}
local hud_hide_timeouts = {}
function mcl_tmp_message.message(player, message)
local name = player:get_player_name()
player:hud_change(huds[name], "text", message)
hud_hide_timeouts[name] = 3
end
minetest.register_on_joinplayer(function(player)
huds[player:get_player_name()] = player:hud_add({
hud_elem_type = "text",
position = {x=0.5, y=1},
offset = {x = 0, y = -210},
alignment = {x=0, y=0},
number = 0xFFFFFF ,
text = "",
z_index = 100,
})
end)
minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name()
huds[name] = nil
hud_hide_timeouts[name] = nil
end)
minetest.register_globalstep(function(dtime)
local new_timeouts = {}
for name, timeout in pairs(hud_hide_timeouts) do
timeout = timeout - dtime
if timeout <= 0 then
local player = minetest.get_player_by_name(name)
if player then
player:hud_change(huds[name], "text", "")
end
else
new_timeouts[name] = timeout
end
end
hud_hide_timeouts = new_timeouts
end)

@ -1,3 +0,0 @@
name = mcl_tmp_message
author = Fleckenstein
description = A simple API to show a temporary message to a player

@ -168,6 +168,60 @@ local dispenserdef = {
end
inv:set_stack("main", stack_id, stack)
-- Use shears on sheeps
elseif igroups.shears then
for _, obj in pairs(minetest.get_objects_inside_radius(droppos, 1)) do
local entity = obj:get_luaentity()
if entity and not entity.child and not entity.gotten then
local entname = entity.name
local pos = obj:get_pos()
local used, texture = false
if entname == "mobs_mc:sheep" then
minetest.add_item(pos, entity.drops[2].name .. " " .. math.random(1, 3))
if not entity.color then
entity.color = "unicolor_white"
end
entity.base_texture = { "blank.png", "mobs_mc_sheep.png" }
texture = entity.base_texture
entity.drops = {
{ name = mobs_mc.items.mutton_raw, chance = 1, min = 1, max = 2 },
}
used = true
elseif entname == "mobs_mc:snowman" then
texture = {
"mobs_mc_snowman.png",
"blank.png", "blank.png",
"blank.png", "blank.png",
"blank.png", "blank.png",
}
used = true
elseif entname == "mobs_mc:mooshroom" then
local droppos = vector.offset(pos, 0, 1.4, 0)
if entity.base_texture[1] == "mobs_mc_mooshroom_brown.png" then
minetest.add_item(droppos, mobs_mc.items.mushroom_brown .. " 5")
else
minetest.add_item(droppos, mobs_mc.items.mushroom_red .. " 5")
end
local oldyaw = obj:get_yaw()
obj:remove()
local cow = minetest.add_entity(pos, "mobs_mc:cow")
cow:set_yaw(oldyaw)
obj = cow
entity = cow:get_luaentity()
used = true
end
if used then
obj:set_properties({ textures = texture })
entity.gotten = true
minetest.sound_play("mcl_tools_shears_cut", { pos = pos }, true)
stack:add_wear(65535 / stackdef._mcl_diggroups.shearsy.uses)
inv:set_stack("main", stack_id, stack)
break
end
end
end
-- Spawn Egg
elseif igroups.spawn_egg then
-- Spawn mob

@ -53,6 +53,15 @@ local function get_consumed_materials(tool, material)
return materials_used
end
local function contains(table, value)
for _, i in pairs(table) do
if i == value then
return true
end
end
return false
end
-- Given 2 input stacks, tells you which is the tool and which is the material.
-- Returns ("tool", input1, input2) if input1 is tool and input2 is material.
-- Returns ("material", input2, input1) if input1 is material and input2 is tool.
@ -60,9 +69,15 @@ end
local function distinguish_tool_and_material(input1, input2)
local def1 = input1:get_definition()
local def2 = input2:get_definition()
if def1.type == "tool" and def1._repair_material then
local r1 = def1._repair_material
local r2 = def2._repair_material
if def1.type == "tool" and r1 and type(r1) == "table" and contains(r1, input2) then
return "tool", input1, input2
elseif def2.type == "tool" and def2._repair_material then
elseif def2.type == "tool" and r2 and type(r2) == "table" and contains(r2, input1) then
return "material", input2, input1
elseif def1.type == "tool" and r1 then
return "tool", input1, input2
elseif def2.type == "tool" and r2 then
return "material", input2, input1
else
return nil
@ -121,11 +136,28 @@ local function update_anvil_slots(meta)
local distinguished, tool, material = distinguish_tool_and_material(input1, input2)
if distinguished then
local tooldef = tool:get_definition()
local repair = tooldef._repair_material
local has_correct_material = false
if string.sub(tooldef._repair_material, 1, 6) == "group:" then
has_correct_material = minetest.get_item_group(material:get_name(), string.sub(tooldef._repair_material, 7)) ~= 0
elseif material:get_name() == tooldef._repair_material then
has_correct_material = true
local material_name = material:get_name()
if type(repair) == "string" then
if string.sub(repair, 1, 6) == "group:" then
has_correct_material = minetest.get_item_group(material_name, string.sub(repair, 7)) ~= 0
elseif material_name == repair then
has_correct_material = true
end
else
if contains(repair, material_name) then
has_correct_material = true
else
for _, r in pairs(repair) do
if string.sub(r, 1, 6) == "group:" then
if minetest.get_item_group(material_name, string.sub(r, 7)) ~= 0 then
has_correct_material = true
end
end
end
end
end
if has_correct_material and tool:get_wear() > 0 then
local materials_used = get_consumed_materials(tool, material)
@ -284,6 +316,12 @@ local function damage_anvil_by_falling(pos, distance)
end
end
local anvilbox = {
type = "fixed",
fixed = {
{ -8 / 16, -8 / 16, -6 / 16, 8 / 16, 8 / 16, 6 / 16 },
},
}
local anvildef = {
groups = {pickaxey=1, falling_node=1, falling_node_damage=1, crush_after_fall=1, deco_block=1, anvil=1},
tiles = {"mcl_anvils_anvil_top_damaged_0.png^[transformR90", "mcl_anvils_anvil_base.png", "mcl_anvils_anvil_side.png"},
@ -297,11 +335,14 @@ local anvildef = {
node_box = {
type = "fixed",
fixed = {
{-8/16, 2/16, -5/16, 8/16, 8/16, 5/16}, -- top
{-5/16, -4/16, -2/16, 5/16, 5/16, 2/16}, -- middle
{-8/16, -8/16, -5/16, 8/16, -4/16, 5/16}, -- base
{ -6 / 16, -8 / 16, -6 / 16, 6 / 16, -4 / 16, 6 / 16 },
{ -5 / 16, -4 / 16, -4 / 16, 5 / 16, -3 / 16, 4 / 16 },
{ -4 / 16, -3 / 16, -2 / 16, 4 / 16, 2 / 16, 2 / 16 },
{ -8 / 16, 2 / 16, -5 / 16, 8 / 16, 8 / 16, 5 / 16 },
}
},
selection_box = anvilbox,
collision_box = anvilbox,
sounds = mcl_sounds.node_sound_metal_defaults(),
_mcl_blast_resistance = 1200,
_mcl_hardness = 5,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 B

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 B

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 B

After

Width:  |  Height:  |  Size: 5.7 KiB

@ -1,5 +1,5 @@
name = mcl_armor
author = stu
description = Adds craftable armor that is visible to other players.
depends = mcl_core, mcl_player, mcl_enchanting
depends = mcl_core, mcl_player, mcl_enchanting, mcl_damage
optional_depends = mcl_fire, ethereal, bakedclay

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 B

After

Width:  |  Height:  |  Size: 409 B

@ -330,7 +330,7 @@ function mcl_beds.on_rightclick(pos, player, is_top)
message = select(2, lay_down(player, ppos, other))
end
if message then
mcl_tmp_message.message(player, message)
mcl_title.set(player, "actionbar", {text=message, color="white", stay=60})
end
else
lay_down(player, nil, nil, false)

@ -1,4 +1,4 @@
name = mcl_brewing
author = bzoss
depends = mcl_init, mcl_formspec, mcl_sounds, mcl_potions, mcl_mobitems
optional_depends = mcl_core, doc, screwdriver
optional_depends = mcl_core, doc, screwdriver, mesecons_mvps

@ -9,13 +9,46 @@ Accept folowing params:
* string: name of the node to place
* function(pos): will returns name of the node to place with pos being the placement position
* source_take: table of liquid source node names to take
* itemname: itemstring of the new bucket item (or nil if liquid is not takeable)
* bucketname: itemstring of the new bucket item
* inventory_image: texture of the new bucket item (ignored if itemname == nil)
* name: user-visible bucket description
* longdesc: long explanatory description (for help)
* usagehelp: short usage explanation (for help)
* tt_help: very short tooltip help
* extra_check(pos, placer): (optional) function(pos) which can returns false to avoid placing the liquid. Placer is object/player who is placing the liquid, can be nil.
* extra_check(pos, placer): (optional) function(pos)
* groups: optional list of item groups
This function can be called from any mod (which depends on this one)
**Usage exemple:**
```lua
mcl_buckets.register_liquid({
bucketname = "dummy:bucket_dummy",
--source_place = "dummy:dummy_source",
source_place = function(pos)
if condition then
return "dummy:dummy_source"
else
return "dummy:dummy_source_nether"
end
end,
source_take = {"dummy:dummy_source"},
inventory_image = "bucket_dummy.png",
name = S("Dummy liquid Bucket"),
longdesc = S("This bucket is filled with a dummy liquid."),
usagehelp = S("Place it to empty the bucket and create a dummy liquid source."),
tt_help = S("Places a dummy liquid source"),
extra_check = function(pos, placer)
--pos = pos where the liquid should be placed
--placer people who tried to place the bucket (can be nil)
--no liquid node will be placed
--the bucket will not be emptied
--return false, false
--liquid node will be placed
--the bucket will be emptied
return true, true
end,
groups = { dummy_group = 123 },
})
```

@ -1,9 +1,12 @@
Bucket mod.
Originally taken from Minetest Game, adapted for MineClone 2.
# MineClone2 Bucket (`mcl_bucket`)
Originally taken from Minetest Game, adapted for MineClone2.
This mod add buckets to the game, including an API to register your own (see `API.md`).
## License
License of source code:
-----------------------
Copyright (C) 2011-2012 Kahrl <kahrl@gmx.net>
Copyright (C) 2011-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify

@ -3,6 +3,7 @@ local modname = minetest.get_current_modname()
local S = minetest.get_translator(modname)
local modpath = minetest.get_modpath(modname)
-- Compatibility with old bucket mod
minetest.register_alias("bucket:bucket_empty", "mcl_buckets:bucket_empty")
minetest.register_alias("bucket:bucket_water", "mcl_buckets:bucket_water")
minetest.register_alias("bucket:bucket_lava", "mcl_buckets:bucket_lava")
@ -11,13 +12,24 @@ local mod_doc = minetest.get_modpath("doc")
local mod_mcl_core = minetest.get_modpath("mcl_core")
--local mod_mclx_core = minetest.get_modpath("mclx_core")
-- Localize some functions for faster access
local vector = vector
local math = math
local string = string
local raycast = minetest.raycast
local get_node = minetest.get_node
local add_node = minetest.add_node
local add_item = minetest.add_item
if mod_mcl_core then
minetest.register_craft({
output = "mcl_buckets:bucket_empty 1",
recipe = {
{"mcl_core:iron_ingot", "", "mcl_core:iron_ingot"},
{"", "mcl_core:iron_ingot", ""},
}
},
})
end
@ -25,147 +37,218 @@ mcl_buckets = {}
mcl_buckets.liquids = {}
-- Sound helper functions for placing and taking liquids
local sound_place = function(itemname, pos)
local function sound_place(itemname, pos)
local def = minetest.registered_nodes[itemname]
if def and def.sounds and def.sounds.place then
minetest.sound_play(def.sounds.place, {gain=1.0, pos = pos, pitch = 1 + math.random(-10, 10)*0.005}, true)
end
end
local sound_take = function(itemname, pos)
local function sound_take(itemname, pos)
local def = minetest.registered_nodes[itemname]
if def and def.sounds and def.sounds.dug then
minetest.sound_play(def.sounds.dug, {gain=1.0, pos = pos, pitch = 1 + math.random(-10, 10)*0.005}, true)
end
end
local place_liquid = function(pos, itemstring)
local function place_liquid(pos, itemstring)
local fullness = minetest.registered_nodes[itemstring].liquid_range
sound_place(itemstring, pos)
minetest.add_node(pos, {name=itemstring, param2=fullness})
end
local function give_bucket(new_bucket, itemstack, user)
local inv = user:get_inventory()
if minetest.is_creative_enabled(user:get_player_name()) then
--TODO: is a full bucket added if inv doesn't contain one?
return itemstack
else
if itemstack:get_count() == 1 then
return new_bucket
else
if inv:room_for_item("main", new_bucket) then
inv:add_item("main", new_bucket)
else
add_item(user:get_pos(), new_bucket)
end
itemstack:take_item()
return itemstack
end
end
end
local pointable_sources = {}
local function bucket_raycast(user)
--local pos = user:get_pos()
local pos = user:get_pos()
--local pos = vector.add(user:get_pos(), user:get_bone_position("Head_Control"))
pos.y = pos.y + user:get_properties().eye_height
local look_dir = user:get_look_dir()
look_dir = vector.multiply(look_dir, 5)
local pos2 = vector.add(pos, look_dir)
local ray = raycast(pos, pos2, false, true)
if ray then
for pointed_thing in ray do
if pointed_thing and pointable_sources[get_node(pointed_thing.above).name] then
--minetest.chat_send_all("found!")
return {under=pointed_thing.under,above=pointed_thing.above}
end
end
end
return nil
end
local function get_node_place(source_place, place_pos)
local node_place
if type(source_place) == "function" then
node_place = source_place(place_pos)
else
node_place = source_place
end
return node_place
end
local function get_extra_check(check, pos, user)
local result
local take_bucket
if check then
result, take_bucket = check(pos, user)
if result == nil then result = true end
if take_bucket == nil then take_bucket = true end
else
result = true
take_bucket = true
end
return result, take_bucket
end
local function get_bucket_drop(itemstack, user, take_bucket)
-- Handle bucket item and inventory stuff
if take_bucket and not minetest.is_creative_enabled(user:get_player_name()) then
-- Add empty bucket and put it into inventory, if possible.
-- Drop empty bucket otherwise.
local new_bucket = ItemStack("mcl_buckets:bucket_empty")
if itemstack:get_count() == 1 then
return new_bucket
else
local inv = user:get_inventory()
if inv:room_for_item("main", new_bucket) then
inv:add_item("main", new_bucket)
else
add_item(user:get_pos(), new_bucket)
end
itemstack:take_item()
return itemstack
end
else
return itemstack
end
end
function mcl_buckets.register_liquid(def)
for i=1, #def.source_take do
mcl_buckets.liquids[def.source_take[i]] = {
for _,source in ipairs(def.source_take) do
mcl_buckets.liquids[source] = {
source_place = def.source_place,
source_take = def.source_take[i],
source_take = source,
on_take = def.on_take,
itemname = def.itemname,
bucketname = def.bucketname,
}
pointable_sources[source] = true
if type(def.source_place) == "string" then
mcl_buckets.liquids[def.source_place] = mcl_buckets.liquids[def.source_take[i]]
mcl_buckets.liquids[def.source_place] = mcl_buckets.liquids[source]
end
end
if def.itemname then
minetest.register_craftitem(def.itemname, {
description = def.name,
_doc_items_longdesc = def.longdesc,
_doc_items_usagehelp = def.usagehelp,
_tt_help = def.tt_help,
inventory_image = def.inventory_image,
stack_max = 1,
groups = def.groups,
on_place = function(itemstack, user, pointed_thing)
-- Must be pointing to node
if pointed_thing.type ~= "node" then
return
end
if def.bucketname == nil or def.bucketname == "" then
error(string.format("[mcl_bucket] Invalid itemname then registering [%s]!", def.name))
end
local node = minetest.get_node(pointed_thing.under)
local place_pos = pointed_thing.under
local nn = node.name
local nodedef = minetest.registered_nodes[nn]
-- Call on_rightclick if the pointed node defines it
if user and not user:get_player_control().sneak then
if nodedef and nodedef.on_rightclick then
return nodedef.on_rightclick(place_pos, node, user, itemstack) or itemstack
end
end
minetest.register_craftitem(def.bucketname, {
description = def.name,
_doc_items_longdesc = def.longdesc,
_doc_items_usagehelp = def.usagehelp,
_tt_help = def.tt_help,
inventory_image = def.inventory_image,
stack_max = 1,
groups = def.groups,
on_place = function(itemstack, user, pointed_thing)
-- Must be pointing to node
if pointed_thing.type ~= "node" then
return
end
-- Call on_rightclick if the pointed node defines it
local new_stack = mcl_util.call_on_rightclick(itemstack, user, pointed_thing)
if new_stack then
return new_stack
end
local node_place
if type(def.source_place) == "function" then
node_place = def.source_place(place_pos)
else
node_place = def.source_place
end
-- Check if pointing to a buildable node
--local item = itemstack:get_name()
local undernode = get_node(pointed_thing.under)
local abovenode = get_node(pointed_thing.above)
local buildable1 = minetest.registered_nodes[undernode.name] and minetest.registered_nodes[undernode.name].buildable_to
local buildable2 = minetest.registered_nodes[abovenode.name] and minetest.registered_nodes[abovenode.name].buildable_to
if not buildable1 and not buildable2 then return itemstack end --if both nodes aren't buildable_to, skip
if def.extra_check and def.extra_check(place_pos, user) == true and nodedef and nodedef.buildable_to then
-- buildable; replace the node
if buildable1 then
local result, take_bucket = get_extra_check(def.extra_check, pointed_thing.under, user)
if result then
local node_place = get_node_place(def.source_place, pointed_thing.under)
local pns = user:get_player_name()
if minetest.is_protected(place_pos, pns) then
minetest.record_protection_violation(place_pos, pns)
-- Check protection
if minetest.is_protected(pointed_thing.under, pns) then
minetest.record_protection_violation(pointed_thing.under, pns)
return itemstack
end
place_liquid(place_pos, node_place)
-- Place liquid
place_liquid(pointed_thing.under, node_place)
-- Update doc mod
if mod_doc and doc.entry_exists("nodes", node_place) then
doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place)
end
else
-- not buildable to; place the liquid above
-- check if the node above can be replaced
local abovenode = minetest.get_node(pointed_thing.above)
if minetest.registered_nodes[abovenode.name] and minetest.registered_nodes[abovenode.name].buildable_to then
local pn = user:get_player_name()
if minetest.is_protected(pointed_thing.above, pn) then
minetest.record_protection_violation(pointed_thing.above, pn)
return itemstack
end
place_liquid(pointed_thing.above, node_place)
if mod_doc and doc.entry_exists("nodes", node_place) then
doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place)
end
else
-- do not remove the bucket with the liquid
return
end
end
return get_bucket_drop(itemstack, user, take_bucket)
elseif buildable2 then
local result, take_bucket = get_extra_check(def.extra_check, pointed_thing.above, user)
if result then
local node_place = get_node_place(def.source_place, pointed_thing.above)
local pns = user:get_player_name()
-- Handle bucket item and inventory stuff
if not minetest.is_creative_enabled(user:get_player_name()) then
-- Add empty bucket and put it into inventory, if possible.
-- Drop empty bucket otherwise.
local new_bucket = ItemStack("mcl_buckets:bucket_empty")
if itemstack:get_count() == 1 then
return new_bucket
else
local inv = user:get_inventory()
if inv:room_for_item("main", new_bucket) then
inv:add_item("main", new_bucket)
else
minetest.add_item(user:get_pos(), new_bucket)
end
itemstack:take_item()
-- Check protection
if minetest.is_protected(pointed_thing.above, pns) then
minetest.record_protection_violation(pointed_thing.above, pns)
return itemstack
end
else
return
end
end,
_on_dispense = function(stack, pos, droppos, dropnode, dropdir)
--local iname = stack:get_name()
local buildable = minetest.registered_nodes[dropnode.name].buildable_to or dropnode.name == "mcl_portals:portal"
--if def.extra_check and def.extra_check(droppos, nil) == false then
-- Fail placement of liquid
if def.extra_check and def.extra_check(droppos, nil) == true and buildable then
-- buildable; replace the node
local node_place
if type(def.source_place) == "function" then
node_place = def.source_place(droppos)
else
node_place = def.source_place
-- Place liquid
place_liquid(pointed_thing.above, node_place)
-- Update doc mod
if mod_doc and doc.entry_exists("nodes", node_place) then
doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place)
end
place_liquid(droppos, node_place)
stack:set_name("mcl_buckets:bucket_empty")
end
return stack
end,
})
end
return get_bucket_drop(itemstack, user, take_bucket)
else
return itemstack
end
end,
_on_dispense = function(stack, pos, droppos, dropnode, dropdir)
local buildable = minetest.registered_nodes[dropnode.name].buildable_to or dropnode.name == "mcl_portals:portal"
if not buildable then return stack end
local result, take_bucket = get_extra_check(def.extra_check, droppos, nil)
if result then -- Fail placement of liquid if result is false
place_liquid(droppos, get_node_place(def.source_place, droppos))
end
if take_bucket then
stack:set_name("mcl_buckets:bucket_empty")
end
return stack
end,
})
end
minetest.register_craftitem("mcl_buckets:bucket_empty", {
@ -173,8 +256,7 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", {
_doc_items_longdesc = S("A bucket can be used to collect and release liquids."),
_doc_items_usagehelp = S("Punch a liquid source to collect it. You can then use the filled bucket to place the liquid somewhere else."),
_tt_help = S("Collects liquids"),
liquids_pointable = true,
--liquids_pointable = true,
inventory_image = "bucket.png",
stack_max = 16,
on_place = function(itemstack, user, pointed_thing)
@ -184,74 +266,70 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", {
end
-- Call on_rightclick if the pointed node defines it
local new_stack = mcl_util.call_on_rightclick(itemstack, user, pointed_thing)
if new_stack then
return new_stack
end
local node = minetest.get_node(pointed_thing.under)
local nn = node.name
if user and not user:get_player_control().sneak then
if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].on_rightclick then
return minetest.registered_nodes[nn].on_rightclick(pointed_thing.under, node, user, itemstack) or itemstack
end
end
-- Can't steal liquids
if minetest.is_protected(pointed_thing.above, user:get_player_name()) then
minetest.record_protection_violation(pointed_thing.under, user:get_player_name())
return itemstack
end
-- Check if pointing to a liquid source
local liquiddef = mcl_buckets.liquids[nn]
local new_bucket
if liquiddef and liquiddef.itemname and (nn == liquiddef.source_take) then
-- Fill bucket, but not in Creative Mode
if not minetest.is_creative_enabled(user:get_player_name()) then
new_bucket = ItemStack({name = liquiddef.itemname})
if liquiddef.on_take then
liquiddef.on_take(user)
end
local liquid_node = bucket_raycast(user)
if liquid_node then
if minetest.is_protected(liquid_node.above, user:get_player_name()) then
minetest.record_protection_violation(liquid_node.above, user:get_player_name())
end
local liquid_name = get_node(liquid_node.above).name
if liquid_name then
local liquid_def = mcl_buckets.liquids[liquid_name]
if liquid_def then
--minetest.chat_send_all("test")
-- Fill bucket, but not in Creative Mode
-- FIXME: remove this line
--if not minetest.is_creative_enabled(user:get_player_name()) then
if not false then
new_bucket = ItemStack({name = liquid_def.bucketname})
if liquid_def.on_take then
liquid_def.on_take(user)
end
end
add_node(liquid_node.above, {name="air"})
sound_take(nn, liquid_node.above)
minetest.add_node(pointed_thing.under, {name="air"})
sound_take(nn, pointed_thing.under)
if mod_doc and doc.entry_exists("nodes", nn) then
doc.mark_entry_as_revealed(user:get_player_name(), "nodes", nn)
end
elseif nn == "mcl_cauldrons:cauldron_3" then
-- Take water out of full cauldron
minetest.set_node(pointed_thing.under, {name="mcl_cauldrons:cauldron"})
if not minetest.is_creative_enabled(user:get_player_name()) then
new_bucket = ItemStack("mcl_buckets:bucket_water")
end
sound_take("mcl_core:water_source", pointed_thing.under)
elseif nn == "mcl_cauldrons:cauldron_3r" then
-- Take river water out of full cauldron
minetest.set_node(pointed_thing.under, {name="mcl_cauldrons:cauldron"})
if not minetest.is_creative_enabled(user:get_player_name()) then
new_bucket = ItemStack("mcl_buckets:bucket_river_water")
end
sound_take("mclx_core:river_water_source", pointed_thing.under)
end
-- Add liquid bucket and put it into inventory, if possible.
-- Drop new bucket otherwise.
if new_bucket then
if itemstack:get_count() == 1 then
return new_bucket
else
local inv = user:get_inventory()
if inv:room_for_item("main", new_bucket) then
inv:add_item("main", new_bucket)
if mod_doc and doc.entry_exists("nodes", liquid_name) then
doc.mark_entry_as_revealed(user:get_player_name(), "nodes", liquid_name)
end
if new_bucket then
return give_bucket(new_bucket, itemstack, user)
end
else
minetest.add_item(user:get_pos(), new_bucket)
minetest.log("error", string.format("[mcl_buckets] Node [%s] has invalid group [_mcl_bucket_pointable]!", liquid_name))
end
if not minetest.is_creative_enabled(user:get_player_name()) then
itemstack:take_item()
end
return itemstack
end
end
return itemstack
else
-- FIXME: replace this ugly code by cauldrons API
if nn == "mcl_cauldrons:cauldron_3" then
-- Take water out of full cauldron
minetest.set_node(pointed_thing.under, {name="mcl_cauldrons:cauldron"})
if not minetest.is_creative_enabled(user:get_player_name()) then
new_bucket = ItemStack("mcl_buckets:bucket_water")
end
sound_take("mcl_core:water_source", pointed_thing.under)
elseif nn == "mcl_cauldrons:cauldron_3r" then
-- Take river water out of full cauldron
minetest.set_node(pointed_thing.under, {name="mcl_cauldrons:cauldron"})
if not minetest.is_creative_enabled(user:get_player_name()) then
new_bucket = ItemStack("mcl_buckets:bucket_river_water")
end
sound_take("mclx_core:river_water_source", pointed_thing.under)
end
if new_bucket then
return give_bucket(new_bucket, itemstack, user)
end
end
return itemstack
end,
_on_dispense = function(stack, pos, droppos, dropnode, dropdir)
-- Fill empty bucket with liquid or drop bucket if no liquid
@ -259,9 +337,9 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", {
local liquiddef = mcl_buckets.liquids[dropnode.name]
local new_bucket
if liquiddef and liquiddef.itemname and (dropnode.name == liquiddef.source_take) then
if liquiddef and liquiddef.bucketname and (dropnode.name == liquiddef.source_take) then
-- Fill bucket
new_bucket = ItemStack({name = liquiddef.itemname})
new_bucket = ItemStack({name = liquiddef.bucketname})
sound_take(dropnode.name, droppos)
collect_liquid = true
end

@ -1,6 +1,6 @@
name = mcl_buckets
author = Kahrl
description =
depends = mcl_worlds
depends = mcl_worlds, mcl_util
optional_depends = mcl_core, mclx_core, doc

@ -3,7 +3,7 @@ local mod_mcl_core = minetest.get_modpath("mcl_core")
local mod_mclx_core = minetest.get_modpath("mclx_core")
local has_awards = minetest.get_modpath("awards")
local sound_place = function(itemname, pos)
local function sound_place(itemname, pos)
local def = minetest.registered_nodes[itemname]
if def and def.sounds and def.sounds.place then
minetest.sound_play(def.sounds.place, {gain=1.0, pos = pos, pitch = 1 + math.random(-10, 10)*0.005}, true)
@ -34,7 +34,7 @@ if mod_mcl_core then
awards.unlock(user:get_player_name(), "mcl:hotStuff")
end
end,
itemname = "mcl_buckets:bucket_lava",
bucketname = "mcl_buckets:bucket_lava",
inventory_image = "bucket_lava.png",
name = S("Lava Bucket"),
longdesc = S("A bucket can be used to collect and release liquids. This one is filled with hot lava, safely contained inside. Use with caution."),
@ -46,22 +46,13 @@ if mod_mcl_core then
mcl_buckets.register_liquid({
source_place = "mcl_core:water_source",
source_take = {"mcl_core:water_source"},
itemname = "mcl_buckets:bucket_water",
bucketname = "mcl_buckets:bucket_water",
inventory_image = "bucket_water.png",
name = S("Water Bucket"),
longdesc = S("A bucket can be used to collect and release liquids. This one is filled with water."),
usagehelp = S("Place it to empty the bucket and create a water source."),
tt_help = S("Places a water source"),
extra_check = function(pos, placer)
-- Check protection
local placer_name = ""
if placer then
placer_name = placer:get_player_name()
end
if placer and minetest.is_protected(pos, placer_name) then
minetest.record_protection_violation(pos, placer_name)
return false
end
local nn = minetest.get_node(pos).name
-- Pour water into cauldron
if minetest.get_item_group(nn, "cauldron") ~= 0 then
@ -70,13 +61,13 @@ if mod_mcl_core then
minetest.set_node(pos, {name="mcl_cauldrons:cauldron_3"})
end
sound_place("mcl_core:water_source", pos)
return false
return false, true
-- Evaporate water if used in Nether (except on cauldron)
else
local dim = mcl_worlds.pos_to_dimension(pos)
if dim == "nether" then
minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true)
return false
return false, true
end
end
end,
@ -89,22 +80,13 @@ if mod_mclx_core then
mcl_buckets.register_liquid({
source_place = "mclx_core:river_water_source",
source_take = {"mclx_core:river_water_source"},
itemname = "mcl_buckets:bucket_river_water",
bucketname = "mcl_buckets:bucket_river_water",
inventory_image = "bucket_river_water.png",
name = S("River Water Bucket"),
longdesc = S("A bucket can be used to collect and release liquids. This one is filled with river water."),
usagehelp = S("Place it to empty the bucket and create a river water source."),
tt_help = S("Places a river water source"),
extra_check = function(pos, placer)
-- Check protection
local placer_name = ""
if placer then
placer_name = placer:get_player_name()
end
if placer and minetest.is_protected(pos, placer_name) then
minetest.record_protection_violation(pos, placer_name)
return false
end
local nn = minetest.get_node(pos).name
-- Pour into cauldron
if minetest.get_item_group(nn, "cauldron") ~= 0 then
@ -113,13 +95,13 @@ if mod_mclx_core then
minetest.set_node(pos, {name="mcl_cauldrons:cauldron_3r"})
end
sound_place("mcl_core:water_source", pos)
return false
return false, true
else
-- Evaporate water if used in Nether (except on cauldron)
local dim = mcl_worlds.pos_to_dimension(pos)
if dim == "nether" then
minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true)
return false
return false, true
end
end
end,

@ -1133,7 +1133,7 @@ for color, desc in pairs(boxtypes) do
if mod_doc then
if is_canonical then
longdesc = S("A shulker box is a portable container which provides 27 inventory slots for any item except shulker boxes. Shulker boxes keep their inventory when broken, so shulker boxes as well as their contents can be taken as a single item. Shulker boxes come in many different colors.")
usagehelp = S("To access the inventory of a shulker box, place and right-click it. To take a shulker box and its contents with you, just break and collect it, the items will not fall out.")
usagehelp = S("To access the inventory of a shulker box, place and right-click it. To take a shulker box and its contents with you, just break and collect it, the items will not fall out. Place the shulker box again to be able to retrieve its contents.")
entry_name = S("Shulker Box")
else
create_entry = false

@ -24,7 +24,7 @@ Red Shulker Box=
Grey Shulker Box=
Black Shulker Box=
A shulker box is a portable container which provides 27 inventory slots for any item except shulker boxes. Shulker boxes keep their inventory when broken, so shulker boxes as well as their contents can be taken as a single item. Shulker boxes come in many different colors.=
To access the inventory of a shulker box, place and right-click it. To take a shulker box and its contents with you, just break and collect it, the items will not fall out.=
To access the inventory of a shulker box, place and right-click it. To take a shulker box and its contents with you, just break and collect it, the items will not fall out. Place the shulker box again to be able to retrieve its contents.=
Shulker Box=
Large Chest=
Inventory=

@ -184,6 +184,7 @@ minetest.register_abm({
end,
})
-- Cactus mechanisms
minetest.register_abm({
label = "Cactus growth",
nodenames = {"mcl_core:cactus"},
@ -195,19 +196,31 @@ minetest.register_abm({
end,
})
-- Make cactus destroy items
minetest.register_abm({
label = "Cactus destroy items",
label = "Cactus mechanisms",
nodenames = {"mcl_core:cactus"},
interval = 1,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
for _,object in pairs(minetest.get_objects_inside_radius(pos, 0.9)) do
for _, object in pairs(minetest.get_objects_inside_radius(pos, 0.9)) do
local entity = object:get_luaentity()
if entity and entity.name == "__builtin:item" then
object:remove()
end
end
local posses = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } }
for _, p in pairs(posses) do
if minetest.registered_nodes[minetest.get_node(vector.new(pos.x + p[1], pos.y, pos.z + p[2])).name].walkable then
local posy = pos.y
while minetest.get_node(vector.new(pos.x, posy, pos.z)).name == "mcl_core:cactus" do
local pos = vector.new(pos.x, posy, pos.z)
minetest.remove_node(pos)
minetest.add_item(vector.offset(pos, math.random(-0.5, 0.5), 0, math.random(-0.5, 0.5)), "mcl_core:cactus")
posy = posy + 1
end
break
end
end
end,
})

@ -453,7 +453,7 @@ function mcl_end.grow_chorus_plant_step(pos, node, pr)
end
--- ABM ---
local seed = minetest.get_mapgen_params().seed
local seed = minetest.get_mapgen_setting("seed")
local pr = PseudoRandom(seed)
minetest.register_abm({
label = "Chorus plant growth",

@ -0,0 +1,3 @@
# textdomain: mcl_fireworks
Firework Rocket=
Flight Duration:=

@ -0,0 +1,3 @@
# textdomain: mcl_fireworks
Firework Rocket=Fusée
Flight Duration:=Durée de vol :

@ -0,0 +1,3 @@
# textdomain: mcl_fireworks
Firework Rocket=
Flight Duration:=

@ -1,5 +1,8 @@
# textdomain: mcl_maps
Empty Map=Carte Vierge
Empty maps are not useful as maps, but they can be stacked and turned to maps which can be used.=Les cartes vierges ne sont pas utiles en tant que cartes, mais elles peuvent être empilées et transformées en cartes utilisables.
Rightclick to start using the map (which can't be stacked anymore).=Clic droit pour commencer à utiliser la carte (qui ne peut plus être empilée).
Rightclick to create a filled map (which can't be stacked anymore).=Clic droit pour créer une carte remplie (qui ne peut plus être empilée).
Map=Carte
Shows a map image.=Affiche une carte.
When created, the map saves the nearby area as an image that can be viewed any time by holding the map.=Lors de sa création, la carte sauvegarde le terrain proche sous forme d'image qui peut être consultée n'importe quand en tenant la carte dans la main.
Hold the map in your hand. This will display a map on your screen.=Tenez la carte dans votre main. Cela affichera la carte à l'écran.

@ -1,4 +1,4 @@
name = mcl_portals
description = Adds buildable portals to the Nether and End dimensions.
depends = mcl_nether, mcl_end, mcl_particles, mcl_spawn
depends = mcl_nether, mcl_end, mcl_particles, mcl_spawn, mcl_credits
optional_depends = awards, doc

@ -4,6 +4,8 @@ local table = table
local vector = vector
local math = math
local has_doc = minetest.get_modpath("doc")
-- Parameters
--local SPAWN_MIN = mcl_vars.mg_end_min+70
--local SPAWN_MAX = mcl_vars.mg_end_min+98
@ -339,7 +341,7 @@ minetest.register_node("mcl_portals:end_portal_frame_eye", {
_mcl_hardness = -1,
})
if minetest.get_modpath("doc") then
if has_doc then
doc.add_entry_alias("nodes", "mcl_portals:end_portal_frame", "nodes", "mcl_portals:end_portal_frame_eye")
end
@ -366,7 +368,7 @@ minetest.override_item("mcl_end:ender_eye", {
end
minetest.set_node(pointed_thing.under, { name = "mcl_portals:end_portal_frame_eye", param2 = node.param2 })
if minetest.get_modpath("doc") then
if has_doc then
doc.mark_entry_as_revealed(user:get_player_name(), "nodes", "mcl_portals:end_portal_frame")
end
minetest.sound_play(
@ -381,7 +383,7 @@ minetest.override_item("mcl_end:ender_eye", {
-- Epic 'portal open' sound effect that can be heard everywhere
minetest.sound_play("mcl_portals_open_end_portal", {gain=0.8}, true)
end_portal_area(ppos)
if minetest.get_modpath("doc") then
if has_doc then
doc.mark_entry_as_revealed(user:get_player_name(), "nodes", "mcl_portals:portal_end")
end
end
@ -389,7 +391,3 @@ minetest.override_item("mcl_end:ender_eye", {
return itemstack
end,
})
minetest.override_item("mcl_core:bedrock", {
after_destruct = destroy_portal,
})

@ -35,13 +35,13 @@ local function potions_init_icons(player)
local name = player:get_player_name()
icon_ids[name] = {}
for e=1, EFFECT_TYPES do
local x = -7 + -38 * e
local x = -52 * e - 2
local id = player:hud_add({
hud_elem_type = "image",
text = "blank.png",
position = { x = 1, y = 0 },
offset = { x = x, y = 272 },
scale = { x = 2, y = 2 },
offset = { x = x, y = 3 },
scale = { x = 3, y = 3 },
alignment = { x = 1, y = 1 },
z_index = 100,
})

@ -35,40 +35,6 @@ minetest.register_craft({
},
})
minetest.register_craft({
output = "mcl_armor:helmet_chain",
recipe = {
{ "xpanes:bar_flat", "mcl_core:iron_ingot", "xpanes:bar_flat" },
{ "xpanes:bar_flat", "", "xpanes:bar_flat" },
}
})
minetest.register_craft({
output = "mcl_armor:leggings_chain",
recipe = {
{ "xpanes:bar_flat", "mcl_core:iron_ingot", "xpanes:bar_flat" },
{ "xpanes:bar_flat", "", "xpanes:bar_flat" },
{ "xpanes:bar_flat", "", "xpanes:bar_flat" },
}
})
minetest.register_craft({
output = "mcl_armor:boots_chain",
recipe = {
{ "xpanes:bar_flat", "", "xpanes:bar_flat" },
{ "xpanes:bar_flat", "", "xpanes:bar_flat" },
}
})
minetest.register_craft({
output = "mcl_armor:chestplate_chain",
recipe = {
{ "xpanes:bar_flat", "", "xpanes:bar_flat" },
{ "xpanes:bar_flat", "mcl_core:iron_ingot", "xpanes:bar_flat" },
{ "xpanes:bar_flat", "xpanes:bar_flat", "xpanes:bar_flat" },
}
})
-- Make red sand, red sandstone and more craftable in v6
-- NOTE: When you change these, also update mcl_craftguide for the "v6" icon in
-- the craft guide!

@ -152,26 +152,18 @@ function mcl_hunger.item_eat(hunger_change, replace_with_item, poisontime, poiso
-- If false, force item to not spawn any food partiles when eaten
if def._food_particles ~= false and texture and texture ~= "" then
local v = user:get_velocity() or user:get_player_velocity()
local minvel = vector.add(v, {x=-1, y=1, z=-1})
local maxvel = vector.add(v, {x=1, y=2, z=1})
minetest.add_particlespawner({
amount = math.min(math.max(8, hunger_change*2), 25),
time = 0.1,
minpos = {x=pos.x, y=pos.y, z=pos.z},
maxpos = {x=pos.x, y=pos.y, z=pos.z},
minvel = minvel,
maxvel = maxvel,
minacc = {x=0, y=-5, z=0},
maxacc = {x=0, y=-9, z=0},
minexptime = 1,
maxexptime = 1,
minsize = 1,
maxsize = 2,
collisiondetection = true,
vertical = false,
texture = texture,
})
for i = 0, math.min(math.max(8, hunger_change*2), 25) do
minetest.add_particle({
pos = { x = pos.x, y = pos.y, z = pos.z },
velocity = vector.add(v, { x = math.random(-1, 1), y = math.random(1, 2), z = math.random(-1, 1) }),
acceleration = { x = 0, y = math.random(-9, -5), z = 0 },
expirationtime = 1,
size = math.random(1, 2),
collisiondetection = true,
vertical = false,
texture = "[combine:3x3:" .. -i .. "," .. -i .. "=" .. texture,
})
end
end
minetest.sound_play("mcl_hunger_bite", {
max_hear_distance = 12,

@ -1,5 +1,5 @@
name = mcl_playerplus
author = TenPlus1
description = Adds some simple player-related gameplay effects: Hurt by touching a cactus, suffocation and more.
depends = mcl_init, mcl_core, mcl_particles, mcl_hunger, playerphysics, mcl_playerinfo, mcl_weather, mcl_spawn, mcl_enchanting, mcl_damage
depends = mcl_init, mcl_core, mcl_particles, mcl_hunger, playerphysics, mcl_playerinfo, mcl_weather, mcl_spawn, mcl_enchanting, mcl_damage, mcl_sprint

@ -69,18 +69,19 @@ local function setSprinting(playerName, sprinting) --Sets the state of a player
local controls = player:get_player_control()
if players[playerName] then
players[playerName].sprinting = sprinting
local fov_old = players[playerName].fov
local fov_new = fov_old
local fade_time = .15
if sprinting == true
or controls.RMB
and string.find(player:get_wielded_item():get_name(), "mcl_bows:bow")
and player:get_wielded_item():get_name() ~= "mcl_bows:bow" then
if sprinting == true then
players[playerName].fov = math.min(players[playerName].fov + 0.05, 1.2)
players[playerName].fade_time = .15
fov_new = math.min(players[playerName].fov + 0.05, 1.2)
else
players[playerName].fov = .7
fov_new = .7
players[playerName].fade_time = .3
end
player:set_fov(players[playerName].fov, true, players[playerName].fade_time)
if sprinting == true then
playerphysics.add_physics_factor(player, "speed", "mcl_sprint:sprint", mcl_sprint.SPEED)
end
@ -88,12 +89,15 @@ local function setSprinting(playerName, sprinting) --Sets the state of a player
and player:get_wielded_item():get_name() ~= "mcl_bows:bow_0"
and player:get_wielded_item():get_name() ~= "mcl_bows:bow_1"
and player:get_wielded_item():get_name() ~= "mcl_bows:bow_2" then
players[playerName].fov = math.max(players[playerName].fov - 0.05, 1.0)
player:set_fov(players[playerName].fov, true, 0.15)
fov_new = math.max(players[playerName].fov - 0.05, 1.0)
if sprinting == false then
playerphysics.remove_physics_factor(player, "speed", "mcl_sprint:sprint")
end
end
if fov_new ~= fov_old then
players[playerName].fov = fov_new
player:set_fov(fov_new, true, fade_time)
end
return true
end
return false

@ -153,3 +153,7 @@ fix_doubleplants (Mcimport double plant fixes) bool true
# Allow players to create Minecraft-like maps.
enable_real_maps (Enable Real Maps) bool true
[Debugging]
# If enabled, this will show the itemstring of an item in the description.
mcl_item_id_debug (Item ID Debug) bool false