1
0
Fork 0

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

View File

@ -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. 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. Public functions should not use self references but rather just access the table directly.
Functions should be defined in this way: Functions should be defined in this way:
``` ```lua
function mcl_xyz.stuff(param) end function mcl_xyz.stuff(param) end
``` ```
Insteed of this way: Insteed of this way:
``` ```lua
mcl_xyz.stuff = function(param) end mcl_xyz.stuff = function(param) end
``` ```
Indentation must be unified, more likely with tabs. Indentation must be unified, more likely with tabs.
Time sensitive mods should make a local copy of most used API functions to improve performances. Time sensitive mods should make a local copy of most used API functions to improve performances.
``` ```lua
local vector = vector local vector = vector
local get_node = minetest.get_node local get_node = minetest.get_node
``` ```

View File

@ -84,7 +84,7 @@ local function attach_object(self, obj)
end end
end, name) end, name)
obj:set_look_horizontal(yaw) 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 else
obj:get_luaentity()._old_visual_size = visual_size obj:get_luaentity()._old_visual_size = visual_size
end end

View File

@ -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 Dark Oak Boat=Bateau en Chêne Noir
Jungle Boat=Bateau en Acajou Jungle Boat=Bateau en Acajou
Oak Boat=Bateau en Chêne 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 Spruce Boat=Bateau en Sapin
Water vehicle=Véhicule aquatique Water vehicle=Véhicule aquatique
Sneak to dismount=

View File

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

View File

@ -67,14 +67,9 @@ function mcl_burning.set_on_fire(obj, burn_time)
end end
if not storage.burn_time or burn_time >= storage.burn_time then if not storage.burn_time or burn_time >= storage.burn_time then
if obj:is_player() and not storage.fire_hud_id then if obj:is_player() then
storage.fire_hud_id = obj:hud_add({ mcl_burning.channels[obj]:send_all(tostring(mcl_burning.animation_frames))
hud_elem_type = "image", mcl_burning.channels[obj]:send_all("start")
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,
})
end end
storage.burn_time = burn_time storage.burn_time = burn_time
storage.fire_damage_timer = 0 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_properties({visual_size = size})
fire_entity:set_attach(obj, "", offset, {x = 0, y = 0, z = 0}) fire_entity:set_attach(obj, "", offset, {x = 0, y = 0, z = 0})
local fire_luaentity = fire_entity:get_luaentity() 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 for _, other in pairs(minetest.get_objects_inside_radius(fire_entity:get_pos(), 0)) do
local other_luaentity = other:get_luaentity() local other_luaentity = other:get_luaentity()
@ -111,9 +105,7 @@ function mcl_burning.extinguish(obj)
if mcl_burning.is_burning(obj) then if mcl_burning.is_burning(obj) then
local storage = mcl_burning.get_storage(obj) local storage = mcl_burning.get_storage(obj)
if obj:is_player() then if obj:is_player() then
if storage.fire_hud_id then mcl_burning.channels[obj]:send_all("stop")
obj:hud_remove(storage.fire_hud_id)
end
mcl_burning.storage[obj] = {} mcl_burning.storage[obj] = {}
else else
storage.burn_time = nil storage.burn_time = nil

View File

@ -7,6 +7,7 @@ local get_item_group = minetest.get_item_group
mcl_burning = { mcl_burning = {
storage = {}, storage = {},
channels = {},
animation_frames = tonumber(minetest.settings:get("fire_animation_frames")) or 8 animation_frames = tonumber(minetest.settings:get("fire_animation_frames")) or 8
} }
@ -54,12 +55,11 @@ minetest.register_on_joinplayer(function(player)
end end
mcl_burning.storage[player] = storage mcl_burning.storage[player] = storage
mcl_burning.channels[player] = minetest.mod_channel_join("mcl_burning:" .. player:get_player_name())
end) end)
minetest.register_on_leaveplayer(function(player) minetest.register_on_leaveplayer(function(player)
local storage = mcl_burning.storage[player] player:get_meta():set_string("mcl_burning:data", minetest.serialize(mcl_burning.storage[player]))
storage.fire_hud_id = nil
player:get_meta():set_string("mcl_burning:data", minetest.serialize(storage))
mcl_burning.storage[player] = nil mcl_burning.storage[player] = nil
end) end)
@ -68,27 +68,28 @@ minetest.register_entity("mcl_burning:fire", {
initial_properties = { initial_properties = {
physical = false, physical = false,
collisionbox = {0, 0, 0, 0, 0, 0}, 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, pointable = false,
glow = -1, glow = -1,
backface_culling = false, backface_culling = false,
}, },
animation_frame = 0, animation_frame = 0,
animation_timer = 0, animation_timer = 0,
on_step = function(self, dtime) on_activate = function(self)
local parent, storage = self:sanity_check() self.object:set_sprite({x = 0, y = 0}, mcl_burning.animation_frames, 1.0 / mcl_burning.animation_frames)
end,
if parent then on_step = function(self)
self.animation_timer = self.animation_timer + dtime if not self:sanity_check() then
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
self.object:remove() self.object:remove()
end end
end, end,
@ -96,23 +97,15 @@ minetest.register_entity("mcl_burning:fire", {
local parent = self.object:get_attach() local parent = self.object:get_attach()
if not parent then if not parent then
return return false
end end
local storage = mcl_burning.get_storage(parent) local storage = mcl_burning.get_storage(parent)
if not storage or not storage.burn_time then if not storage or not storage.burn_time then
return return false
end end
return parent, storage return true
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
end, end,
}) })

View File

@ -480,7 +480,7 @@ minetest.register_entity(":__builtin:item", {
end, end,
get_staticdata = function(self) get_staticdata = function(self)
return minetest.serialize({ local data = minetest.serialize({
itemstring = self.itemstring, itemstring = self.itemstring,
always_collect = self.always_collect, always_collect = self.always_collect,
age = self.age, age = self.age,
@ -488,6 +488,39 @@ minetest.register_entity(":__builtin:item", {
_flowing = self._flowing, _flowing = self._flowing,
_removed = self._removed, _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, end,
on_activate = function(self, staticdata, dtime_s) on_activate = function(self, staticdata, dtime_s)
@ -575,7 +608,7 @@ minetest.register_entity(":__builtin:item", {
return true return true
end, end,
on_step = function(self, dtime) on_step = function(self, dtime, moveresult)
if self._removed then if self._removed then
self.object:set_properties({ self.object:set_properties({
physical = false physical = false
@ -642,6 +675,18 @@ minetest.register_entity(":__builtin:item", {
end end
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 -- Push item out when stuck inside solid opaque node
if def and def.walkable and def.groups and def.groups.opaque == 1 then if def and def.walkable and def.groups and def.groups.opaque == 1 then
local shootdir local shootdir

View File

@ -646,7 +646,7 @@ register_minecart(
if player then if player then
mcl_player.player_set_animation(player, "sit" , 30) 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}) 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
end, name) end, name)
end end

View File

@ -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é 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 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é Can be ignited by tools or powered activator rail=Peut être allumé par des outils ou un rail d'activation motorisé
Sneak to dismount=

View File

@ -1,6 +1,6 @@
name = mcl_minecarts name = mcl_minecarts
author = Krock author = Krock
description = Minecarts are vehicles to move players quickly on rails. 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 optional_depends = doc_identifier, mcl_wip

View File

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

View File

@ -233,4 +233,4 @@ mobs:spawn(spawn_grass)
mobs:register_egg("mobs_mc:rabbit", S("Rabbit"), "mobs_mc_spawn_icon_rabbit.png", 0) mobs:register_egg("mobs_mc:rabbit", S("Rabbit"), "mobs_mc_spawn_icon_rabbit.png", 0)
-- Note: This spawn egg does not exist in Minecraft -- 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

View File

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

View File

@ -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")

View File

@ -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)

View File

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

View File

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

View File

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

View File

@ -107,3 +107,8 @@ tt.register_snippet(function(itemstring)
end end
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)

View File

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

View File

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

View File

@ -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=

View File

@ -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

View File

@ -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=

View File

@ -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
View 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
View 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,
})
]]

View File

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

View File

@ -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>.

View File

@ -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)

View File

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

View File

@ -168,6 +168,60 @@ local dispenserdef = {
end end
inv:set_stack("main", stack_id, stack) 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 -- Spawn Egg
elseif igroups.spawn_egg then elseif igroups.spawn_egg then
-- Spawn mob -- Spawn mob

View File

@ -53,6 +53,15 @@ local function get_consumed_materials(tool, material)
return materials_used return materials_used
end 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. -- 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 ("tool", input1, input2) if input1 is tool and input2 is material.
-- Returns ("material", input2, input1) if input1 is material and input2 is tool. -- 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 function distinguish_tool_and_material(input1, input2)
local def1 = input1:get_definition() local def1 = input1:get_definition()
local def2 = input2: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 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 return "material", input2, input1
else else
return nil return nil
@ -121,11 +136,28 @@ local function update_anvil_slots(meta)
local distinguished, tool, material = distinguish_tool_and_material(input1, input2) local distinguished, tool, material = distinguish_tool_and_material(input1, input2)
if distinguished then if distinguished then
local tooldef = tool:get_definition() local tooldef = tool:get_definition()
local repair = tooldef._repair_material
local has_correct_material = false local has_correct_material = false
if string.sub(tooldef._repair_material, 1, 6) == "group:" then local material_name = material:get_name()
has_correct_material = minetest.get_item_group(material:get_name(), string.sub(tooldef._repair_material, 7)) ~= 0 if type(repair) == "string" then
elseif material:get_name() == tooldef._repair_material then if string.sub(repair, 1, 6) == "group:" then
has_correct_material = true 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 end
if has_correct_material and tool:get_wear() > 0 then if has_correct_material and tool:get_wear() > 0 then
local materials_used = get_consumed_materials(tool, material) local materials_used = get_consumed_materials(tool, material)
@ -284,6 +316,12 @@ local function damage_anvil_by_falling(pos, distance)
end end
end end
local anvilbox = {
type = "fixed",
fixed = {
{ -8 / 16, -8 / 16, -6 / 16, 8 / 16, 8 / 16, 6 / 16 },
},
}
local anvildef = { local anvildef = {
groups = {pickaxey=1, falling_node=1, falling_node_damage=1, crush_after_fall=1, deco_block=1, anvil=1}, 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"}, 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 = { node_box = {
type = "fixed", type = "fixed",
fixed = { fixed = {
{-8/16, 2/16, -5/16, 8/16, 8/16, 5/16}, -- top { -6 / 16, -8 / 16, -6 / 16, 6 / 16, -4 / 16, 6 / 16 },
{-5/16, -4/16, -2/16, 5/16, 5/16, 2/16}, -- middle { -5 / 16, -4 / 16, -4 / 16, 5 / 16, -3 / 16, 4 / 16 },
{-8/16, -8/16, -5/16, 8/16, -4/16, 5/16}, -- base { -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(), sounds = mcl_sounds.node_sound_metal_defaults(),
_mcl_blast_resistance = 1200, _mcl_blast_resistance = 1200,
_mcl_hardness = 5, _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

View File

@ -1,5 +1,5 @@
name = mcl_armor name = mcl_armor
author = stu author = stu
description = Adds craftable armor that is visible to other players. 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 optional_depends = mcl_fire, ethereal, bakedclay

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 B

After

Width:  |  Height:  |  Size: 409 B

View File

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

View File

@ -1,4 +1,4 @@
name = mcl_brewing name = mcl_brewing
author = bzoss author = bzoss
depends = mcl_init, mcl_formspec, mcl_sounds, mcl_potions, mcl_mobitems 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

View File

@ -9,13 +9,46 @@ Accept folowing params:
* string: name of the node to place * string: name of the node to place
* function(pos): will returns name of the node to place with pos being the placement position * 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 * 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) * inventory_image: texture of the new bucket item (ignored if itemname == nil)
* name: user-visible bucket description * name: user-visible bucket description
* longdesc: long explanatory description (for help) * longdesc: long explanatory description (for help)
* usagehelp: short usage explanation (for help) * usagehelp: short usage explanation (for help)
* tt_help: very short tooltip 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 * 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 },
})
```

View File

@ -1,9 +1,12 @@
Bucket mod. # MineClone2 Bucket (`mcl_bucket`)
Originally taken from Minetest Game, adapted for MineClone 2. 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 Kahrl <kahrl@gmx.net>
Copyright (C) 2011-2012 celeron55, Perttu Ahola <celeron55@gmail.com> Copyright (C) 2011-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify

View File

@ -3,6 +3,7 @@ local modname = minetest.get_current_modname()
local S = minetest.get_translator(modname) local S = minetest.get_translator(modname)
local modpath = minetest.get_modpath(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_empty", "mcl_buckets:bucket_empty")
minetest.register_alias("bucket:bucket_water", "mcl_buckets:bucket_water") minetest.register_alias("bucket:bucket_water", "mcl_buckets:bucket_water")
minetest.register_alias("bucket:bucket_lava", "mcl_buckets:bucket_lava") 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_mcl_core = minetest.get_modpath("mcl_core")
--local mod_mclx_core = minetest.get_modpath("mclx_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 if mod_mcl_core then
minetest.register_craft({ minetest.register_craft({
output = "mcl_buckets:bucket_empty 1", output = "mcl_buckets:bucket_empty 1",
recipe = { recipe = {
{"mcl_core:iron_ingot", "", "mcl_core:iron_ingot"}, {"mcl_core:iron_ingot", "", "mcl_core:iron_ingot"},
{"", "mcl_core:iron_ingot", ""}, {"", "mcl_core:iron_ingot", ""},
} },
}) })
end end
@ -25,147 +37,218 @@ mcl_buckets = {}
mcl_buckets.liquids = {} mcl_buckets.liquids = {}
-- Sound helper functions for placing and taking 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] local def = minetest.registered_nodes[itemname]
if def and def.sounds and def.sounds.place then 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) minetest.sound_play(def.sounds.place, {gain=1.0, pos = pos, pitch = 1 + math.random(-10, 10)*0.005}, true)
end end
end end
local sound_take = function(itemname, pos) local function sound_take(itemname, pos)
local def = minetest.registered_nodes[itemname] local def = minetest.registered_nodes[itemname]
if def and def.sounds and def.sounds.dug then 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) minetest.sound_play(def.sounds.dug, {gain=1.0, pos = pos, pitch = 1 + math.random(-10, 10)*0.005}, true)
end end
end end
local place_liquid = function(pos, itemstring) local function place_liquid(pos, itemstring)
local fullness = minetest.registered_nodes[itemstring].liquid_range local fullness = minetest.registered_nodes[itemstring].liquid_range
sound_place(itemstring, pos) sound_place(itemstring, pos)
minetest.add_node(pos, {name=itemstring, param2=fullness}) minetest.add_node(pos, {name=itemstring, param2=fullness})
end 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) function mcl_buckets.register_liquid(def)
for i=1, #def.source_take do for _,source in ipairs(def.source_take) do
mcl_buckets.liquids[def.source_take[i]] = { mcl_buckets.liquids[source] = {
source_place = def.source_place, source_place = def.source_place,
source_take = def.source_take[i], source_take = source,
on_take = def.on_take, on_take = def.on_take,
itemname = def.itemname, bucketname = def.bucketname,
} }
pointable_sources[source] = true
if type(def.source_place) == "string" then 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
end end
if def.itemname then if def.bucketname == nil or def.bucketname == "" then
minetest.register_craftitem(def.itemname, { error(string.format("[mcl_bucket] Invalid itemname then registering [%s]!", def.name))
description = def.name, end
_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
local node = minetest.get_node(pointed_thing.under) minetest.register_craftitem(def.bucketname, {
local place_pos = pointed_thing.under description = def.name,
local nn = node.name _doc_items_longdesc = def.longdesc,
local nodedef = minetest.registered_nodes[nn] _doc_items_usagehelp = def.usagehelp,
-- Call on_rightclick if the pointed node defines it _tt_help = def.tt_help,
if user and not user:get_player_control().sneak then inventory_image = def.inventory_image,
if nodedef and nodedef.on_rightclick then stack_max = 1,
return nodedef.on_rightclick(place_pos, node, user, itemstack) or itemstack groups = def.groups,
end on_place = function(itemstack, user, pointed_thing)
end -- 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 local undernode = get_node(pointed_thing.under)
if type(def.source_place) == "function" then local abovenode = get_node(pointed_thing.above)
node_place = def.source_place(place_pos) local buildable1 = minetest.registered_nodes[undernode.name] and minetest.registered_nodes[undernode.name].buildable_to
else local buildable2 = minetest.registered_nodes[abovenode.name] and minetest.registered_nodes[abovenode.name].buildable_to
node_place = def.source_place if not buildable1 and not buildable2 then return itemstack end --if both nodes aren't buildable_to, skip
end
-- Check if pointing to a buildable node
--local item = itemstack:get_name()
if def.extra_check and def.extra_check(place_pos, user) == true and nodedef and nodedef.buildable_to then if buildable1 then
-- buildable; replace the node 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() 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 return itemstack
end 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 if mod_doc and doc.entry_exists("nodes", node_place) then
doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place) doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place)
end 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 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 -- Check protection
if not minetest.is_creative_enabled(user:get_player_name()) then if minetest.is_protected(pointed_thing.above, pns) then
-- Add empty bucket and put it into inventory, if possible. minetest.record_protection_violation(pointed_thing.above, pns)
-- 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()
return itemstack return itemstack
end 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 -- Place liquid
-- Fail placement of liquid place_liquid(pointed_thing.above, node_place)
if def.extra_check and def.extra_check(droppos, nil) == true and buildable then
-- buildable; replace the node -- Update doc mod
local node_place if mod_doc and doc.entry_exists("nodes", node_place) then
if type(def.source_place) == "function" then doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place)
node_place = def.source_place(droppos)
else
node_place = def.source_place
end end
place_liquid(droppos, node_place)
stack:set_name("mcl_buckets:bucket_empty")
end end
return stack return get_bucket_drop(itemstack, user, take_bucket)
end, else
}) return itemstack
end 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 end
minetest.register_craftitem("mcl_buckets:bucket_empty", { 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_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."), _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"), _tt_help = S("Collects liquids"),
--liquids_pointable = true,
liquids_pointable = true,
inventory_image = "bucket.png", inventory_image = "bucket.png",
stack_max = 16, stack_max = 16,
on_place = function(itemstack, user, pointed_thing) on_place = function(itemstack, user, pointed_thing)
@ -184,74 +266,70 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", {
end end
-- Call on_rightclick if the pointed node defines it -- 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 node = minetest.get_node(pointed_thing.under)
local nn = node.name 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 local new_bucket
if liquiddef and liquiddef.itemname and (nn == liquiddef.source_take) then local liquid_node = bucket_raycast(user)
if liquid_node then
-- Fill bucket, but not in Creative Mode if minetest.is_protected(liquid_node.above, user:get_player_name()) then
if not minetest.is_creative_enabled(user:get_player_name()) then minetest.record_protection_violation(liquid_node.above, user:get_player_name())
new_bucket = ItemStack({name = liquiddef.itemname})
if liquiddef.on_take then
liquiddef.on_take(user)
end
end 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"}) if mod_doc and doc.entry_exists("nodes", liquid_name) then
sound_take(nn, pointed_thing.under) doc.mark_entry_as_revealed(user:get_player_name(), "nodes", liquid_name)
end
if mod_doc and doc.entry_exists("nodes", nn) then if new_bucket then
doc.mark_entry_as_revealed(user:get_player_name(), "nodes", nn) return give_bucket(new_bucket, itemstack, user)
end 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)
else 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 end
if not minetest.is_creative_enabled(user:get_player_name()) then
itemstack:take_item()
end
return itemstack
end 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, end,
_on_dispense = function(stack, pos, droppos, dropnode, dropdir) _on_dispense = function(stack, pos, droppos, dropnode, dropdir)
-- Fill empty bucket with liquid or drop bucket if no liquid -- 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 liquiddef = mcl_buckets.liquids[dropnode.name]
local new_bucket 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 -- Fill bucket
new_bucket = ItemStack({name = liquiddef.itemname}) new_bucket = ItemStack({name = liquiddef.bucketname})
sound_take(dropnode.name, droppos) sound_take(dropnode.name, droppos)
collect_liquid = true collect_liquid = true
end end

View File

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

View File

@ -3,7 +3,7 @@ local mod_mcl_core = minetest.get_modpath("mcl_core")
local mod_mclx_core = minetest.get_modpath("mclx_core") local mod_mclx_core = minetest.get_modpath("mclx_core")
local has_awards = minetest.get_modpath("awards") 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] local def = minetest.registered_nodes[itemname]
if def and def.sounds and def.sounds.place then 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) 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") awards.unlock(user:get_player_name(), "mcl:hotStuff")
end end
end, end,
itemname = "mcl_buckets:bucket_lava", bucketname = "mcl_buckets:bucket_lava",
inventory_image = "bucket_lava.png", inventory_image = "bucket_lava.png",
name = S("Lava Bucket"), 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."), 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({ mcl_buckets.register_liquid({
source_place = "mcl_core:water_source", source_place = "mcl_core:water_source",
source_take = {"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", inventory_image = "bucket_water.png",
name = S("Water Bucket"), name = S("Water Bucket"),
longdesc = S("A bucket can be used to collect and release liquids. This one is filled with water."), 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."), usagehelp = S("Place it to empty the bucket and create a water source."),
tt_help = S("Places a water source"), tt_help = S("Places a water source"),
extra_check = function(pos, placer) 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 local nn = minetest.get_node(pos).name
-- Pour water into cauldron -- Pour water into cauldron
if minetest.get_item_group(nn, "cauldron") ~= 0 then 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"}) minetest.set_node(pos, {name="mcl_cauldrons:cauldron_3"})
end end
sound_place("mcl_core:water_source", pos) sound_place("mcl_core:water_source", pos)
return false return false, true
-- Evaporate water if used in Nether (except on cauldron) -- Evaporate water if used in Nether (except on cauldron)
else else
local dim = mcl_worlds.pos_to_dimension(pos) local dim = mcl_worlds.pos_to_dimension(pos)
if dim == "nether" then if dim == "nether" then
minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true) minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true)
return false return false, true
end end
end end
end, end,
@ -89,22 +80,13 @@ if mod_mclx_core then
mcl_buckets.register_liquid({ mcl_buckets.register_liquid({
source_place = "mclx_core:river_water_source", source_place = "mclx_core:river_water_source",
source_take = {"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", inventory_image = "bucket_river_water.png",
name = S("River Water Bucket"), name = S("River Water Bucket"),
longdesc = S("A bucket can be used to collect and release liquids. This one is filled with river water."), 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."), usagehelp = S("Place it to empty the bucket and create a river water source."),
tt_help = S("Places a river water source"), tt_help = S("Places a river water source"),
extra_check = function(pos, placer) 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 local nn = minetest.get_node(pos).name
-- Pour into cauldron -- Pour into cauldron
if minetest.get_item_group(nn, "cauldron") ~= 0 then 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"}) minetest.set_node(pos, {name="mcl_cauldrons:cauldron_3r"})
end end
sound_place("mcl_core:water_source", pos) sound_place("mcl_core:water_source", pos)
return false return false, true
else else
-- Evaporate water if used in Nether (except on cauldron) -- Evaporate water if used in Nether (except on cauldron)
local dim = mcl_worlds.pos_to_dimension(pos) local dim = mcl_worlds.pos_to_dimension(pos)
if dim == "nether" then if dim == "nether" then
minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true) minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true)
return false return false, true
end end
end end
end, end,

View File

@ -1133,7 +1133,7 @@ for color, desc in pairs(boxtypes) do
if mod_doc then if mod_doc then
if is_canonical 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.") 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") entry_name = S("Shulker Box")
else else
create_entry = false create_entry = false

View File

@ -24,7 +24,7 @@ Red Shulker Box=
Grey Shulker Box= Grey Shulker Box=
Black 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.= 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= Shulker Box=
Large Chest= Large Chest=
Inventory= Inventory=

View File

@ -184,6 +184,7 @@ minetest.register_abm({
end, end,
}) })
-- Cactus mechanisms
minetest.register_abm({ minetest.register_abm({
label = "Cactus growth", label = "Cactus growth",
nodenames = {"mcl_core:cactus"}, nodenames = {"mcl_core:cactus"},
@ -195,19 +196,31 @@ minetest.register_abm({
end, end,
}) })
-- Make cactus destroy items
minetest.register_abm({ minetest.register_abm({
label = "Cactus destroy items", label = "Cactus mechanisms",
nodenames = {"mcl_core:cactus"}, nodenames = {"mcl_core:cactus"},
interval = 1, interval = 1,
chance = 1, chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider) 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() local entity = object:get_luaentity()
if entity and entity.name == "__builtin:item" then if entity and entity.name == "__builtin:item" then
object:remove() object:remove()
end end
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, end,
}) })

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,8 @@
# textdomain: mcl_maps # textdomain: mcl_maps
Empty Map=Carte Vierge 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. 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 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.

View File

@ -1,4 +1,4 @@
name = mcl_portals name = mcl_portals
description = Adds buildable portals to the Nether and End dimensions. 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 optional_depends = awards, doc

View File

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

View File

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

View File

@ -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 -- Make red sand, red sandstone and more craftable in v6
-- NOTE: When you change these, also update mcl_craftguide for the "v6" icon in -- NOTE: When you change these, also update mcl_craftguide for the "v6" icon in
-- the craft guide! -- the craft guide!

View File

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

View File

@ -1,5 +1,5 @@
name = mcl_playerplus name = mcl_playerplus
author = TenPlus1 author = TenPlus1
description = Adds some simple player-related gameplay effects: Hurt by touching a cactus, suffocation and more. 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

View File

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

View File

@ -153,3 +153,7 @@ fix_doubleplants (Mcimport double plant fixes) bool true
# Allow players to create Minecraft-like maps. # Allow players to create Minecraft-like maps.
enable_real_maps (Enable Real Maps) bool true 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