Merge pull request 'Formspec Refactoring' (#2635) from AFCMS/MineClone2:formspec-v4 into master
Reviewed-on: https://git.minetest.land/MineClone2/MineClone2/pulls/2635 Reviewed-by: 𝕵𝖔𝖍𝖆𝖓𝖓𝖊𝖘 𝕱𝖗𝖎𝖙𝖟 <mrrar@noreply.git.minetest.land> Reviewed-by: ancientmarinerdev <ancientmariner_dev@proton.me>
@ -1,3 +1,5 @@
|
||||
---@diagnostic disable
|
||||
|
||||
unused_args = false
|
||||
allow_defined_top = true
|
||||
max_line_length = false
|
||||
|
22
.luarc.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"runtime.version": "LuaJIT",
|
||||
"diagnostics": { "disable": ["lowercase-global"] },
|
||||
"diagnostics.globals": [
|
||||
"minetest",
|
||||
"dump",
|
||||
"dump2",
|
||||
"Raycast",
|
||||
"Settings",
|
||||
"PseudoRandom",
|
||||
"PerlinNoise",
|
||||
"VoxelManip",
|
||||
"SecureRandom",
|
||||
"VoxelArea",
|
||||
"PerlinNoiseMap",
|
||||
"PcgRandom",
|
||||
"ItemStack",
|
||||
"AreaStore",
|
||||
"vector"
|
||||
],
|
||||
"workspace.ignoreDir": [".luacheckrc"]
|
||||
}
|
@ -147,13 +147,13 @@ function mcl_experience.throw_xp(pos, total_xp)
|
||||
|
||||
obj:set_velocity(vector.new(
|
||||
math.random(-2, 2) * math.random(),
|
||||
math.random( 2, 5),
|
||||
math.random(2, 5),
|
||||
math.random(-2, 2) * math.random()
|
||||
))
|
||||
|
||||
i = i + xp
|
||||
j = j + 1
|
||||
table.insert(obs,obj)
|
||||
table.insert(obs, obj)
|
||||
end
|
||||
return obs
|
||||
end
|
||||
@ -179,18 +179,18 @@ function mcl_experience.setup_hud(player)
|
||||
if not minetest.is_creative_enabled(player:get_player_name()) then
|
||||
hud_bars[player] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0.5, y = 1},
|
||||
offset = {x = (-9 * 28) - 3, y = -(48 + 24 + 16 - 5)},
|
||||
scale = {x = 0.35, y = 0.375},
|
||||
alignment = {x = 1, y = 1},
|
||||
position = { x = 0.5, y = 1 },
|
||||
offset = { x = (-9 * 28) - 3, y = -(48 + 24 + 16 - 5) },
|
||||
scale = { x = 0.35, y = 0.375 },
|
||||
alignment = { x = 1, y = 1 },
|
||||
z_index = 11,
|
||||
})
|
||||
|
||||
hud_levels[player] = player:hud_add({
|
||||
hud_elem_type = "text",
|
||||
position = {x = 0.5, y = 1},
|
||||
position = { x = 0.5, y = 1 },
|
||||
number = 0x80FF20,
|
||||
offset = {x = 0, y = -(48 + 24 + 24)},
|
||||
offset = { x = 0, y = -(48 + 24 + 24) },
|
||||
z_index = 12,
|
||||
})
|
||||
end
|
||||
@ -221,7 +221,7 @@ function mcl_experience.update(player)
|
||||
end
|
||||
|
||||
function mcl_experience.register_on_add_xp(func, priority)
|
||||
table.insert(mcl_experience.on_add_xp, {func = func, priority = priority or 0})
|
||||
table.insert(mcl_experience.on_add_xp, { func = func, priority = priority or 0 })
|
||||
end
|
||||
|
||||
-- callbacks
|
||||
@ -247,3 +247,12 @@ end)
|
||||
minetest.register_on_mods_loaded(function()
|
||||
table.sort(mcl_experience.on_add_xp, function(a, b) return a.priority < b.priority end)
|
||||
end)
|
||||
|
||||
mcl_gamemode.register_on_gamemode_change(function(player, old_gamemode, new_gamemode)
|
||||
if new_gamemode == "survival" then
|
||||
mcl_experience.setup_hud(player)
|
||||
mcl_experience.update(player)
|
||||
elseif new_gamemode == "creative" then
|
||||
mcl_experience.remove_hud(player)
|
||||
end
|
||||
end)
|
||||
|
@ -1,3 +1,4 @@
|
||||
name = mcl_experience
|
||||
author = oilboi
|
||||
description = eXPerience mod
|
||||
depends = mcl_gamemode
|
||||
|
40
mods/HUD/mcl_formspec/API.md
Normal file
@ -0,0 +1,40 @@
|
||||
# MineClone2 Formspec API
|
||||
|
||||
## `mcl_formspec.label_color`
|
||||
|
||||
Contains the color used for formspec labels, currently `#313131`.
|
||||
|
||||
## `mcl_formspec.get_itemslot_bg(x, y, w, h)`
|
||||
|
||||
Get the background of inventory slots (formspec version = 1)
|
||||
|
||||
ex:
|
||||
|
||||
```lua
|
||||
local formspec = table.concat({
|
||||
mcl_formspec.get_itemslot_bg(0, 0, 5, 2),
|
||||
"list[current_player;super_inventory;0,0;5,2;]",
|
||||
})
|
||||
```
|
||||
|
||||
## `mcl_formspec.get_itemslot_bg_v4(x, y, w, h, size, texture)`
|
||||
|
||||
Get the background of inventory slots (formspec version > 1)
|
||||
|
||||
Works basically the same as `mcl_formspec.get_itemslot_bg(x, y, w, h)` but have more customisation options:
|
||||
|
||||
- `size`: allow you to customize the size of the slot borders, default is 0.05
|
||||
- `texture`: allow you to specify a custom texture tu use instead of the default one
|
||||
|
||||
ex:
|
||||
|
||||
```lua
|
||||
local formspec = table.concat({
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 0.375, 5, 2, 0.1, "super_slot_background.png"),
|
||||
"list[current_player;super_inventory;0.375,0.375;5,2;]",
|
||||
})
|
||||
```
|
||||
|
||||
## `mcl_formspec.itemslot_border_size`
|
||||
|
||||
Contains the default item slot border size used by `mcl_formspec.get_itemslot_bg_v4`, currently 0.05
|
21
mods/HUD/mcl_formspec/FORMSPEC_GUIDE.md
Normal file
@ -0,0 +1,21 @@
|
||||
# MineClone2 Formspec Guide
|
||||
|
||||
**_This guide will teach you the rules for creating formspecs for the MineClone2 game._**
|
||||
|
||||
Formspecs are an important part of game and mod development.
|
||||
|
||||
First of all, MineClone2 aims to support ONLY last formspec version. Many utility functions will not work with formspec v1 or v2.
|
||||
|
||||
The typical width of an 9 slots width inventory formspec is `0.375 + 9 + ((9-1) * 0.25) + 0.375 = 11.75`
|
||||
|
||||
Margins are 0.375.
|
||||
|
||||
The labels color is `mcl_formspec.label_color`
|
||||
|
||||
Space between 1st inventory line and the rest of inventory is 0.45
|
||||
|
||||
Labels should have 0.375 space above if there is no other stuff above and 0.45 between content
|
||||
|
||||
- 0.375 under
|
||||
|
||||
According to minetest modding book, table.concat is faster than string concatenation, so this method should be prefered (the code is also more clear)
|
@ -1,10 +1,55 @@
|
||||
mcl_formspec = {}
|
||||
|
||||
mcl_formspec.label_color = "#313131"
|
||||
|
||||
---Get the background of inventory slots (formspec version = 1)
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@param w number
|
||||
---@param h number
|
||||
---@return string
|
||||
function mcl_formspec.get_itemslot_bg(x, y, w, h)
|
||||
local out = ""
|
||||
for i = 0, w - 1, 1 do
|
||||
for j = 0, h - 1, 1 do
|
||||
out = out .."image["..x+i..","..y+j..";1,1;mcl_formspec_itemslot.png]"
|
||||
out = out .. "image[" .. x + i .. "," .. y + j .. ";1,1;mcl_formspec_itemslot.png]"
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
---This function will replace mcl_formspec.get_itemslot_bg then every formspec will be upgrade to version 4
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@param size number
|
||||
---@param texture? string
|
||||
---@return string
|
||||
---@nodiscard
|
||||
local function get_slot(x, y, size, texture)
|
||||
local t = "image[" .. x - size .. "," .. y - size .. ";" .. 1 + (size * 2) ..
|
||||
"," .. 1 + (size * 2) .. ";" .. (texture and texture or "mcl_formspec_itemslot.png") .. "]"
|
||||
return t
|
||||
end
|
||||
|
||||
mcl_formspec.itemslot_border_size = 0.05
|
||||
|
||||
---Get the background of inventory slots (formspec version > 1)
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@param w integer
|
||||
---@param h integer
|
||||
---@param size? number Optional size of the slot border (default: 0.05)
|
||||
---@param texture? string Optional texture to replace the default one
|
||||
---@return string
|
||||
---@nodiscard
|
||||
function mcl_formspec.get_itemslot_bg_v4(x, y, w, h, size, texture)
|
||||
if not size then
|
||||
size = mcl_formspec.itemslot_border_size
|
||||
end
|
||||
local out = ""
|
||||
for i = 0, w - 1, 1 do
|
||||
for j = 0, h - 1, 1 do
|
||||
out = out .. get_slot(x + i + (i * 0.25), y + j + (j * 0.25), size, texture)
|
||||
end
|
||||
end
|
||||
return out
|
||||
|
35
mods/HUD/mcl_inventory/API.md
Normal file
@ -0,0 +1,35 @@
|
||||
# `mcl_inventory`
|
||||
|
||||
## `mcl_inventory.register_survival_inventory_tab(def)`
|
||||
|
||||
```lua
|
||||
mcl_inventory.register_survival_inventory_tab({
|
||||
-- Page identifier
|
||||
-- Used to uniquely identify the tab
|
||||
id = "test",
|
||||
|
||||
-- The tab description, can be translated
|
||||
description = "Test",
|
||||
|
||||
-- The name of the item that will be used as icon
|
||||
item_icon = "mcl_core:stone",
|
||||
|
||||
-- If true, the main inventory will be shown at the bottom of the tab
|
||||
-- Listrings need to be added by hand
|
||||
show_inventory = true,
|
||||
|
||||
-- This function must return the tab's formspec for the player
|
||||
build = function(player)
|
||||
return "label[1,1;Hello hello]button[2,2;2,2;Hello;hey]"
|
||||
end,
|
||||
|
||||
-- This function will be called in the on_player_receive_fields callback if the tab is currently open
|
||||
handle = function(player, fields)
|
||||
print(dump(fields))
|
||||
end,
|
||||
|
||||
-- This function will be called to know if a player can see the tab
|
||||
-- Returns true by default
|
||||
access = function(player)
|
||||
end,
|
||||
```
|
@ -3,19 +3,35 @@ local F = minetest.formspec_escape
|
||||
local C = minetest.colorize
|
||||
|
||||
-- Prepare player info table
|
||||
---@type table<string, {page: string, filter: string, start_i: integer, inv_size: integer}>
|
||||
local players = {}
|
||||
|
||||
-- Containing all the items for each Creative Mode tab
|
||||
---@type table<string, string[]>
|
||||
local inventory_lists = {}
|
||||
|
||||
--local mod_player = minetest.get_modpath("mcl_player")
|
||||
|
||||
-- Create tables
|
||||
local builtin_filter_ids = {"blocks","deco","redstone","rail","food","tools","combat","mobs","brew","matr","misc","all"}
|
||||
---@type string[]
|
||||
local builtin_filter_ids = {
|
||||
"blocks",
|
||||
"deco",
|
||||
"redstone",
|
||||
"rail",
|
||||
"food",
|
||||
"tools",
|
||||
"combat",
|
||||
"mobs",
|
||||
"brew",
|
||||
"matr",
|
||||
"misc",
|
||||
"all"
|
||||
}
|
||||
|
||||
for _, f in pairs(builtin_filter_ids) do
|
||||
inventory_lists[f] = {}
|
||||
end
|
||||
|
||||
---@param tbl string[]
|
||||
local function replace_enchanted_books(tbl)
|
||||
for k, item in ipairs(tbl) do
|
||||
if item:find("mcl_enchanting:book_enchanted") == 1 then
|
||||
@ -28,20 +44,32 @@ local function replace_enchanted_books(tbl)
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Populate all the item tables. We only do this once. Note this code must be
|
||||
executed after loading all the other mods in order to work. ]]
|
||||
-- Populate all the item tables. We only do this once.
|
||||
-- Note this code must be executed after loading all the other mods in order to work.
|
||||
minetest.register_on_mods_loaded(function()
|
||||
for name,def in pairs(minetest.registered_items) do
|
||||
if (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0) and def.description and def.description ~= "" then
|
||||
for name, def in pairs(minetest.registered_items) do
|
||||
if (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0) and def.description and
|
||||
def.description ~= "" then
|
||||
---@param def mt.ItemDef|mt.NodeDef
|
||||
local function is_redstone(def)
|
||||
return def.mesecons or def.groups.mesecon or def.groups.mesecon_conductor_craftable or def.groups.mesecon_effecor_off
|
||||
return def.mesecons or def.groups.mesecon or def.groups.mesecon_conductor_craftable or
|
||||
def.groups.mesecon_effecor_off
|
||||
end
|
||||
|
||||
---@param def mt.ItemDef|mt.NodeDef
|
||||
local function is_tool(def)
|
||||
return def.groups.tool or (def.tool_capabilities and def.tool_capabilities.damage_groups == nil)
|
||||
end
|
||||
|
||||
---@param def mt.ItemDef|mt.NodeDef
|
||||
local function is_weapon_or_armor(def)
|
||||
return def.groups.weapon or def.groups.weapon_ranged or def.groups.ammo or def.groups.combat_item or ((def.groups.armor_head or def.groups.armor_torso or def.groups.armor_legs or def.groups.armor_feet or def.groups.horse_armor) and def.groups.non_combat_armor ~= 1)
|
||||
return def.groups.weapon or def.groups.weapon_ranged or def.groups.ammo or def.groups.combat_item or
|
||||
(
|
||||
(
|
||||
def.groups.armor_head or def.groups.armor_torso or def.groups.armor_legs or def.groups.armor_feet or
|
||||
def.groups.horse_armor) and def.groups.non_combat_armor ~= 1)
|
||||
end
|
||||
|
||||
-- Is set to true if it was added in any category besides misc
|
||||
local nonmisc = false
|
||||
if def.groups.building_block then
|
||||
@ -110,6 +138,11 @@ minetest.register_on_mods_loaded(function()
|
||||
end
|
||||
end)
|
||||
|
||||
---@param name string
|
||||
---@param description string
|
||||
---@param lang mt.LangCode
|
||||
---@param filter string
|
||||
---@return integer
|
||||
local function filter_item(name, description, lang, filter)
|
||||
local desc
|
||||
if not lang then
|
||||
@ -120,13 +153,16 @@ local function filter_item(name, description, lang, filter)
|
||||
return string.find(name, filter, nil, true) or string.find(desc, filter, nil, true)
|
||||
end
|
||||
|
||||
---@param filter string
|
||||
---@param player mt.PlayerObjectRef
|
||||
local function set_inv_search(filter, player)
|
||||
local playername = player:get_player_name()
|
||||
local inv = minetest.get_inventory({type="detached", name="creative_"..playername})
|
||||
local inv = minetest.get_inventory({ type = "detached", name = "creative_" .. playername })
|
||||
local creative_list = {}
|
||||
local lang = minetest.get_player_information(playername).lang_code
|
||||
for name,def in pairs(minetest.registered_items) do
|
||||
if (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0) and def.description and def.description ~= "" then
|
||||
for name, def in pairs(minetest.registered_items) do
|
||||
if (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0) and def.description and
|
||||
def.description ~= "" then
|
||||
if filter_item(string.lower(def.name), def.description, lang, filter) then
|
||||
table.insert(creative_list, name)
|
||||
end
|
||||
@ -147,9 +183,11 @@ local function set_inv_search(filter, player)
|
||||
inv:set_list("main", creative_list)
|
||||
end
|
||||
|
||||
---@param page string
|
||||
---@param player mt.PlayerObjectRef
|
||||
local function set_inv_page(page, player)
|
||||
local playername = player:get_player_name()
|
||||
local inv = minetest.get_inventory({type="detached", name="creative_"..playername})
|
||||
local inv = minetest.get_inventory({ type = "detached", name = "creative_" .. playername })
|
||||
inv:set_size("main", 0)
|
||||
local creative_list = {}
|
||||
if inventory_lists[page] then -- Standard filter
|
||||
@ -160,9 +198,11 @@ local function set_inv_page(page, player)
|
||||
inv:set_list("main", creative_list)
|
||||
end
|
||||
|
||||
|
||||
---@param player mt.PlayerObjectRef
|
||||
local function init(player)
|
||||
local playername = player:get_player_name()
|
||||
minetest.create_detached_inventory("creative_"..playername, {
|
||||
minetest.create_detached_inventory("creative_" .. playername, {
|
||||
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||
if minetest.is_creative_enabled(playername) then
|
||||
return count
|
||||
@ -197,24 +237,45 @@ local trash = minetest.create_detached_inventory("trash", {
|
||||
inv:set_stack(listname, index, "")
|
||||
end,
|
||||
})
|
||||
|
||||
trash:set_size("main", 1)
|
||||
|
||||
local noffset = {} -- numeric tab offset
|
||||
local offset = {} -- string offset:
|
||||
local boffset = {} --
|
||||
local hoch = {}
|
||||
local filtername = {}
|
||||
--local bg = {}
|
||||
------------------------------
|
||||
-- Formspec Precalculations --
|
||||
------------------------------
|
||||
|
||||
local noffset_x_start = -0.24
|
||||
-- Numeric position of tab background image, indexed by tab name
|
||||
---@type table<string, {[0]: number, [1]: number}>
|
||||
local noffset = {}
|
||||
|
||||
-- String position of tab button background image, indexed by tab name
|
||||
---@type table<string, string>
|
||||
local offset = {}
|
||||
|
||||
-- String position of tab button, indexed by tab name
|
||||
---@type table<string, string>
|
||||
local boffset = {}
|
||||
|
||||
-- Used to determine the tab button background image
|
||||
---@type table<string, ""|"_down">
|
||||
local button_bg_postfix = {}
|
||||
|
||||
-- Tab caption/tooltip translated string, indexed by tab name
|
||||
---@type table<string, string>
|
||||
local filtername = {}
|
||||
|
||||
local noffset_x_start = 0.2
|
||||
local noffset_x = noffset_x_start
|
||||
local noffset_y = -0.25
|
||||
local noffset_y = -1.34
|
||||
|
||||
---@param id string
|
||||
---@param right? boolean
|
||||
local function next_noffset(id, right)
|
||||
if right then
|
||||
noffset[id] = { 8.94, noffset_y }
|
||||
noffset[id] = { 11.3, noffset_y }
|
||||
else
|
||||
noffset[id] = { noffset_x, noffset_y }
|
||||
noffset_x = noffset_x + 1.25
|
||||
noffset_x = noffset_x + 1.6
|
||||
end
|
||||
end
|
||||
|
||||
@ -228,7 +289,7 @@ next_noffset("misc")
|
||||
next_noffset("nix", true)
|
||||
|
||||
noffset_x = noffset_x_start
|
||||
noffset_y = 8.12
|
||||
noffset_y = 8.64
|
||||
|
||||
-- Lower row
|
||||
next_noffset("food")
|
||||
@ -238,25 +299,25 @@ next_noffset("mobs")
|
||||
next_noffset("matr")
|
||||
next_noffset("inv", true)
|
||||
|
||||
for k,v in pairs(noffset) do
|
||||
for k, v in pairs(noffset) do
|
||||
offset[k] = tostring(v[1]) .. "," .. tostring(v[2])
|
||||
boffset[k] = tostring(v[1]+0.19) .. "," .. tostring(v[2]+0.25)
|
||||
boffset[k] = tostring(v[1] + 0.24) .. "," .. tostring(v[2] + 0.25)
|
||||
end
|
||||
|
||||
hoch["blocks"] = ""
|
||||
hoch["deco"] = ""
|
||||
hoch["redstone"] = ""
|
||||
hoch["rail"] = ""
|
||||
hoch["brew"] = ""
|
||||
hoch["misc"] = ""
|
||||
hoch["nix"] = ""
|
||||
hoch["default"] = ""
|
||||
hoch["food"] = "_down"
|
||||
hoch["tools"] = "_down"
|
||||
hoch["combat"] = "_down"
|
||||
hoch["mobs"] = "_down"
|
||||
hoch["matr"] = "_down"
|
||||
hoch["inv"] = "_down"
|
||||
button_bg_postfix["blocks"] = ""
|
||||
button_bg_postfix["deco"] = ""
|
||||
button_bg_postfix["redstone"] = ""
|
||||
button_bg_postfix["rail"] = ""
|
||||
button_bg_postfix["brew"] = ""
|
||||
button_bg_postfix["misc"] = ""
|
||||
button_bg_postfix["nix"] = ""
|
||||
button_bg_postfix["default"] = ""
|
||||
button_bg_postfix["food"] = "_down"
|
||||
button_bg_postfix["tools"] = "_down"
|
||||
button_bg_postfix["combat"] = "_down"
|
||||
button_bg_postfix["mobs"] = "_down"
|
||||
button_bg_postfix["matr"] = "_down"
|
||||
button_bg_postfix["inv"] = "_down"
|
||||
|
||||
filtername["blocks"] = S("Building Blocks")
|
||||
filtername["deco"] = S("Decoration Blocks")
|
||||
@ -291,121 +352,9 @@ filtername["inv"] = S("Survival Inventory")
|
||||
bg["default"] = dark_bg
|
||||
end]]
|
||||
|
||||
local function get_stack_size(player)
|
||||
return player:get_meta():get_int("mcl_inventory:switch_stack")
|
||||
end
|
||||
|
||||
local function set_stack_size(player, n)
|
||||
player:get_meta():set_int("mcl_inventory:switch_stack", n)
|
||||
end
|
||||
|
||||
minetest.register_on_joinplayer(function (player)
|
||||
if get_stack_size(player) == 0 then
|
||||
set_stack_size(player, 64)
|
||||
end
|
||||
end)
|
||||
|
||||
function mcl_inventory.set_creative_formspec(player)
|
||||
local playername = player:get_player_name()
|
||||
if not players[playername] then return end
|
||||
|
||||
local start_i = players[playername].start_i
|
||||
local pagenum = start_i / (9*5) + 1
|
||||
local name = players[playername].page
|
||||
local inv_size = players[playername].inv_size
|
||||
local filter = players[playername].filter
|
||||
local pagemax = math.max(1, math.floor((inv_size-1) / (9*5) + 1))
|
||||
local main_list
|
||||
local listrings = "listring[detached:creative_"..playername..";main]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[detached:trash;main]"
|
||||
|
||||
local inv_bg = "crafting_inventory_creative.png"
|
||||
if name == "inv" then
|
||||
inv_bg = "crafting_inventory_creative_survival.png"
|
||||
|
||||
-- Background images for armor slots (hide if occupied)
|
||||
local armor_slot_imgs = ""
|
||||
local inv = player:get_inventory()
|
||||
if inv:get_stack("armor", 2):is_empty() then
|
||||
armor_slot_imgs = armor_slot_imgs .. "image[2.5,1.3;1,1;mcl_inventory_empty_armor_slot_helmet.png]"
|
||||
end
|
||||
if inv:get_stack("armor", 3):is_empty() then
|
||||
armor_slot_imgs = armor_slot_imgs .. "image[2.5,2.75;1,1;mcl_inventory_empty_armor_slot_chestplate.png]"
|
||||
end
|
||||
if inv:get_stack("armor", 4):is_empty() then
|
||||
armor_slot_imgs = armor_slot_imgs .. "image[5.5,1.3;1,1;mcl_inventory_empty_armor_slot_leggings.png]"
|
||||
end
|
||||
if inv:get_stack("armor", 5):is_empty() then
|
||||
armor_slot_imgs = armor_slot_imgs .. "image[5.5,2.75;1,1;mcl_inventory_empty_armor_slot_boots.png]"
|
||||
end
|
||||
|
||||
if inv:get_stack("offhand", 1):is_empty() then
|
||||
armor_slot_imgs = armor_slot_imgs .. "image[1.5,2.025;1,1;mcl_inventory_empty_armor_slot_shield.png]"
|
||||
end
|
||||
|
||||
local stack_size = get_stack_size(player)
|
||||
|
||||
-- Survival inventory slots
|
||||
main_list = "list[current_player;main;0,3.75;9,3;9]" ..
|
||||
mcl_formspec.get_itemslot_bg(0, 3.75, 9, 3) ..
|
||||
|
||||
-- Armor
|
||||
"list[current_player;armor;2.5,1.3;1,1;1]" ..
|
||||
"list[current_player;armor;2.5,2.75;1,1;2]" ..
|
||||
"list[current_player;armor;5.5,1.3;1,1;3]" ..
|
||||
"list[current_player;armor;5.5,2.75;1,1;4]" ..
|
||||
mcl_formspec.get_itemslot_bg(2.5, 1.3, 1, 1) ..
|
||||
mcl_formspec.get_itemslot_bg(2.5, 2.75, 1, 1) ..
|
||||
mcl_formspec.get_itemslot_bg(5.5, 1.3, 1, 1) ..
|
||||
mcl_formspec.get_itemslot_bg(5.5, 2.75, 1, 1) ..
|
||||
"list[current_player;offhand;1.5,2.025;1,1]" ..
|
||||
mcl_formspec.get_itemslot_bg(1.5, 2.025, 1, 1) ..
|
||||
armor_slot_imgs ..
|
||||
|
||||
-- Player preview
|
||||
mcl_player.get_player_formspec_model(player, 3.9, 1.4, 1.2333, 2.4666, "") ..
|
||||
|
||||
-- Crafting guide button
|
||||
"image_button[9,1;1,1;craftguide_book.png;__mcl_craftguide;]" ..
|
||||
"tooltip[__mcl_craftguide;"..F(S("Recipe book")) .. "]" ..
|
||||
|
||||
-- Help button
|
||||
"image_button[9,2;1,1;doc_button_icon_lores.png;__mcl_doc;]" ..
|
||||
"tooltip[__mcl_doc;" .. F(S("Help")) .. "]" ..
|
||||
|
||||
-- Achievements button
|
||||
"image_button[9,3;1,1;mcl_achievements_button.png;__mcl_achievements;]" ..
|
||||
--"style_type[image_button;border=;bgimg=;bgimg_pressed=]" ..
|
||||
"tooltip[__mcl_achievements;"..F(S("Advancements")) .. "]" ..
|
||||
|
||||
-- Switch stack size button
|
||||
"image_button[9,4;1,1;default_apple.png;__switch_stack;]" ..
|
||||
"label[9.4,4.4;" .. F(C("#FFFFFF", stack_size ~= 1 and stack_size or "")) .. "]" ..
|
||||
"tooltip[__switch_stack;" .. F(S("Switch stack size")) .. "]"
|
||||
|
||||
-- Skins button
|
||||
if minetest.global_exists("mcl_skins") then
|
||||
main_list = main_list ..
|
||||
"image_button[9,5;1,1;mcl_skins_button.png;__mcl_skins;]" ..
|
||||
"tooltip[__mcl_skins;"..F(S("Select player skin")) .. "]"
|
||||
end
|
||||
|
||||
-- For shortcuts
|
||||
listrings = listrings ..
|
||||
"listring[detached:"..playername.."_armor;armor]"..
|
||||
"listring[current_player;main]"
|
||||
else
|
||||
-- Creative inventory slots
|
||||
main_list = "list[detached:creative_"..playername..";main;0,1.75;9,5;"..tostring(start_i).."]"..
|
||||
mcl_formspec.get_itemslot_bg(0,1.75,9,5)..
|
||||
-- Page buttons
|
||||
"label[9.0,5.5;"..F(S("@1/@2", pagenum, pagemax)).."]"..
|
||||
"image_button[9.0,6.0;0.7,0.7;crafting_creative_prev.png;creative_prev;]"..
|
||||
"image_button[9.5,6.0;0.7,0.7;crafting_creative_next.png;creative_next;]"
|
||||
end
|
||||
|
||||
local tab_icon = {
|
||||
-- Item name representing a tab, indexed by tab name
|
||||
---@type table<string, string>
|
||||
local tab_icon = {
|
||||
blocks = "mcl_core:brick_block",
|
||||
deco = "mcl_flowers:peony",
|
||||
redstone = "mesecons:redstone",
|
||||
@ -419,69 +368,236 @@ function mcl_inventory.set_creative_formspec(player)
|
||||
brew = "mcl_potions:dragon_breath",
|
||||
matr = "mcl_core:stick",
|
||||
inv = "mcl_chests:chest",
|
||||
}
|
||||
}
|
||||
|
||||
-- Get the player configured stack size when taking items from creative inventory
|
||||
---@param player mt.PlayerObjectRef
|
||||
---@return integer
|
||||
local function get_stack_size(player)
|
||||
return player:get_meta():get_int("mcl_inventory:switch_stack")
|
||||
end
|
||||
|
||||
-- Set the player configured stack size when taking items from creative inventory
|
||||
---@param player mt.PlayerObjectRef
|
||||
---@param n integer
|
||||
local function set_stack_size(player, n)
|
||||
player:get_meta():set_int("mcl_inventory:switch_stack", n)
|
||||
end
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
if get_stack_size(player) == 0 then
|
||||
set_stack_size(player, 64)
|
||||
end
|
||||
end)
|
||||
|
||||
---@param player mt.PlayerObjectRef
|
||||
function mcl_inventory.set_creative_formspec(player)
|
||||
local playername = player:get_player_name()
|
||||
if not players[playername] then return end
|
||||
|
||||
local start_i = players[playername].start_i
|
||||
local pagenum = start_i / (9 * 5) + 1
|
||||
local page = players[playername].page
|
||||
local inv_size = players[playername].inv_size
|
||||
local filter = players[playername].filter
|
||||
|
||||
if not inv_size then
|
||||
if page == "nix" then
|
||||
local inv = minetest.get_inventory({ type = "detached", name = "creative_" .. playername })
|
||||
inv_size = inv:get_size("main")
|
||||
elseif page and page ~= "inv" then
|
||||
inv_size = #(inventory_lists[page])
|
||||
else
|
||||
inv_size = 0
|
||||
end
|
||||
end
|
||||
local pagemax = math.max(1, math.floor((inv_size - 1) / (9 * 5) + 1))
|
||||
local name = "nix"
|
||||
local main_list
|
||||
local listrings = table.concat({
|
||||
"listring[detached:creative_" .. playername .. ";main]",
|
||||
"listring[current_player;main]",
|
||||
"listring[detached:trash;main]",
|
||||
})
|
||||
|
||||
if page then
|
||||
name = page
|
||||
if players[playername] then
|
||||
players[playername].page = page
|
||||
end
|
||||
end
|
||||
|
||||
if name == "inv" then
|
||||
-- Background images for armor slots (hide if occupied)
|
||||
local armor_slot_imgs = ""
|
||||
local inv = player:get_inventory()
|
||||
if inv:get_stack("armor", 2):is_empty() then
|
||||
armor_slot_imgs = armor_slot_imgs .. "image[3.5,0.375;1,1;mcl_inventory_empty_armor_slot_helmet.png]"
|
||||
end
|
||||
if inv:get_stack("armor", 3):is_empty() then
|
||||
armor_slot_imgs = armor_slot_imgs .. "image[3.5,2.125;1,1;mcl_inventory_empty_armor_slot_chestplate.png]"
|
||||
end
|
||||
if inv:get_stack("armor", 4):is_empty() then
|
||||
armor_slot_imgs = armor_slot_imgs .. "image[7.25,0.375;1,1;mcl_inventory_empty_armor_slot_leggings.png]"
|
||||
end
|
||||
if inv:get_stack("armor", 5):is_empty() then
|
||||
armor_slot_imgs = armor_slot_imgs .. "image[7.25,2.125;1,1;mcl_inventory_empty_armor_slot_boots.png]"
|
||||
end
|
||||
|
||||
if inv:get_stack("offhand", 1):is_empty() then
|
||||
armor_slot_imgs = armor_slot_imgs .. "image[2.25,1.25;1,1;mcl_inventory_empty_armor_slot_shield.png]"
|
||||
end
|
||||
|
||||
local stack_size = get_stack_size(player)
|
||||
|
||||
-- Survival inventory slots
|
||||
main_list = table.concat({
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 3.375, 9, 3),
|
||||
"list[current_player;main;0.375,3.375;9,3;9]",
|
||||
|
||||
-- Armor
|
||||
mcl_formspec.get_itemslot_bg_v4(3.5, 0.375, 1, 1),
|
||||
mcl_formspec.get_itemslot_bg_v4(3.5, 2.125, 1, 1),
|
||||
mcl_formspec.get_itemslot_bg_v4(7.25, 0.375, 1, 1),
|
||||
mcl_formspec.get_itemslot_bg_v4(7.25, 2.125, 1, 1),
|
||||
"list[current_player;armor;3.5,0.375;1,1;1]",
|
||||
"list[current_player;armor;3.5,2.125;1,1;2]",
|
||||
"list[current_player;armor;7.25,0.375;1,1;3]",
|
||||
"list[current_player;armor;7.25,2.125;1,1;4]",
|
||||
|
||||
-- Offhand
|
||||
mcl_formspec.get_itemslot_bg_v4(2.25, 1.25, 1, 1),
|
||||
"list[current_player;offhand;2.25,1.25;1,1]",
|
||||
|
||||
armor_slot_imgs,
|
||||
|
||||
-- Player preview
|
||||
"image[4.75,0.33;2.25,2.83;mcl_inventory_background9.png;2]",
|
||||
mcl_player.get_player_formspec_model(player, 4.75, 0.45, 2.25, 2.75, ""),
|
||||
|
||||
-- Crafting guide button
|
||||
"image_button[11.575,0.825;1.1,1.1;craftguide_book.png;__mcl_craftguide;]",
|
||||
"tooltip[__mcl_craftguide;" .. F(S("Recipe book")) .. "]",
|
||||
|
||||
-- Help button
|
||||
"image_button[11.575,2.075;1.1,1.1;doc_button_icon_lores.png;__mcl_doc;]",
|
||||
"tooltip[__mcl_doc;" .. F(S("Help")) .. "]",
|
||||
|
||||
-- Advancements button
|
||||
"image_button[11.575,3.325;1.1,1.1;mcl_achievements_button.png;__mcl_achievements;]",
|
||||
--"style_type[image_button;border=;bgimg=;bgimg_pressed=]",
|
||||
"tooltip[__mcl_achievements;" .. F(S("Advancements")) .. "]",
|
||||
|
||||
-- Switch stack size button
|
||||
"image_button[11.575,4.575;1.1,1.1;default_apple.png;__switch_stack;]",
|
||||
"label[12.275,5.35;" .. F(C("#FFFFFF", tostring(stack_size ~= 1 and stack_size or ""))) .. "]",
|
||||
"tooltip[__switch_stack;" .. F(S("Switch stack size")) .. "]",
|
||||
|
||||
-- Skins button
|
||||
"image_button[11.575,5.825;1.1,1.1;mcl_skins_button.png;__mcl_skins;]",
|
||||
"tooltip[__mcl_skins;" .. F(S("Select player skin")) .. "]",
|
||||
})
|
||||
|
||||
-- For shortcuts
|
||||
listrings = listrings ..
|
||||
"listring[detached:" .. playername .. "_armor;armor]" ..
|
||||
"listring[current_player;main]"
|
||||
else
|
||||
|
||||
--local nb_lines = math.ceil(inv_size / 9)
|
||||
-- Creative inventory slots
|
||||
main_list = table.concat({
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 0.875, 9, 5),
|
||||
|
||||
-- Basic code to replace buttons by scrollbar
|
||||
-- Require Minetest 5.8
|
||||
--
|
||||
--"scroll_container[0.375,0.875;11.575,6;scroll;vertical;1.25]",
|
||||
--"list[detached:creative_" .. playername .. ";main;0,0;9," .. nb_lines .. ";]",
|
||||
--"scroll_container_end[]",
|
||||
--"scrollbaroptions[min=0;max=" .. math.max(nb_lines - 5, 0) .. ";smallstep=1;largesteps=1;arrows=hide]",
|
||||
--"scrollbar[11.75,0.825;0.75,6.1;vertical;scroll;0]",
|
||||
|
||||
"list[detached:creative_" .. playername .. ";main;0.375,0.875;9,5;" .. tostring(start_i) .. "]",
|
||||
|
||||
-- Page buttons
|
||||
"label[11.65,4.33;" .. F(S("@1 / @2", pagenum, pagemax)) .. "]",
|
||||
"image_button[11.575,4.58;1.1,1.1;crafting_creative_prev.png^[transformR270;creative_prev;]",
|
||||
"image_button[11.575,5.83;1.1,1.1;crafting_creative_next.png^[transformR270;creative_next;]",
|
||||
})
|
||||
end
|
||||
|
||||
---@param current_tab string
|
||||
---@param this_tab string
|
||||
---@return string
|
||||
local function tab(current_tab, this_tab)
|
||||
local bg_img
|
||||
if current_tab == this_tab then
|
||||
bg_img = "crafting_creative_active"..hoch[this_tab]..".png"
|
||||
bg_img = "crafting_creative_active" .. button_bg_postfix[this_tab] .. ".png"
|
||||
else
|
||||
bg_img = "crafting_creative_inactive"..hoch[this_tab]..".png"
|
||||
bg_img = "crafting_creative_inactive" .. button_bg_postfix[this_tab] .. ".png"
|
||||
end
|
||||
return
|
||||
"style["..this_tab..";border=false;bgimg=;bgimg_pressed=]"..
|
||||
"item_image_button[" .. boffset[this_tab] ..";1,1;"..tab_icon[this_tab]..";"..this_tab..";]"..
|
||||
"image[" .. offset[this_tab] .. ";1.5,1.44;" .. bg_img .. "]"
|
||||
return table.concat({
|
||||
"style[" .. this_tab .. ";border=false;bgimg=;bgimg_pressed=;noclip=true]",
|
||||
"image[" .. offset[this_tab] .. ";1.5,1.44;" .. bg_img .. "]",
|
||||
"item_image_button[" .. boffset[this_tab] .. ";1,1;" .. tab_icon[this_tab] .. ";" .. this_tab .. ";]",
|
||||
"tooltip[blocks;" .. F(filtername[this_tab]) .. "]"
|
||||
})
|
||||
end
|
||||
|
||||
local caption = ""
|
||||
if name ~= "inv" and filtername[name] then
|
||||
caption = "label[0,1.2;"..F(minetest.colorize("#313131", filtername[name])).."]"
|
||||
caption = "label[0.375,0.375;" .. F(C(mcl_formspec.label_color, filtername[name])) .. "]"
|
||||
end
|
||||
|
||||
local formspec = "size[10,9.3]"..
|
||||
"no_prepend[]"..
|
||||
mcl_vars.gui_nonbg..mcl_vars.gui_bg_color..
|
||||
"background[-0.19,-0.25;10.5,9.87;"..inv_bg.."]"..
|
||||
"label[-5,-5;"..name.."]"..
|
||||
tab(name, "blocks") ..
|
||||
"tooltip[blocks;"..F(filtername["blocks"]).."]"..
|
||||
tab(name, "deco") ..
|
||||
"tooltip[deco;"..F(filtername["deco"]).."]"..
|
||||
tab(name, "redstone") ..
|
||||
"tooltip[redstone;"..F(filtername["redstone"]).."]"..
|
||||
tab(name, "rail") ..
|
||||
"tooltip[rail;"..F(filtername["rail"]).."]"..
|
||||
tab(name, "misc") ..
|
||||
"tooltip[misc;"..F(filtername["misc"]).."]"..
|
||||
tab(name, "nix") ..
|
||||
"tooltip[nix;"..F(filtername["nix"]).."]"..
|
||||
caption..
|
||||
"list[current_player;main;0,7;9,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(0,7,9,1)..
|
||||
main_list..
|
||||
tab(name, "food") ..
|
||||
"tooltip[food;"..F(filtername["food"]).."]"..
|
||||
tab(name, "tools") ..
|
||||
"tooltip[tools;"..F(filtername["tools"]).."]"..
|
||||
tab(name, "combat") ..
|
||||
"tooltip[combat;"..F(filtername["combat"]).."]"..
|
||||
tab(name, "mobs") ..
|
||||
"tooltip[mobs;"..F(filtername["mobs"]).."]"..
|
||||
tab(name, "brew") ..
|
||||
"tooltip[brew;"..F(filtername["brew"]).."]"..
|
||||
tab(name, "matr") ..
|
||||
"tooltip[matr;"..F(filtername["matr"]).."]"..
|
||||
tab(name, "inv") ..
|
||||
"tooltip[inv;"..F(filtername["inv"]).."]"..
|
||||
"list[detached:trash;main;9,7;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(9,7,1,1)..
|
||||
"image[9,7;1,1;crafting_creative_trash.png]"..
|
||||
listrings
|
||||
local formspec = table.concat({
|
||||
"formspec_version[6]",
|
||||
"size[13,8.75]",
|
||||
|
||||
"style_type[image;noclip=true]",
|
||||
|
||||
-- Hotbar
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 7.375, 9, 1),
|
||||
"list[current_player;main;0.375,7.375;9,1;]",
|
||||
|
||||
-- Trash
|
||||
mcl_formspec.get_itemslot_bg_v4(11.625, 7.375, 1, 1, nil, "crafting_creative_trash.png"),
|
||||
"list[detached:trash;main;11.625,7.375;1,1;]",
|
||||
|
||||
main_list,
|
||||
|
||||
caption,
|
||||
|
||||
listrings,
|
||||
|
||||
tab(name, "blocks"),
|
||||
tab(name, "deco"),
|
||||
tab(name, "redstone"),
|
||||
tab(name, "rail"),
|
||||
tab(name, "misc"),
|
||||
tab(name, "nix"),
|
||||
|
||||
tab(name, "food"),
|
||||
tab(name, "tools"),
|
||||
tab(name, "combat"),
|
||||
tab(name, "mobs"),
|
||||
tab(name, "brew"),
|
||||
tab(name, "matr"),
|
||||
tab(name, "inv"),
|
||||
})
|
||||
|
||||
if name == "nix" then
|
||||
formspec = formspec .. "field[5.3,1.34;4,0.75;search;;"..minetest.formspec_escape(filter).."]"
|
||||
formspec = formspec .. "field_close_on_enter[search;false]"
|
||||
if filter == nil then
|
||||
filter = ""
|
||||
end
|
||||
if pagenum then formspec = formspec .. "p"..tostring(pagenum) end
|
||||
|
||||
formspec = formspec .. table.concat({
|
||||
"field[5.325,0.15;6.1,0.6;search;;" .. minetest.formspec_escape(filter) .. "]",
|
||||
"field_close_on_enter[search;false]",
|
||||
"set_focus[search;true]",
|
||||
})
|
||||
end
|
||||
if pagenum then formspec = formspec .. "p" .. tostring(pagenum) end
|
||||
player:set_inventory_formspec(formspec)
|
||||
end
|
||||
|
||||
@ -500,50 +616,50 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
|
||||
if fields.blocks then
|
||||
if players[name].page == "blocks" then return end
|
||||
set_inv_page("blocks",player)
|
||||
set_inv_page("blocks", player)
|
||||
page = "blocks"
|
||||
elseif fields.deco then
|
||||
if players[name].page == "deco" then return end
|
||||
set_inv_page("deco",player)
|
||||
set_inv_page("deco", player)
|
||||
page = "deco"
|
||||
elseif fields.redstone then
|
||||
if players[name].page == "redstone" then return end
|
||||
set_inv_page("redstone",player)
|
||||
set_inv_page("redstone", player)
|
||||
page = "redstone"
|
||||
elseif fields.rail then
|
||||
if players[name].page == "rail" then return end
|
||||
set_inv_page("rail",player)
|
||||
set_inv_page("rail", player)
|
||||
page = "rail"
|
||||
elseif fields.misc then
|
||||
if players[name].page == "misc" then return end
|
||||
set_inv_page("misc",player)
|
||||
set_inv_page("misc", player)
|
||||
page = "misc"
|
||||
elseif fields.nix then
|
||||
set_inv_page("all",player)
|
||||
set_inv_page("all", player)
|
||||
page = "nix"
|
||||
elseif fields.food then
|
||||
if players[name].page == "food" then return end
|
||||
set_inv_page("food",player)
|
||||
set_inv_page("food", player)
|
||||
page = "food"
|
||||
elseif fields.tools then
|
||||
if players[name].page == "tools" then return end
|
||||
set_inv_page("tools",player)
|
||||
set_inv_page("tools", player)
|
||||
page = "tools"
|
||||
elseif fields.combat then
|
||||
if players[name].page == "combat" then return end
|
||||
set_inv_page("combat",player)
|
||||
set_inv_page("combat", player)
|
||||
page = "combat"
|
||||
elseif fields.mobs then
|
||||
if players[name].page == "mobs" then return end
|
||||
set_inv_page("mobs",player)
|
||||
set_inv_page("mobs", player)
|
||||
page = "mobs"
|
||||
elseif fields.brew then
|
||||
if players[name].page == "brew" then return end
|
||||
set_inv_page("brew",player)
|
||||
set_inv_page("brew", player)
|
||||
page = "brew"
|
||||
elseif fields.matr then
|
||||
if players[name].page == "matr" then return end
|
||||
set_inv_page("matr",player)
|
||||
set_inv_page("matr", player)
|
||||
page = "matr"
|
||||
elseif fields.inv then
|
||||
if players[name].page == "inv" then return end
|
||||
@ -552,7 +668,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
set_inv_page("all", player)
|
||||
page = "nix"
|
||||
elseif fields.search and not fields.creative_next and not fields.creative_prev then
|
||||
set_inv_search(string.lower(fields.search),player)
|
||||
set_inv_search(string.lower(fields.search), player)
|
||||
page = "nix"
|
||||
elseif fields.__switch_stack then
|
||||
local switch = 1
|
||||
@ -570,20 +686,20 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
|
||||
local start_i = players[name].start_i
|
||||
if fields.creative_prev then
|
||||
start_i = start_i - 9*5
|
||||
start_i = start_i - 9 * 5
|
||||
elseif fields.creative_next then
|
||||
start_i = start_i + 9*5
|
||||
start_i = start_i + 9 * 5
|
||||
else
|
||||
-- Reset scroll bar if not scrolled
|
||||
start_i = 0
|
||||
end
|
||||
if start_i < 0 then
|
||||
start_i = start_i + 9*5
|
||||
start_i = start_i + 9 * 5
|
||||
end
|
||||
|
||||
local inv_size
|
||||
if page == "nix" then
|
||||
local inv = minetest.get_inventory({type="detached", name="creative_"..name})
|
||||
local inv = minetest.get_inventory({ type = "detached", name = "creative_" .. name })
|
||||
inv_size = inv:get_size("main")
|
||||
elseif page and page ~= "inv" then
|
||||
inv_size = #(inventory_lists[page])
|
||||
@ -593,7 +709,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
players[name].inv_size = inv_size
|
||||
|
||||
if start_i >= inv_size then
|
||||
start_i = start_i - 9*5
|
||||
start_i = start_i - 9 * 5
|
||||
end
|
||||
if start_i < 0 or start_i >= inv_size then
|
||||
start_i = 0
|
||||
@ -609,11 +725,34 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
mcl_inventory.set_creative_formspec(player)
|
||||
end)
|
||||
|
||||
|
||||
minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack)
|
||||
return placer and placer:is_player() and minetest.is_creative_enabled(placer:get_player_name())
|
||||
end)
|
||||
|
||||
if minetest.is_creative_enabled("") then
|
||||
minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack)
|
||||
-- Place infinite nodes, except for shulker boxes
|
||||
local group = minetest.get_item_group(itemstack:get_name(), "shulker_box")
|
||||
return group == 0 or group == nil
|
||||
end)
|
||||
|
||||
function minetest.handle_node_drops(pos, drops, digger)
|
||||
if not digger or not digger:is_player() then
|
||||
for _, item in ipairs(drops) do
|
||||
minetest.add_item(pos, item)
|
||||
end
|
||||
end
|
||||
local inv = digger:get_inventory()
|
||||
if inv then
|
||||
for _, item in ipairs(drops) do
|
||||
if not inv:contains_item("main", item, true) then
|
||||
inv:add_item("main", item)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
-- Initialize variables and inventory
|
||||
local name = player:get_player_name()
|
||||
@ -629,7 +768,8 @@ minetest.register_on_joinplayer(function(player)
|
||||
end)
|
||||
|
||||
minetest.register_on_player_inventory_action(function(player, action, inventory, inventory_info)
|
||||
if minetest.is_creative_enabled(player:get_player_name()) and get_stack_size(player) == 64 and action == "put" and inventory_info.listname == "main" then
|
||||
if minetest.is_creative_enabled(player:get_player_name()) and get_stack_size(player) == 64 and action == "put" and
|
||||
inventory_info.listname == "main" then
|
||||
local stack = inventory_info.stack
|
||||
stack:set_count(stack:get_stack_max())
|
||||
player:get_inventory():set_stack("main", inventory_info.index, stack)
|
||||
|
@ -1,13 +1,17 @@
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
local F = minetest.formspec_escape
|
||||
|
||||
mcl_inventory = {}
|
||||
|
||||
dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/creative.lua")
|
||||
dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/survival.lua")
|
||||
|
||||
--local mod_player = minetest.get_modpath("mcl_player")
|
||||
--local mod_craftguide = minetest.get_modpath("mcl_craftguide")
|
||||
|
||||
-- Returns a single itemstack in the given inventory to the main inventory, or drop it when there's no space left
|
||||
function return_item(itemstack, dropper, pos, inv)
|
||||
---Returns a single itemstack in the given inventory to the main inventory, or drop it when there's no space left.
|
||||
---@param itemstack mt.ItemStack
|
||||
---@param dropper mt.ObjectRef
|
||||
---@param pos mt.Vector
|
||||
---@param inv mt.InvRef
|
||||
local function return_item(itemstack, dropper, pos, inv)
|
||||
if dropper:is_player() then
|
||||
-- Return to main inventory
|
||||
if inv:room_for_item("main", itemstack) then
|
||||
@ -15,14 +19,14 @@ function return_item(itemstack, dropper, pos, inv)
|
||||
else
|
||||
-- Drop item on the ground
|
||||
local v = dropper:get_look_dir()
|
||||
local p = {x=pos.x, y=pos.y+1.2, z=pos.z}
|
||||
p.x = p.x+(math.random(1,3)*0.2)
|
||||
p.z = p.z+(math.random(1,3)*0.2)
|
||||
local p = vector.offset(pos, 0, 1.2, 0)
|
||||
p.x = p.x + (math.random(1, 3) * 0.2)
|
||||
p.z = p.z + (math.random(1, 3) * 0.2)
|
||||
local obj = minetest.add_item(p, itemstack)
|
||||
if obj then
|
||||
v.x = v.x*4
|
||||
v.y = v.y*4 + 2
|
||||
v.z = v.z*4
|
||||
v.x = v.x * 4
|
||||
v.y = v.y * 4 + 2
|
||||
v.z = v.z * 4
|
||||
obj:set_velocity(v)
|
||||
obj:get_luaentity()._insta_collect = false
|
||||
end
|
||||
@ -34,111 +38,53 @@ function return_item(itemstack, dropper, pos, inv)
|
||||
return itemstack
|
||||
end
|
||||
|
||||
-- Return items in the given inventory list (name) to the main inventory, or drop them if there is no space left
|
||||
function return_fields(player, name)
|
||||
---Return items in the given inventory list (name) to the main inventory, or drop them if there is no space left.
|
||||
---@param player mt.PlayerObjectRef
|
||||
---@param name string
|
||||
local function return_fields(player, name)
|
||||
local inv = player:get_inventory()
|
||||
|
||||
local list = inv:get_list(name)
|
||||
if not list then return end
|
||||
for i,stack in ipairs(list) do
|
||||
for i, stack in ipairs(list) do
|
||||
return_item(stack, player, player:get_pos(), inv)
|
||||
stack:clear()
|
||||
inv:set_stack(name, i, stack)
|
||||
end
|
||||
end
|
||||
|
||||
local function set_inventory(player)
|
||||
---@param player mt.PlayerObjectRef
|
||||
---@param armor_change_only? boolean
|
||||
local function set_inventory(player, armor_change_only)
|
||||
if minetest.is_creative_enabled(player:get_player_name()) then
|
||||
mcl_inventory.set_creative_formspec(player)
|
||||
if armor_change_only then
|
||||
-- Stay on survival inventory plage if only the armor has been changed
|
||||
mcl_inventory.set_creative_formspec(player, 0, 0, nil, nil, "inv")
|
||||
else
|
||||
mcl_inventory.set_creative_formspec(player, 0, 1)
|
||||
end
|
||||
return
|
||||
end
|
||||
local inv = player:get_inventory()
|
||||
inv:set_width("craft", 2)
|
||||
inv:set_size("craft", 4)
|
||||
|
||||
local armor_slots = {"helmet", "chestplate", "leggings", "boots"}
|
||||
local armor_slot_imgs = ""
|
||||
for a=1,4 do
|
||||
if inv:get_stack("armor", a+1):is_empty() then
|
||||
armor_slot_imgs = armor_slot_imgs .. "image[0,"..(a-1)..";1,1;mcl_inventory_empty_armor_slot_"..armor_slots[a]..".png]"
|
||||
end
|
||||
end
|
||||
|
||||
if inv:get_stack("offhand", 1):is_empty() then
|
||||
armor_slot_imgs = armor_slot_imgs .. "image[3,2;1,1;mcl_inventory_empty_armor_slot_shield.png]"
|
||||
end
|
||||
|
||||
local form = "size[9,8.75]" ..
|
||||
"background[-0.19,-0.25;9.41,9.49;crafting_formspec_bg.png]" ..
|
||||
mcl_player.get_player_formspec_model(player, 1.0, 0.0, 2.25, 4.5, "") ..
|
||||
|
||||
-- Armor
|
||||
"list[current_player;armor;0,0;1,1;1]" ..
|
||||
"list[current_player;armor;0,1;1,1;2]" ..
|
||||
"list[current_player;armor;0,2;1,1;3]" ..
|
||||
"list[current_player;armor;0,3;1,1;4]" ..
|
||||
mcl_formspec.get_itemslot_bg(0,0,1,1) ..
|
||||
mcl_formspec.get_itemslot_bg(0,1,1,1) ..
|
||||
mcl_formspec.get_itemslot_bg(0,2,1,1) ..
|
||||
mcl_formspec.get_itemslot_bg(0,3,1,1) ..
|
||||
"list[current_player;offhand;3,2;1,1]" ..
|
||||
mcl_formspec.get_itemslot_bg(3,2,1,1) ..
|
||||
armor_slot_imgs ..
|
||||
|
||||
-- Craft and inventory
|
||||
"label[0,4;"..F(minetest.colorize("#313131", S("Inventory"))) .. "]" ..
|
||||
"list[current_player;main;0,4.5;9,3;9]" ..
|
||||
"list[current_player;main;0,7.74;9,1;]" ..
|
||||
"label[4,0.5;"..F(minetest.colorize("#313131", S("Crafting"))) .. "]" ..
|
||||
"list[current_player;craft;4,1;2,2]" ..
|
||||
"list[current_player;craftpreview;7,1.5;1,1;]" ..
|
||||
mcl_formspec.get_itemslot_bg(0, 4.5, 9, 3) ..
|
||||
mcl_formspec.get_itemslot_bg(0, 7.74, 9, 1) ..
|
||||
mcl_formspec.get_itemslot_bg(4, 1,2, 2) ..
|
||||
mcl_formspec.get_itemslot_bg(7, 1.5, 1, 1) ..
|
||||
|
||||
-- Crafting guide button
|
||||
"image_button[4.5,3;1,1;craftguide_book.png;__mcl_craftguide;]" ..
|
||||
"tooltip[__mcl_craftguide;"..F(S("Recipe book")) .. "]" ..
|
||||
|
||||
-- Help button
|
||||
"image_button[8,3;1,1;doc_button_icon_lores.png;__mcl_doc;]" ..
|
||||
"tooltip[__mcl_doc;" .. F(S("Help")) .. "]"
|
||||
|
||||
-- Skins button
|
||||
if minetest.global_exists("mcl_skins") then
|
||||
form = form ..
|
||||
"image_button[3,3;1,1;mcl_skins_button.png;__mcl_skins;]" ..
|
||||
"tooltip[__mcl_skins;" .. F(S("Select player skin")) .. "]"
|
||||
end
|
||||
|
||||
form = form ..
|
||||
-- Achievements button
|
||||
"image_button[7,3;1,1;mcl_achievements_button.png;__mcl_achievements;]" ..
|
||||
"tooltip[__mcl_achievements;" .. F(S("Advancements")) .. "]" ..
|
||||
|
||||
-- For shortcuts
|
||||
"listring[current_player;main]" ..
|
||||
"listring[current_player;armor]" ..
|
||||
"listring[current_player;main]" ..
|
||||
"listring[current_player;craft]" ..
|
||||
"listring[current_player;main]"
|
||||
|
||||
player:set_inventory_formspec(form)
|
||||
player:set_inventory_formspec(mcl_inventory.build_survival_formspec(player))
|
||||
end
|
||||
|
||||
-- Drop items in craft grid and reset inventory on closing
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if fields.quit then
|
||||
return_fields(player,"craft")
|
||||
return_fields(player,"enchanting_lapis")
|
||||
return_fields(player,"enchanting_item")
|
||||
return_fields(player, "craft")
|
||||
return_fields(player, "enchanting_lapis")
|
||||
return_fields(player, "enchanting_item")
|
||||
if not minetest.is_creative_enabled(player:get_player_name()) and (formname == "" or formname == "main") then
|
||||
set_inventory(player)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
mcl_inventory.update_inventory_formspec = set_inventory
|
||||
|
||||
function mcl_inventory.update_inventory_formspec(player)
|
||||
set_inventory(player)
|
||||
end
|
||||
|
||||
-- Drop crafting grid items on leaving
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
@ -150,6 +96,7 @@ end)
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
--init inventory
|
||||
local inv = player:get_inventory()
|
||||
|
||||
inv:set_width("main", 9)
|
||||
inv:set_size("main", 36)
|
||||
inv:set_size("offhand", 1)
|
||||
@ -174,73 +121,18 @@ minetest.register_on_joinplayer(function(player)
|
||||
return_fields(player, "enchanting_lapis")
|
||||
end)
|
||||
|
||||
dofile(minetest.get_modpath(minetest.get_current_modname()).."/creative.lua")
|
||||
---@param player mt.PlayerObjectRef
|
||||
function mcl_inventory.update_inventory(player)
|
||||
local player_gamemode = mcl_gamemode.get_gamemode(player)
|
||||
if player_gamemode == "creative" then
|
||||
mcl_inventory.set_creative_formspec(player)
|
||||
elseif player_gamemode == "survival" then
|
||||
player:set_inventory_formspec(mcl_inventory.build_survival_formspec(player))
|
||||
end
|
||||
end
|
||||
|
||||
mcl_gamemode.register_on_gamemode_change(function(player, old_gamemode, new_gamemode)
|
||||
set_inventory(player)
|
||||
end)
|
||||
|
||||
mcl_player.register_on_visual_change(mcl_inventory.update_inventory_formspec)
|
||||
|
||||
local mt_is_creative_enabled = minetest.is_creative_enabled
|
||||
|
||||
function minetest.is_creative_enabled(name)
|
||||
if mt_is_creative_enabled(name) then return true end
|
||||
if not name then return false end
|
||||
local p = minetest.get_player_by_name(name)
|
||||
if p then
|
||||
return p:get_meta():get_string("gamemode") == "creative"
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function in_table(n,h)
|
||||
for k,v in pairs(h) do
|
||||
if v == n then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local gamemodes = {
|
||||
"survival",
|
||||
"creative"
|
||||
}
|
||||
|
||||
function mcl_inventory.player_set_gamemode(p,g)
|
||||
local m = p:get_meta()
|
||||
m:set_string("gamemode",g)
|
||||
if g == "survival" then
|
||||
mcl_experience.setup_hud(p)
|
||||
mcl_experience.update(p)
|
||||
elseif g == "creative" then
|
||||
mcl_experience.remove_hud(p)
|
||||
end
|
||||
mcl_meshhand.update_player(p)
|
||||
set_inventory(p)
|
||||
end
|
||||
|
||||
minetest.register_chatcommand("gamemode",{
|
||||
params = S("[<gamemode>] [<player>]"),
|
||||
description = S("Change gamemode (survival/creative) for yourself or player"),
|
||||
privs = { server = true },
|
||||
func = function(n,param)
|
||||
-- Full input validation ( just for @erlehmann <3 )
|
||||
local p
|
||||
local args = param:split(" ")
|
||||
if args[2] ~= nil then
|
||||
p = minetest.get_player_by_name(args[2])
|
||||
n = args[2]
|
||||
else
|
||||
p = minetest.get_player_by_name(n)
|
||||
end
|
||||
if not p then
|
||||
return false, S("Player not online")
|
||||
end
|
||||
if args[1] ~= nil and not in_table(args[1],gamemodes) then
|
||||
return false, S("Gamemode " .. args[1] .. " does not exist.")
|
||||
elseif args[1] ~= nil then
|
||||
mcl_inventory.player_set_gamemode(p,args[1])
|
||||
end
|
||||
|
||||
--Result message - show effective game mode
|
||||
local gm = p:get_meta():get_string("gamemode")
|
||||
if gm == "" then gm = gamemodes[1] end
|
||||
return true, S("Gamemode for player ")..n..S(": "..gm)
|
||||
end
|
||||
})
|
||||
|
@ -1,5 +1,5 @@
|
||||
name = mcl_inventory
|
||||
author = BlockMen
|
||||
description = Adds the player inventory and creative inventory.
|
||||
depends = mcl_init, mcl_formspec, mcl_enchanting, mcl_player
|
||||
optional_depends = mcl_armor, mcl_brewing, mcl_potions, mcl_enchanting, mcl_craftguide
|
||||
depends = mcl_init, mcl_formspec, mcl_enchanting, mcl_gamemode
|
||||
optional_depends = mcl_armor, mcl_brewing, mcl_potions, mcl_enchanting, mcl_craftguide, mcl_player
|
||||
|
224
mods/HUD/mcl_inventory/survival.lua
Normal file
@ -0,0 +1,224 @@
|
||||
---@diagnostic disable need-check-nil
|
||||
|
||||
local table = table
|
||||
local ipairs = ipairs
|
||||
|
||||
local S = minetest.get_translator("mcl_inventory")
|
||||
local F = minetest.formspec_escape
|
||||
|
||||
---@type {id: string, description: string, item_icon: string, build: (fun(player: ObjectRef): string), handle: fun(player: ObjectRef, fields: table), access: (fun(player): boolean), show_inventory: boolean}[]
|
||||
mcl_inventory.registered_survival_inventory_tabs = {}
|
||||
|
||||
---@param def {id: string, description: string, item_icon: string, build: (fun(player: ObjectRef): string), handle: fun(player: ObjectRef, fields: table), access: (fun(player): boolean), show_inventory: boolean}
|
||||
function mcl_inventory.register_survival_inventory_tab(def)
|
||||
if #mcl_inventory.registered_survival_inventory_tabs == 7 then
|
||||
error("Too much tabs registered!")
|
||||
end
|
||||
|
||||
assert(def.id)
|
||||
assert(def.description)
|
||||
assert(def.item_icon)
|
||||
assert(def.build)
|
||||
assert(def.handle)
|
||||
|
||||
for _, d in ipairs(mcl_inventory.registered_survival_inventory_tabs) do
|
||||
assert(d.id ~= def.id, "Another tab exists with the same name!")
|
||||
end
|
||||
|
||||
if not def.access then
|
||||
function def.access(player)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
if def.show_inventory == nil then
|
||||
def.show_inventory = true
|
||||
end
|
||||
|
||||
table.insert(mcl_inventory.registered_survival_inventory_tabs, def)
|
||||
end
|
||||
|
||||
local player_current_tab = {}
|
||||
|
||||
minetest.register_on_joinplayer(function(player, last_login)
|
||||
player_current_tab[player] = "main"
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player, timed_out)
|
||||
player_current_tab[player] = nil
|
||||
end)
|
||||
|
||||
---@param player ObjectRef
|
||||
---@param content string
|
||||
---@param inventory boolean
|
||||
---@param tabname string
|
||||
local function build_page(player, content, inventory, tabname)
|
||||
local tab_buttons = "style_type[image;noclip=true]"
|
||||
|
||||
if #mcl_inventory.registered_survival_inventory_tabs ~= 1 then
|
||||
for i, d in ipairs(mcl_inventory.registered_survival_inventory_tabs) do
|
||||
local btn_name = "tab_" .. d.id
|
||||
|
||||
tab_buttons = tab_buttons .. table.concat({
|
||||
"style[" .. btn_name .. ";border=false;bgimg=;bgimg_pressed=;noclip=true]",
|
||||
"image[" ..
|
||||
(0.2 + (i - 1) * 1.6) ..
|
||||
",-1.34;1.5,1.44;" .. (tabname == d.id and "crafting_creative_active.png" or "crafting_creative_inactive.png") ..
|
||||
"]",
|
||||
"item_image_button[" .. (0.44 + (i - 1) * 1.6) .. ",-1.1;1,1;" .. d.item_icon .. ";" .. btn_name .. ";]",
|
||||
"tooltip[" .. btn_name .. ";" .. F(d.description) .. "]"
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
return table.concat({
|
||||
"formspec_version[6]",
|
||||
"size[11.75,10.9]",
|
||||
|
||||
inventory and table.concat({
|
||||
--Main inventory
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 5.575, 9, 3),
|
||||
"list[current_player;main;0.375,5.575;9,3;9]",
|
||||
|
||||
--Hotbar
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 9.525, 9, 1),
|
||||
"list[current_player;main;0.375,9.525;9,1;]"
|
||||
}) or "",
|
||||
|
||||
content,
|
||||
tab_buttons,
|
||||
})
|
||||
end
|
||||
|
||||
local main_page_static = table.concat({
|
||||
--Armor slots
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 0.375, 1, 4),
|
||||
"list[current_player;armor;0.375,0.375;1,1;1]",
|
||||
"list[current_player;armor;0.375,1.625;1,1;2]",
|
||||
"list[current_player;armor;0.375,2.875;1,1;3]",
|
||||
"list[current_player;armor;0.375,4.125;1,1;4]",
|
||||
|
||||
--Player model background
|
||||
"image[1.57,0.343;3.62,4.85;mcl_inventory_background9.png;2]",
|
||||
|
||||
--Offhand
|
||||
mcl_formspec.get_itemslot_bg_v4(5.375, 4.125, 1, 1),
|
||||
"list[current_player;offhand;5.375,4.125;1,1]",
|
||||
|
||||
--Craft grid
|
||||
"label[6.61,0.5;" .. F(minetest.colorize(mcl_formspec.label_color, S("Crafting"))) .. "]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(6.625, 0.875, 2, 2),
|
||||
"list[current_player;craft;6.625,0.875;2,2]",
|
||||
|
||||
"image[9.125,1.5;1,1;crafting_formspec_arrow.png]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(10.375, 1.5, 1, 1),
|
||||
"list[current_player;craftpreview;10.375,1.5;1,1;]",
|
||||
|
||||
--Crafting guide button
|
||||
"image_button[6.575,4.075;1.1,1.1;craftguide_book.png;__mcl_craftguide;]",
|
||||
"tooltip[__mcl_craftguide;" .. F(S("Recipe book")) .. "]",
|
||||
|
||||
--Help button
|
||||
"image_button[7.825,4.075;1.1,1.1;doc_button_icon_lores.png;__mcl_doc;]",
|
||||
"tooltip[__mcl_doc;" .. F(S("Help")) .. "]",
|
||||
|
||||
--Skins button
|
||||
"image_button[9.075,4.075;1.1,1.1;mcl_skins_button.png;__mcl_skins;]",
|
||||
"tooltip[__mcl_skins;" .. F(S("Select player skin")) .. "]",
|
||||
|
||||
--Achievements button
|
||||
"image_button[10.325,4.075;1.1,1.1;mcl_achievements_button.png;__mcl_achievements;]",
|
||||
"tooltip[__mcl_achievements;" .. F(S("Achievements")) .. "]",
|
||||
|
||||
--Listring
|
||||
"listring[current_player;main]",
|
||||
"listring[current_player;armor]",
|
||||
"listring[current_player;main]",
|
||||
"listring[current_player;craft]",
|
||||
"listring[current_player;main]",
|
||||
})
|
||||
|
||||
mcl_inventory.register_survival_inventory_tab({
|
||||
id = "main",
|
||||
description = "Main Inventory",
|
||||
item_icon = "mcl_crafting_table:crafting_table",
|
||||
show_inventory = true,
|
||||
build = function(player)
|
||||
local inv = player:get_inventory()
|
||||
|
||||
local armor_slots = { "helmet", "chestplate", "leggings", "boots" }
|
||||
local armor_slot_imgs = ""
|
||||
|
||||
for a = 1, 4 do
|
||||
if inv:get_stack("armor", a + 1):is_empty() then
|
||||
armor_slot_imgs = armor_slot_imgs ..
|
||||
"image[0.375," .. (0.375 + (a - 1) * 1.25) .. ";1,1;mcl_inventory_empty_armor_slot_" .. armor_slots[a] .. ".png]"
|
||||
end
|
||||
end
|
||||
|
||||
if inv:get_stack("offhand", 1):is_empty() then
|
||||
armor_slot_imgs = armor_slot_imgs .. "image[5.375,4.125;1,1;mcl_inventory_empty_armor_slot_shield.png]"
|
||||
end
|
||||
return main_page_static .. armor_slot_imgs .. mcl_player.get_player_formspec_model(player, 1.57, 0.4, 3.62, 4.85, "")
|
||||
end,
|
||||
handle = function() end,
|
||||
})
|
||||
|
||||
--[[
|
||||
mcl_inventory.register_survival_inventory_tab({
|
||||
id = "test",
|
||||
description = "Test",
|
||||
item_icon = "mcl_core:stone",
|
||||
show_inventory = true,
|
||||
build = function(player)
|
||||
return "label[1,1;Hello hello]button[2,2;2,2;Hello;hey]"
|
||||
end,
|
||||
handle = function(player, fields)
|
||||
print(dump(fields))
|
||||
end,
|
||||
})]]
|
||||
|
||||
---@param player ObjectRef
|
||||
function mcl_inventory.build_survival_formspec(player)
|
||||
local inv = player:get_inventory()
|
||||
|
||||
inv:set_width("craft", 2)
|
||||
inv:set_size("craft", 4)
|
||||
|
||||
local tab = player_current_tab[player]
|
||||
|
||||
local tab_def = nil
|
||||
|
||||
for _, d in ipairs(mcl_inventory.registered_survival_inventory_tabs) do
|
||||
if tab == d.id then
|
||||
tab_def = d
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local form = build_page(player, tab_def.build(player), tab_def.show_inventory, tab)
|
||||
|
||||
return form
|
||||
end
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if formname == "" and #mcl_inventory.registered_survival_inventory_tabs ~= 1 and
|
||||
mcl_gamemode.get_gamemode(player) == "survival" then
|
||||
for _, d in ipairs(mcl_inventory.registered_survival_inventory_tabs) do
|
||||
if fields["tab_" .. d.id] and d.access(player) then
|
||||
player_current_tab[player] = d.id
|
||||
mcl_inventory.update_inventory(player)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
for _, d in ipairs(mcl_inventory.registered_survival_inventory_tabs) do
|
||||
if player_current_tab[player] == d.id and d.access(player) then
|
||||
d.handle(player, fields)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
@ -8,23 +8,36 @@ All node definitions share a lot of code, so this is the reason why there
|
||||
are so many weird tables below.
|
||||
]]
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
local C = minetest.colorize
|
||||
local F = minetest.formspec_escape
|
||||
|
||||
-- For after_place_node
|
||||
local dispenser_formspec = table.concat({
|
||||
"formspec_version[4]",
|
||||
"size[11.75,10.425]",
|
||||
|
||||
"label[4.125,0.375;" .. F(C(mcl_formspec.label_color, S("Dispenser"))) .. "]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(4.125, 0.75, 3, 3),
|
||||
"list[context;main;4.125,0.75;3,3;]",
|
||||
|
||||
"label[0.375,4.7;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3),
|
||||
"list[current_player;main;0.375,5.1;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1),
|
||||
"list[current_player;main;0.375,9.05;9,1;]",
|
||||
|
||||
"listring[context;main]",
|
||||
"listring[current_player;main]",
|
||||
})
|
||||
|
||||
---For after_place_node
|
||||
---@param pos Vector
|
||||
local function setup_dispenser(pos)
|
||||
-- Set formspec and inventory
|
||||
local form = "size[9,8.75]"..
|
||||
"label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]"..
|
||||
"list[current_player;main;0,4.5;9,3;9]"..
|
||||
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
|
||||
"list[current_player;main;0,7.74;9,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(0,7.74,9,1)..
|
||||
"label[3,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Dispenser"))).."]"..
|
||||
"list[context;main;3,0.5;3,3;]"..
|
||||
mcl_formspec.get_itemslot_bg(3,0.5,3,3)..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("formspec", form)
|
||||
meta:set_string("formspec", dispenser_formspec)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size("main", 9)
|
||||
end
|
||||
@ -38,9 +51,9 @@ local function orientate_dispenser(pos, placer)
|
||||
|
||||
local node = minetest.get_node(pos)
|
||||
if pitch > 55 then
|
||||
minetest.swap_node(pos, {name="mcl_dispensers:dispenser_up", param2 = node.param2})
|
||||
minetest.swap_node(pos, { name = "mcl_dispensers:dispenser_up", param2 = node.param2 })
|
||||
elseif pitch < -55 then
|
||||
minetest.swap_node(pos, {name="mcl_dispensers:dispenser_down", param2 = node.param2})
|
||||
minetest.swap_node(pos, { name = "mcl_dispensers:dispenser_down", param2 = node.param2 })
|
||||
end
|
||||
end
|
||||
|
||||
@ -85,11 +98,10 @@ local dispenserdef = {
|
||||
local meta2 = meta:to_table()
|
||||
meta:from_table(oldmetadata)
|
||||
local inv = meta:get_inventory()
|
||||
for i=1, inv:get_size("main") do
|
||||
for i = 1, inv:get_size("main") do
|
||||
local stack = inv:get_stack("main", i)
|
||||
if not stack:is_empty() then
|
||||
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5}
|
||||
minetest.add_item(p, stack)
|
||||
minetest.add_item(vector.offset(pos, math.random(0, 10) / 10 - 0.5, 0, math.random(0, 10) / 10 - 0.5), stack)
|
||||
end
|
||||
end
|
||||
meta:from_table(meta2)
|
||||
@ -107,19 +119,19 @@ local dispenserdef = {
|
||||
dropdir = vector.multiply(minetest.facedir_to_dir(node.param2), -1)
|
||||
droppos = vector.add(pos, dropdir)
|
||||
elseif node.name == "mcl_dispensers:dispenser_up" then
|
||||
dropdir = {x=0, y=1, z=0}
|
||||
droppos = {x=pos.x, y=pos.y+1, z=pos.z}
|
||||
dropdir = vector.new(0, 1, 0)
|
||||
droppos = vector.offset(pos, 0, 1, 0)
|
||||
elseif node.name == "mcl_dispensers:dispenser_down" then
|
||||
dropdir = {x=0, y=-1, z=0}
|
||||
droppos = {x=pos.x, y=pos.y-1, z=pos.z}
|
||||
dropdir = vector.new(0, -1, 0)
|
||||
droppos = vector.offset(pos, 0, -1, 0)
|
||||
end
|
||||
local dropnode = minetest.get_node(droppos)
|
||||
local dropnodedef = minetest.registered_nodes[dropnode.name]
|
||||
local stacks = {}
|
||||
for i=1,inv:get_size("main") do
|
||||
for i = 1, inv:get_size("main") do
|
||||
local stack = inv:get_stack("main", i)
|
||||
if not stack:is_empty() then
|
||||
table.insert(stacks, {stack = stack, stackpos = i})
|
||||
table.insert(stacks, { stack = stack, stackpos = i })
|
||||
end
|
||||
end
|
||||
if #stacks >= 1 then
|
||||
@ -143,9 +155,10 @@ local dispenserdef = {
|
||||
|
||||
-- Armor, mob heads and pumpkins
|
||||
if igroups.armor then
|
||||
local droppos_below = {x = droppos.x, y = droppos.y - 1, z = droppos.z}
|
||||
local droppos_below = vector.offset(droppos, 0, -1, 0)
|
||||
|
||||
for _, objs in ipairs({minetest.get_objects_inside_radius(droppos, 1), minetest.get_objects_inside_radius(droppos_below, 1)}) do
|
||||
for _, objs in ipairs({ minetest.get_objects_inside_radius(droppos, 1),
|
||||
minetest.get_objects_inside_radius(droppos_below, 1) }) do
|
||||
for _, obj in ipairs(objs) do
|
||||
stack = mcl_armor.equip(stack, obj)
|
||||
if stack:is_empty() then
|
||||
@ -161,7 +174,7 @@ local dispenserdef = {
|
||||
if not stack:is_empty() then
|
||||
if igroups.head or iname == "mcl_farming:pumpkin_face" then
|
||||
if dropnodedef.buildable_to then
|
||||
minetest.set_node(droppos, {name = iname, param2 = node.param2})
|
||||
minetest.set_node(droppos, { name = iname, param2 = node.param2 })
|
||||
stack:take_item()
|
||||
end
|
||||
end
|
||||
@ -263,7 +276,7 @@ local dispenserdef = {
|
||||
local item_entity = minetest.add_item(droppos, dropitem)
|
||||
local drop_vel = vector.subtract(droppos, pos)
|
||||
local speed = 3
|
||||
item_entity:set_velocity(vector.multiply(drop_vel,speed))
|
||||
item_entity:set_velocity(vector.multiply(drop_vel, speed))
|
||||
end
|
||||
else
|
||||
stack:take_item()
|
||||
@ -280,7 +293,7 @@ local dispenserdef = {
|
||||
local item_entity = minetest.add_item(droppos, dropitem)
|
||||
local drop_vel = vector.subtract(droppos, pos)
|
||||
local speed = 3
|
||||
item_entity:set_velocity(vector.multiply(drop_vel,speed))
|
||||
item_entity:set_velocity(vector.multiply(drop_vel, speed))
|
||||
stack:take_item()
|
||||
inv:set_stack("main", stack_id, stack)
|
||||
end
|
||||
@ -299,27 +312,28 @@ local dispenserdef = {
|
||||
|
||||
local horizontal_def = table.copy(dispenserdef)
|
||||
horizontal_def.description = S("Dispenser")
|
||||
horizontal_def._tt_help = S("9 inventory slots").."\n"..S("Launches item when powered by redstone power")
|
||||
horizontal_def._tt_help = S("9 inventory slots") .. "\n" .. S("Launches item when powered by redstone power")
|
||||
horizontal_def._doc_items_longdesc = S("A dispenser is a block which acts as a redstone component which, when powered with redstone power, dispenses an item. It has a container with 9 inventory slots.")
|
||||
horizontal_def._doc_items_usagehelp = S("Place the dispenser in one of 6 possible directions. The “hole” is where items will fly out of the dispenser. Use the dispenser to access its inventory. Insert the items you wish to dispense. Supply the dispenser with redstone energy once to dispense a random item.").."\n\n"..
|
||||
horizontal_def._doc_items_usagehelp = S("Place the dispenser in one of 6 possible directions. The “hole” is where items will fly out of the dispenser. Use the dispenser to access its inventory. Insert the items you wish to dispense. Supply the dispenser with redstone energy once to dispense a random item.")
|
||||
.. "\n\n" ..
|
||||
|
||||
S("The dispenser will do different things, depending on the dispensed item:").."\n\n"..
|
||||
S("The dispenser will do different things, depending on the dispensed item:") .. "\n\n" ..
|
||||
|
||||
S("• Arrows: Are launched").."\n"..
|
||||
S("• Eggs and snowballs: Are thrown").."\n"..
|
||||
S("• Fire charges: Are fired in a straight line").."\n"..
|
||||
S("• Armor: Will be equipped to players and armor stands").."\n"..
|
||||
S("• Boats: Are placed on water or are dropped").."\n"..
|
||||
S("• Minecart: Are placed on rails or are dropped").."\n"..
|
||||
S("• Bone meal: Is applied on the block it is facing").."\n"..
|
||||
S("• Empty buckets: Are used to collect a liquid source").."\n"..
|
||||
S("• Filled buckets: Are used to place a liquid source").."\n"..
|
||||
S("• Heads, pumpkins: Equipped to players and armor stands, or placed as a block").."\n"..
|
||||
S("• Shulker boxes: Are placed as a block").."\n"..
|
||||
S("• TNT: Is placed and ignited").."\n"..
|
||||
S("• Flint and steel: Is used to ignite a fire in air and to ignite TNT").."\n"..
|
||||
S("• Spawn eggs: Will summon the mob they contain").."\n"..
|
||||
S("• Other items: Are simply dropped")
|
||||
S("• Arrows: Are launched") .. "\n" ..
|
||||
S("• Eggs and snowballs: Are thrown") .. "\n" ..
|
||||
S("• Fire charges: Are fired in a straight line") .. "\n" ..
|
||||
S("• Armor: Will be equipped to players and armor stands") .. "\n" ..
|
||||
S("• Boats: Are placed on water or are dropped") .. "\n" ..
|
||||
S("• Minecart: Are placed on rails or are dropped") .. "\n" ..
|
||||
S("• Bone meal: Is applied on the block it is facing") .. "\n" ..
|
||||
S("• Empty buckets: Are used to collect a liquid source") .. "\n" ..
|
||||
S("• Filled buckets: Are used to place a liquid source") .. "\n" ..
|
||||
S("• Heads, pumpkins: Equipped to players and armor stands, or placed as a block") .. "\n" ..
|
||||
S("• Shulker boxes: Are placed as a block") .. "\n" ..
|
||||
S("• TNT: Is placed and ignited") .. "\n" ..
|
||||
S("• Flint and steel: Is used to ignite a fire in air and to ignite TNT") .. "\n" ..
|
||||
S("• Spawn eggs: Will summon the mob they contain") .. "\n" ..
|
||||
S("• Other items: Are simply dropped")
|
||||
|
||||
function horizontal_def.after_place_node(pos, placer, itemstack, pointed_thing)
|
||||
setup_dispenser(pos)
|
||||
@ -332,7 +346,7 @@ horizontal_def.tiles = {
|
||||
"default_furnace_side.png", "mcl_dispensers_dispenser_front_horizontal.png"
|
||||
}
|
||||
horizontal_def.paramtype2 = "facedir"
|
||||
horizontal_def.groups = {pickaxey=1, container=2, material_stone=1}
|
||||
horizontal_def.groups = { pickaxey = 1, container = 2, material_stone = 1 }
|
||||
|
||||
minetest.register_node("mcl_dispensers:dispenser", horizontal_def)
|
||||
|
||||
@ -345,7 +359,7 @@ down_def.tiles = {
|
||||
"default_furnace_side.png", "default_furnace_side.png",
|
||||
"default_furnace_side.png", "default_furnace_side.png"
|
||||
}
|
||||
down_def.groups = {pickaxey=1, container=2,not_in_creative_inventory=1, material_stone=1}
|
||||
down_def.groups = { pickaxey = 1, container = 2, not_in_creative_inventory = 1, material_stone = 1 }
|
||||
down_def._doc_items_create_entry = false
|
||||
down_def.drop = "mcl_dispensers:dispenser"
|
||||
minetest.register_node("mcl_dispensers:dispenser_down", down_def)
|
||||
@ -365,9 +379,9 @@ minetest.register_node("mcl_dispensers:dispenser_up", up_def)
|
||||
minetest.register_craft({
|
||||
output = "mcl_dispensers:dispenser",
|
||||
recipe = {
|
||||
{"mcl_core:cobble", "mcl_core:cobble", "mcl_core:cobble",},
|
||||
{"mcl_core:cobble", "mcl_bows:bow", "mcl_core:cobble",},
|
||||
{"mcl_core:cobble", "mesecons:redstone", "mcl_core:cobble",},
|
||||
{ "mcl_core:cobble", "mcl_core:cobble", "mcl_core:cobble", },
|
||||
{ "mcl_core:cobble", "mcl_bows:bow", "mcl_core:cobble", },
|
||||
{ "mcl_core:cobble", "mesecons:redstone", "mcl_core:cobble", },
|
||||
}
|
||||
})
|
||||
|
||||
@ -384,6 +398,6 @@ minetest.register_lbm({
|
||||
nodenames = { "mcl_dispensers:dispenser", "mcl_dispensers:dispenser_down", "mcl_dispensers:dispenser_up" },
|
||||
action = function(pos, node)
|
||||
setup_dispenser(pos)
|
||||
minetest.log("action", "[mcl_dispenser] Node formspec updated at "..minetest.pos_to_string(pos))
|
||||
minetest.log("action", "[mcl_dispenser] Node formspec updated at " .. minetest.pos_to_string(pos))
|
||||
end,
|
||||
})
|
||||
|
@ -9,23 +9,36 @@ are so many weird tables below.
|
||||
]]
|
||||
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
local C = minetest.colorize
|
||||
local F = minetest.formspec_escape
|
||||
|
||||
-- For after_place_node
|
||||
local dropper_formspec = table.concat({
|
||||
"formspec_version[4]",
|
||||
"size[11.75,10.425]",
|
||||
|
||||
"label[4.125,0.375;" .. F(C(mcl_formspec.label_color, S("Dropper"))) .. "]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(4.125, 0.75, 3, 3),
|
||||
"list[context;main;4.125,0.75;3,3;]",
|
||||
|
||||
"label[0.375,4.7;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3),
|
||||
"list[current_player;main;0.375,5.1;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1),
|
||||
"list[current_player;main;0.375,9.05;9,1;]",
|
||||
|
||||
"listring[context;main]",
|
||||
"listring[current_player;main]",
|
||||
})
|
||||
|
||||
---For after_place_node
|
||||
---@param pos Vector
|
||||
local function setup_dropper(pos)
|
||||
-- Set formspec and inventory
|
||||
local form = "size[9,8.75]"..
|
||||
"label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]"..
|
||||
"list[current_player;main;0,4.5;9,3;9]"..
|
||||
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
|
||||
"list[current_player;main;0,7.74;9,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(0,7.74,9,1)..
|
||||
"label[3,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Dropper"))).."]"..
|
||||
"list[context;main;3,0.5;3,3;]"..
|
||||
mcl_formspec.get_itemslot_bg(3,0.5,3,3)..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("formspec", form)
|
||||
meta:set_string("formspec", dropper_formspec)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size("main", 9)
|
||||
end
|
||||
@ -38,9 +51,9 @@ local function orientate_dropper(pos, placer)
|
||||
local pitch = placer:get_look_vertical() * (180 / math.pi)
|
||||
|
||||
if pitch > 55 then
|
||||
minetest.swap_node(pos, {name="mcl_droppers:dropper_up"})
|
||||
minetest.swap_node(pos, { name = "mcl_droppers:dropper_up" })
|
||||
elseif pitch < -55 then
|
||||
minetest.swap_node(pos, {name="mcl_droppers:dropper_down"})
|
||||
minetest.swap_node(pos, { name = "mcl_droppers:dropper_down" })
|
||||
end
|
||||
end
|
||||
|
||||
@ -58,11 +71,10 @@ local dropperdef = {
|
||||
local meta2 = meta:to_table()
|
||||
meta:from_table(oldmetadata)
|
||||
local inv = meta:get_inventory()
|
||||
for i=1, inv:get_size("main") do
|
||||
for i = 1, inv:get_size("main") do
|
||||
local stack = inv:get_stack("main", i)
|
||||
if not stack:is_empty() then
|
||||
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5}
|
||||
minetest.add_item(p, stack)
|
||||
minetest.add_item(vector.offset(pos, math.random(0, 10) / 10 - 0.5, 0, math.random(0, 10) / 10 - 0.5), stack)
|
||||
end
|
||||
end
|
||||
meta:from_table(meta2)
|
||||
@ -96,7 +108,7 @@ local dropperdef = {
|
||||
end,
|
||||
_mcl_blast_resistance = 3.5,
|
||||
_mcl_hardness = 3.5,
|
||||
mesecons = {effector = {
|
||||
mesecons = { effector = {
|
||||
-- Drop random item when triggered
|
||||
action_on = function(pos, node)
|
||||
if not pos then return end
|
||||
@ -106,9 +118,9 @@ local dropperdef = {
|
||||
if node.name == "mcl_droppers:dropper" then
|
||||
droppos = vector.subtract(pos, minetest.facedir_to_dir(node.param2))
|
||||
elseif node.name == "mcl_droppers:dropper_up" then
|
||||
droppos = {x=pos.x, y=pos.y+1, z=pos.z}
|
||||
droppos = vector.offset(pos, 0, 1, 0)
|
||||
elseif node.name == "mcl_droppers:dropper_down" then
|
||||
droppos = {x=pos.x, y=pos.y-1, z=pos.z}
|
||||
droppos = vector.offset(pos, 0, -1, 0)
|
||||
end
|
||||
local dropnode = minetest.get_node(droppos)
|
||||
-- Do not drop into solid nodes, unless they are containers
|
||||
@ -117,10 +129,10 @@ local dropperdef = {
|
||||
return
|
||||
end
|
||||
local stacks = {}
|
||||
for i=1,inv:get_size("main") do
|
||||
for i = 1, inv:get_size("main") do
|
||||
local stack = inv:get_stack("main", i)
|
||||
if not stack:is_empty() then
|
||||
table.insert(stacks, {stack = stack, stackpos = i})
|
||||
table.insert(stacks, { stack = stack, stackpos = i })
|
||||
end
|
||||
end
|
||||
if #stacks >= 1 then
|
||||
@ -136,22 +148,22 @@ local dropperdef = {
|
||||
if not dropped and not dropnodedef.groups.container then
|
||||
-- Drop item normally
|
||||
local pos_variation = 100
|
||||
droppos = {
|
||||
x = droppos.x + math.random(-pos_variation, pos_variation) / 1000,
|
||||
y = droppos.y + math.random(-pos_variation, pos_variation) / 1000,
|
||||
z = droppos.z + math.random(-pos_variation, pos_variation) / 1000,
|
||||
}
|
||||
droppos = vector.offset(droppos,
|
||||
math.random(-pos_variation, pos_variation) / 1000,
|
||||
math.random(-pos_variation, pos_variation) / 1000,
|
||||
math.random(-pos_variation, pos_variation) / 1000
|
||||
)
|
||||
local item_entity = minetest.add_item(droppos, dropitem)
|
||||
local drop_vel = vector.subtract(droppos, pos)
|
||||
local speed = 3
|
||||
item_entity:set_velocity(vector.multiply(drop_vel,speed))
|
||||
item_entity:set_velocity(vector.multiply(drop_vel, speed))
|
||||
stack:take_item()
|
||||
inv:set_stack("main", stack_id, stack)
|
||||
end
|
||||
end
|
||||
end,
|
||||
rules = mesecon.rules.alldirs,
|
||||
}},
|
||||
} },
|
||||
on_rotate = on_rotate,
|
||||
}
|
||||
|
||||
@ -159,20 +171,21 @@ local dropperdef = {
|
||||
|
||||
local horizontal_def = table.copy(dropperdef)
|
||||
horizontal_def.description = S("Dropper")
|
||||
horizontal_def._tt_help = S("9 inventory slots").."\n"..S("Drops item when powered by redstone power")
|
||||
horizontal_def._tt_help = S("9 inventory slots") .. "\n" .. S("Drops item when powered by redstone power")
|
||||
horizontal_def._doc_items_longdesc = S("A dropper is a redstone component and a container with 9 inventory slots which, when supplied with redstone power, drops an item or puts it into a container in front of it.")
|
||||
horizontal_def._doc_items_usagehelp = S("Droppers can be placed in 6 possible directions, items will be dropped out of the hole. Use the dropper to access its inventory. Supply it with redstone energy once to make the dropper drop or transfer a random item.")
|
||||
function horizontal_def.after_place_node(pos, placer, itemstack, pointed_thing)
|
||||
setup_dropper(pos)
|
||||
orientate_dropper(pos, placer)
|
||||
end
|
||||
|
||||
horizontal_def.tiles = {
|
||||
"default_furnace_top.png", "default_furnace_bottom.png",
|
||||
"default_furnace_side.png", "default_furnace_side.png",
|
||||
"default_furnace_side.png", "mcl_droppers_dropper_front_horizontal.png"
|
||||
}
|
||||
horizontal_def.paramtype2 = "facedir"
|
||||
horizontal_def.groups = {pickaxey=1, container=2, material_stone=1}
|
||||
horizontal_def.groups = { pickaxey = 1, container = 2, material_stone = 1 }
|
||||
|
||||
minetest.register_node("mcl_droppers:dropper", horizontal_def)
|
||||
|
||||
@ -185,7 +198,7 @@ down_def.tiles = {
|
||||
"default_furnace_side.png", "default_furnace_side.png",
|
||||
"default_furnace_side.png", "default_furnace_side.png"
|
||||
}
|
||||
down_def.groups = {pickaxey=1, container=2,not_in_creative_inventory=1, material_stone=1}
|
||||
down_def.groups = { pickaxey = 1, container = 2, not_in_creative_inventory = 1, material_stone = 1 }
|
||||
down_def._doc_items_create_entry = false
|
||||
down_def.drop = "mcl_droppers:dropper"
|
||||
minetest.register_node("mcl_droppers:dropper_down", down_def)
|
||||
@ -207,9 +220,9 @@ minetest.register_node("mcl_droppers:dropper_up", up_def)
|
||||
minetest.register_craft({
|
||||
output = "mcl_droppers:dropper",
|
||||
recipe = {
|
||||
{"mcl_core:cobble", "mcl_core:cobble", "mcl_core:cobble",},
|
||||
{"mcl_core:cobble", "", "mcl_core:cobble",},
|
||||
{"mcl_core:cobble", "mesecons:redstone", "mcl_core:cobble",},
|
||||
{ "mcl_core:cobble", "mcl_core:cobble", "mcl_core:cobble", },
|
||||
{ "mcl_core:cobble", "", "mcl_core:cobble", },
|
||||
{ "mcl_core:cobble", "mesecons:redstone", "mcl_core:cobble", },
|
||||
}
|
||||
})
|
||||
|
||||
@ -226,6 +239,6 @@ minetest.register_lbm({
|
||||
nodenames = { "mcl_droppers:dropper", "mcl_droppers:dropper_down", "mcl_droppers:dropper_up" },
|
||||
action = function(pos, node)
|
||||
setup_dropper(pos)
|
||||
minetest.log("action", "[mcl_droppers] Node formspec updated at "..minetest.pos_to_string(pos))
|
||||
minetest.log("action", "[mcl_droppers] Node formspec updated at " .. minetest.pos_to_string(pos))
|
||||
end,
|
||||
})
|
||||
|
@ -1,4 +1,6 @@
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
local F = minetest.formspec_escape
|
||||
local C = minetest.colorize
|
||||
|
||||
local MAX_NAME_LENGTH = 35
|
||||
local MAX_WEAR = 65535
|
||||
@ -10,41 +12,65 @@ local MATERIAL_TOOL_REPAIR_BOOST = {
|
||||
MAX_WEAR, -- 100%
|
||||
}
|
||||
|
||||
---@param set_name? string
|
||||
local function get_anvil_formspec(set_name)
|
||||
if not set_name then
|
||||
set_name = ""
|
||||
end
|
||||
return "size[9,8.75]"..
|
||||
"background[-0.19,-0.25;9.41,9.49;mcl_anvils_inventory.png]"..
|
||||
"label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]"..
|
||||
"list[current_player;main;0,4.5;9,3;9]"..
|
||||
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
|
||||
"list[current_player;main;0,7.74;9,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(0,7.74,9,1)..
|
||||
"list[context;input;1,2.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(1,2.5,1,1)..
|
||||
"list[context;input;4,2.5;1,1;1]"..
|
||||
mcl_formspec.get_itemslot_bg(4,2.5,1,1)..
|
||||
"list[context;output;8,2.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(8,2.5,1,1)..
|
||||
"label[3,0.1;"..minetest.formspec_escape(minetest.colorize("#313131", S("Repair and Name"))).."]"..
|
||||
"field[3.25,1;4,1;name;;"..minetest.formspec_escape(set_name).."]"..
|
||||
"field_close_on_enter[name;false]"..
|
||||
"button[7,0.7;2,1;name_button;"..minetest.formspec_escape(S("Set Name")).."]"..
|
||||
"listring[context;output]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;input]"..
|
||||
"listring[current_player;main]"
|
||||
|
||||
return table.concat({
|
||||
"formspec_version[4]",
|
||||
"size[11.75,10.425]",
|
||||
|
||||
"label[4.125,0.375;" .. F(C(mcl_formspec.label_color, S("Repair and Name"))) .. "]",
|
||||
|
||||
"image[0.875,0.375;1.75,1.75;mcl_anvils_inventory_hammer.png]",
|
||||
|
||||
"field[4.125,0.75;7.25,1;name;;" .. F(set_name) .. "]",
|
||||
"field_close_on_enter[name;false]",
|
||||
"set_focus[name;true]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(1.625, 2.6, 1, 1),
|
||||
"list[context;input;1.625,2.6;1,1;]",
|
||||
|
||||
"image[3.5,2.6;1,1;mcl_anvils_inventory_cross.png]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(5.375, 2.6, 1, 1),
|
||||
"list[context;input;5.375,2.6;1,1;1]",
|
||||
|
||||
"image[6.75,2.6;2,1;mcl_anvils_inventory_arrow.png]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(9.125, 2.6, 1, 1),
|
||||
"list[context;output;9.125,2.6;1,1;]",
|
||||
|
||||
-- Player Inventory
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3),
|
||||
"list[current_player;main;0.375,5.1;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1),
|
||||
"list[current_player;main;0.375,9.05;9,1;]",
|
||||
|
||||
-- Listrings
|
||||
|
||||
"listring[context;output]",
|
||||
"listring[current_player;main]",
|
||||
"listring[context;input]",
|
||||
"listring[current_player;main]",
|
||||
})
|
||||
end
|
||||
|
||||
-- Given a tool and material stack, returns how many items of the material stack
|
||||
-- needs to be used up to repair the tool.
|
||||
---@param tool ItemStack
|
||||
---@param material ItemStack
|
||||
---@return integer
|
||||
local function get_consumed_materials(tool, material)
|
||||
local wear = tool:get_wear()
|
||||
--local health = (MAX_WEAR - wear)
|
||||
local matsize = material:get_count()
|
||||
local materials_used = 0
|
||||
for m=1, math.min(4, matsize) do
|
||||
for m = 1, math.min(4, matsize) do
|
||||
materials_used = materials_used + 1
|
||||
if (wear - MATERIAL_TOOL_REPAIR_BOOST[m]) <= 0 then
|
||||
break
|
||||
@ -53,27 +79,20 @@ 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.
|
||||
-- Returns nil otherwise.
|
||||
---@param input1 ItemStack
|
||||
---@param input2 ItemStack
|
||||
local function distinguish_tool_and_material(input1, input2)
|
||||
local def1 = input1:get_definition()
|
||||
local def2 = input2:get_definition()
|
||||
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
|
||||
if def1.type == "tool" and r1 and type(r1) == "table" and table.indexof(r1, input2) ~= -1 then
|
||||
return "tool", input1, input2
|
||||
elseif def2.type == "tool" and r2 and type(r2) == "table" and contains(r2, input1) then
|
||||
elseif def2.type == "tool" and r2 and type(r2) == "table" and table.indexof(r1, input1) ~= -1 then
|
||||
return "material", input2, input1
|
||||
elseif def1.type == "tool" and r1 then
|
||||
return "tool", input1, input2
|
||||
@ -84,7 +103,8 @@ local function distinguish_tool_and_material(input1, input2)
|
||||
end
|
||||
end
|
||||
|
||||
-- Helper function to make sure update_anvil_slots NEVER overstacks the output slot
|
||||
---Helper function to make sure update_anvil_slots NEVER overstacks the output slot
|
||||
---@param stack ItemStack
|
||||
local function fix_stack_size(stack)
|
||||
if not stack or stack == "" then return "" end
|
||||
local count = stack:get_count()
|
||||
@ -99,6 +119,7 @@ end
|
||||
|
||||
-- Update the inventory slots of an anvil node.
|
||||
-- meta: Metadata of anvil node
|
||||
---@param meta NodeMetaRef
|
||||
local function update_anvil_slots(meta)
|
||||
local inv = meta:get_inventory()
|
||||
local new_name = meta:get_string("set_name")
|
||||
@ -159,7 +180,7 @@ local function update_anvil_slots(meta)
|
||||
has_correct_material = true
|
||||
end
|
||||
else
|
||||
if contains(repair, material_name) then
|
||||
if table.indexof(repair, material_name) ~= -1 then
|
||||
has_correct_material = true
|
||||
else
|
||||
for _, r in pairs(repair) do
|
||||
@ -231,28 +252,32 @@ local function update_anvil_slots(meta)
|
||||
end
|
||||
end
|
||||
|
||||
-- Drop input items of anvil at pos with metadata meta
|
||||
---Drop input items of anvil at pos with metadata meta
|
||||
---@param pos Vector
|
||||
---@param meta NodeMetaRef
|
||||
local function drop_anvil_items(pos, meta)
|
||||
local inv = meta:get_inventory()
|
||||
for i=1, inv:get_size("input") do
|
||||
for i = 1, inv:get_size("input") do
|
||||
local stack = inv:get_stack("input", i)
|
||||
if not stack:is_empty() then
|
||||
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5}
|
||||
local p = vector.offset(pos, math.random(0, 10) / 10 - 0.5, 0, math.random(0, 10) / 10 - 0.5)
|
||||
minetest.add_item(p, stack)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param pos Vector
|
||||
---@param node node
|
||||
local function damage_particles(pos, node)
|
||||
minetest.add_particlespawner({
|
||||
amount = 30,
|
||||
time = 0.1,
|
||||
minpos = vector.add(pos, {x=-0.5, y=-0.5, z=-0.5}),
|
||||
maxpos = vector.add(pos, {x=0.5, y=-0.25, z=0.5}),
|
||||
minvel = {x=-0.5, y=0.05, z=-0.5},
|
||||
maxvel = {x=0.5, y=0.3, z=0.5},
|
||||
minacc = {x=0, y=-9.81, z=0},
|
||||
maxacc = {x=0, y=-9.81, z=0},
|
||||
minpos = vector.offset(pos, -0.5, -0.5, -0.5),
|
||||
maxpos = vector.offset(pos, 0.5, -0.25, 0.5),
|
||||
minvel = vector.new(-0.5, 0.05, -0.5),
|
||||
maxvel = vector.new(0.5, 0.3, 0.5),
|
||||
minacc = vector.new(0, -9.81, 0),
|
||||
maxacc = vector.new(0, -9.81, 0),
|
||||
minexptime = 0.1,
|
||||
maxexptime = 0.5,
|
||||
minsize = 0.4,
|
||||
@ -267,12 +292,12 @@ local function destroy_particles(pos, node)
|
||||
minetest.add_particlespawner({
|
||||
amount = math.random(20, 30),
|
||||
time = 0.1,
|
||||
minpos = vector.add(pos, {x=-0.4, y=-0.4, z=-0.4}),
|
||||
maxpos = vector.add(pos, {x=0.4, y=0.4, z=0.4}),
|
||||
minvel = {x=-0.5, y=-0.1, z=-0.5},
|
||||
maxvel = {x=0.5, y=0.2, z=0.5},
|
||||
minacc = {x=0, y=-9.81, z=0},
|
||||
maxacc = {x=0, y=-9.81, z=0},
|
||||
minpos = vector.offset(pos, -0.4, -0.4, -0.4),
|
||||
maxpos = vector.offset(pos, 0.4, 0.4, 0.4),
|
||||
minvel = vector.new(-0.5, -0.1, -0.5),
|
||||
maxvel = vector.new(0.5, 0.2, 0.5),
|
||||
minacc = vector.new(0, -9.81, 0),
|
||||
maxacc = vector.new(0, -9.81, 0),
|
||||
minexptime = 0.2,
|
||||
maxexptime = 0.65,
|
||||
minsize = 0.8,
|
||||
@ -289,28 +314,29 @@ end
|
||||
local function damage_anvil(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
if node.name == "mcl_anvils:anvil" then
|
||||
minetest.swap_node(pos, {name="mcl_anvils:anvil_damage_1", param2=node.param2})
|
||||
minetest.swap_node(pos, { name = "mcl_anvils:anvil_damage_1", param2 = node.param2 })
|
||||
damage_particles(pos, node)
|
||||
minetest.sound_play(mcl_sounds.node_sound_metal_defaults().dig, {pos=pos, max_hear_distance=16}, true)
|
||||
minetest.sound_play(mcl_sounds.node_sound_metal_defaults().dig, { pos = pos, max_hear_distance = 16 }, true)
|
||||
return false
|
||||
elseif node.name == "mcl_anvils:anvil_damage_1" then
|
||||
minetest.swap_node(pos, {name="mcl_anvils:anvil_damage_2", param2=node.param2})
|
||||
minetest.swap_node(pos, { name = "mcl_anvils:anvil_damage_2", param2 = node.param2 })
|
||||
damage_particles(pos, node)
|
||||
minetest.sound_play(mcl_sounds.node_sound_metal_defaults().dig, {pos=pos, max_hear_distance=16}, true)
|
||||
minetest.sound_play(mcl_sounds.node_sound_metal_defaults().dig, { pos = pos, max_hear_distance = 16 }, true)
|
||||
return false
|
||||
elseif node.name == "mcl_anvils:anvil_damage_2" then
|
||||
-- Destroy anvil
|
||||
local meta = minetest.get_meta(pos)
|
||||
drop_anvil_items(pos, meta)
|
||||
minetest.sound_play(mcl_sounds.node_sound_metal_defaults().dug, {pos=pos, max_hear_distance=16}, true)
|
||||
minetest.sound_play(mcl_sounds.node_sound_metal_defaults().dug, { pos = pos, max_hear_distance = 16 }, true)
|
||||
minetest.remove_node(pos)
|
||||
destroy_particles(pos, node)
|
||||
minetest.check_single_for_falling({x=pos.x, y=pos.y+1, z=pos.z})
|
||||
minetest.check_single_for_falling(vector.offset(pos, 0, 1, 0))
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- Roll a virtual dice and damage anvil at a low chance.
|
||||
---Roll a virtual dice and damage anvil at a low chance.
|
||||
---@param pos Vector
|
||||
local function damage_anvil_by_using(pos)
|
||||
local r = math.random(1, 100)
|
||||
-- 12% chance
|
||||
@ -321,25 +347,30 @@ local function damage_anvil_by_using(pos)
|
||||
end
|
||||
end
|
||||
|
||||
---@param pos Vector
|
||||
---@param distance number
|
||||
local function damage_anvil_by_falling(pos, distance)
|
||||
local r = math.random(1, 100)
|
||||
if distance > 1 then
|
||||
if r <= (5*distance) then
|
||||
if r <= (5 * distance) then
|
||||
damage_anvil(pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@type nodebox
|
||||
local anvilbox = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{ -8 / 16, -8 / 16, -6 / 16, 8 / 16, 8 / 16, 6 / 16 },
|
||||
},
|
||||
}
|
||||
|
||||
---@type node_definition
|
||||
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"},
|
||||
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
|
||||
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" },
|
||||
use_texture_alpha = "opaque",
|
||||
_tt_help = S("Repair and rename items"),
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
@ -353,7 +384,7 @@ local anvildef = {
|
||||
{ -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,
|
||||
@ -416,7 +447,7 @@ local anvildef = {
|
||||
local meta = minetest.get_meta(pos)
|
||||
if from_list == "output" and to_list == "input" then
|
||||
local inv = meta:get_inventory()
|
||||
for i=1, inv:get_size("input") do
|
||||
for i = 1, inv:get_size("input") do
|
||||
if i ~= to_index then
|
||||
local istack = inv:get_stack("input", i)
|
||||
istack:set_count(math.max(0, istack:get_count() - count))
|
||||
@ -504,22 +535,20 @@ local anvildef = {
|
||||
minetest.record_protection_violation(pos, sender_name)
|
||||
return
|
||||
end
|
||||
if fields.name_button or fields.name then
|
||||
local set_name
|
||||
if fields.name == nil then
|
||||
set_name = ""
|
||||
else
|
||||
set_name = fields.name
|
||||
end
|
||||
|
||||
if fields.name then
|
||||
local meta = minetest.get_meta(pos)
|
||||
|
||||
-- Limit name length
|
||||
set_name = string.sub(set_name, 1, MAX_NAME_LENGTH)
|
||||
local set_name = string.sub(fields.name, 1, MAX_NAME_LENGTH)
|
||||
|
||||
meta:set_string("set_name", set_name)
|
||||
update_anvil_slots(meta)
|
||||
meta:set_string("formspec", get_anvil_formspec(set_name))
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
if minetest.get_modpath("screwdriver") then
|
||||
anvildef.on_rotate = screwdriver.rotate_simple
|
||||
end
|
||||
@ -527,29 +556,34 @@ end
|
||||
local anvildef0 = table.copy(anvildef)
|
||||
anvildef0.description = S("Anvil")
|
||||
anvildef0._doc_items_longdesc =
|
||||
S("The anvil allows you to repair tools and armor, and to give names to items. It has a limited durability, however. Don't let it fall on your head, it could be quite painful!")
|
||||
S("The anvil allows you to repair tools and armor, and to give names to items. It has a limited durability, however. Don't let it fall on your head, it could be quite painful!")
|
||||
anvildef0._doc_items_usagehelp =
|
||||
S("To use an anvil, rightclick it. An anvil has 2 input slots (on the left) and one output slot.").."\n"..
|
||||
S("To rename items, put an item stack in one of the item slots while keeping the other input slot empty. Type in a name, hit enter or “Set Name”, then take the renamed item from the output slot.").."\n"..
|
||||
S("There are two possibilities to repair tools (and armor):").."\n"..
|
||||
S("• Tool + Tool: Place two tools of the same type in the input slots. The “health” of the repaired tool is the sum of the “health” of both input tools, plus a 12% bonus.").."\n"..
|
||||
S("• Tool + Material: Some tools can also be repaired by combining them with an item that it's made of. For example, iron pickaxes can be repaired with iron ingots. This repairs the tool by 25%.").."\n"..
|
||||
S("Armor counts as a tool. It is possible to repair and rename a tool in a single step.").."\n\n"..
|
||||
S("The anvil has limited durability and 3 damage levels: undamaged, slightly damaged and very damaged. Each time you repair or rename something, there is a 12% chance the anvil gets damaged. Anvils also have a chance of being damaged when they fall by more than 1 block. If a very damaged anvil is damaged again, it is destroyed.")
|
||||
S("To use an anvil, rightclick it. An anvil has 2 input slots (on the left) and one output slot.") .. "\n" ..
|
||||
S("To rename items, put an item stack in one of the item slots while keeping the other input slot empty. Type in a name, hit enter or “Set Name”, then take the renamed item from the output slot.")
|
||||
.. "\n" ..
|
||||
S("There are two possibilities to repair tools (and armor):") .. "\n" ..
|
||||
S("• Tool + Tool: Place two tools of the same type in the input slots. The “health” of the repaired tool is the sum of the “health” of both input tools, plus a 12% bonus.")
|
||||
.. "\n" ..
|
||||
S("• Tool + Material: Some tools can also be repaired by combining them with an item that it's made of. For example, iron pickaxes can be repaired with iron ingots. This repairs the tool by 25%.")
|
||||
.. "\n" ..
|
||||
S("Armor counts as a tool. It is possible to repair and rename a tool in a single step.") .. "\n\n" ..
|
||||
S("The anvil has limited durability and 3 damage levels: undamaged, slightly damaged and very damaged. Each time you repair or rename something, there is a 12% chance the anvil gets damaged. Anvils also have a chance of being damaged when they fall by more than 1 block. If a very damaged anvil is damaged again, it is destroyed.")
|
||||
|
||||
local anvildef1 = table.copy(anvildef)
|
||||
anvildef1.description = S("Slightly Damaged Anvil")
|
||||
anvildef1._doc_items_create_entry = false
|
||||
anvildef1.groups.anvil = 2
|
||||
anvildef1._doc_items_create_entry = false
|
||||
anvildef1.tiles = {"mcl_anvils_anvil_top_damaged_1.png^[transformR90", "mcl_anvils_anvil_base.png", "mcl_anvils_anvil_side.png"}
|
||||
anvildef1.tiles = { "mcl_anvils_anvil_top_damaged_1.png^[transformR90", "mcl_anvils_anvil_base.png",
|
||||
"mcl_anvils_anvil_side.png" }
|
||||
|
||||
local anvildef2 = table.copy(anvildef)
|
||||
anvildef2.description = S("Very Damaged Anvil")
|
||||
anvildef2._doc_items_create_entry = false
|
||||
anvildef2.groups.anvil = 3
|
||||
anvildef2._doc_items_create_entry = false
|
||||
anvildef2.tiles = {"mcl_anvils_anvil_top_damaged_2.png^[transformR90", "mcl_anvils_anvil_base.png", "mcl_anvils_anvil_side.png"}
|
||||
anvildef2.tiles = { "mcl_anvils_anvil_top_damaged_2.png^[transformR90", "mcl_anvils_anvil_base.png",
|
||||
"mcl_anvils_anvil_side.png" }
|
||||
|
||||
minetest.register_node("mcl_anvils:anvil", anvildef0)
|
||||
minetest.register_node("mcl_anvils:anvil_damage_1", anvildef1)
|
||||
@ -562,7 +596,7 @@ if minetest.get_modpath("mcl_core") then
|
||||
{ "mcl_core:ironblock", "mcl_core:ironblock", "mcl_core:ironblock" },
|
||||
{ "", "mcl_core:iron_ingot", "" },
|
||||
{ "mcl_core:iron_ingot", "mcl_core:iron_ingot", "mcl_core:iron_ingot" },
|
||||
}
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
|
@ -8,6 +8,7 @@ local open_barrels = {}
|
||||
|
||||
local drop_content = mcl_util.drop_items_from_meta_container("main")
|
||||
|
||||
---@param pos Vector
|
||||
local function on_blast(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
drop_content(pos, node)
|
||||
@ -45,30 +46,34 @@ local function barrel_open(pos, node, clicker)
|
||||
local playername = clicker:get_player_name()
|
||||
|
||||
minetest.show_formspec(playername,
|
||||
"mcl_barrels:barrel_"..pos.x.."_"..pos.y.."_"..pos.z,
|
||||
"mcl_barrels:barrel_" .. pos.x .. "_" .. pos.y .. "_" .. pos.z,
|
||||
table.concat({
|
||||
"size[9,8.75]",
|
||||
"label[0,0;"..F(C("#313131", name)).."]",
|
||||
"list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0,0.5;9,3;]",
|
||||
mcl_formspec.get_itemslot_bg(0, 0.5, 9, 3),
|
||||
"label[0,4.0;"..F(C("#313131", S("Inventory"))).."]",
|
||||
"list[current_player;main;0,4.5;9,3;9]",
|
||||
mcl_formspec.get_itemslot_bg(0, 4.5, 9, 3),
|
||||
"list[current_player;main;0,7.74;9,1;]",
|
||||
mcl_formspec.get_itemslot_bg(0, 7.74, 9, 1),
|
||||
"listring[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main]",
|
||||
"formspec_version[4]",
|
||||
"size[11.75,10.425]",
|
||||
|
||||
"label[0.375,0.375;" .. F(C(mcl_formspec.label_color, name)) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 0.75, 9, 3),
|
||||
"list[nodemeta:" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ";main;0.375,0.75;9,3;]",
|
||||
"label[0.375,4.7;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3),
|
||||
"list[current_player;main;0.375,5.1;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1),
|
||||
"list[current_player;main;0.375,9.05;9,1;]",
|
||||
"listring[nodemeta:" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ";main]",
|
||||
"listring[current_player;main]",
|
||||
})
|
||||
)
|
||||
|
||||
minetest.swap_node(pos, { name = "mcl_barrels:barrel_open", param2 = node.param2 })
|
||||
open_barrels[playername] = pos
|
||||
minetest.sound_play({name="mcl_barrels_default_barrel_open", pos=pos, gain=0.5, max_hear_distance=16}, true)
|
||||
minetest.sound_play({ name = "mcl_barrels_default_barrel_open", pos = pos, gain = 0.5, max_hear_distance = 16 }, true)
|
||||
end
|
||||
|
||||
---@param pos Vector
|
||||
local function close_forms(pos)
|
||||
local players = minetest.get_connected_players()
|
||||
local formname = "mcl_barrels:barrel_"..pos.x.."_"..pos.y.."_"..pos.z
|
||||
local formname = "mcl_barrels:barrel_" .. pos.x .. "_" .. pos.y .. "_" .. pos.z
|
||||
for p = 1, #players do
|
||||
if vector.distance(players[p]:get_pos(), pos) <= 30 then
|
||||
minetest.close_formspec(players[p]:get_player_name(), formname)
|
||||
@ -76,15 +81,18 @@ local function close_forms(pos)
|
||||
end
|
||||
end
|
||||
|
||||
---@param pos Vector
|
||||
local function update_after_close(pos)
|
||||
local node = minetest.get_node_or_nil(pos)
|
||||
if not node then return end
|
||||
if node.name == "mcl_barrels:barrel_open" then
|
||||
minetest.swap_node(pos, {name = "mcl_barrels:barrel_closed", param2 = node.param2})
|
||||
minetest.sound_play({name="mcl_barrels_default_barrel_close", pos=pos, gain=0.5, max_hear_distance=16}, true)
|
||||
minetest.swap_node(pos, { name = "mcl_barrels:barrel_closed", param2 = node.param2 })
|
||||
minetest.sound_play({ name = "mcl_barrels_default_barrel_close", pos = pos, gain = 0.5, max_hear_distance = 16 },
|
||||
true)
|
||||
end
|
||||
end
|
||||
|
||||
---@param player ObjectRef
|
||||
local function close_barrel(player)
|
||||
local name = player:get_player_name()
|
||||
local open = open_barrels[name]
|
||||
@ -102,20 +110,22 @@ minetest.register_node("mcl_barrels:barrel_closed", {
|
||||
_tt_help = S("27 inventory slots"),
|
||||
_doc_items_longdesc = S("Barrels are containers which provide 27 inventory slots."),
|
||||
_doc_items_usagehelp = S("To access its inventory, rightclick it. When broken, the items will drop out."),
|
||||
tiles = {"mcl_barrels_barrel_top.png^[transformR270", "mcl_barrels_barrel_bottom.png", "mcl_barrels_barrel_side.png"},
|
||||
tiles = { "mcl_barrels_barrel_top.png^[transformR270", "mcl_barrels_barrel_bottom.png", "mcl_barrels_barrel_side.png" },
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
minetest.rotate_and_place(itemstack, placer, pointed_thing, minetest.is_creative_enabled(placer:get_player_name()), {}, false)
|
||||
minetest.rotate_and_place(itemstack, placer, pointed_thing,
|
||||
minetest.is_creative_enabled(placer:get_player_name()), {}
|
||||
, false)
|
||||
return itemstack
|
||||
end,
|
||||
stack_max = 64,
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
groups = {handy = 1, axey = 1, container = 2, material_wood = 1, flammable = -1, deco_block = 1},
|
||||
groups = { handy = 1, axey = 1, container = 2, material_wood = 1, flammable = -1, deco_block = 1 },
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size("main", 9*3)
|
||||
inv:set_size("main", 9 * 3)
|
||||
end,
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
minetest.get_meta(pos):set_string("name", itemstack:get_meta():get_string("name"))
|
||||
@ -124,16 +134,16 @@ minetest.register_node("mcl_barrels:barrel_closed", {
|
||||
allow_metadata_inventory_take = protection_check_put_take,
|
||||
allow_metadata_inventory_put = protection_check_put_take,
|
||||
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
minetest.log("action", player:get_player_name()..
|
||||
" moves stuff in barrel at "..minetest.pos_to_string(pos))
|
||||
minetest.log("action", player:get_player_name() ..
|
||||
" moves stuff in barrel at " .. minetest.pos_to_string(pos))
|
||||
end,
|
||||
on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
minetest.log("action", player:get_player_name()..
|
||||
" moves stuff to barrel at "..minetest.pos_to_string(pos))
|
||||
minetest.log("action", player:get_player_name() ..
|
||||
" moves stuff to barrel at " .. minetest.pos_to_string(pos))
|
||||
end,
|
||||
on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
minetest.log("action", player:get_player_name()..
|
||||
" takes stuff from barrel at "..minetest.pos_to_string(pos))
|
||||
minetest.log("action", player:get_player_name() ..
|
||||
" takes stuff from barrel at " .. minetest.pos_to_string(pos))
|
||||
end,
|
||||
after_dig_node = drop_content,
|
||||
on_blast = on_blast,
|
||||
@ -149,27 +159,35 @@ minetest.register_node("mcl_barrels:barrel_open", {
|
||||
_doc_items_longdesc = S("Barrels are containers which provide 27 inventory slots."),
|
||||
_doc_items_usagehelp = S("To access its inventory, rightclick it. When broken, the items will drop out."),
|
||||
_doc_items_create_entry = false,
|
||||
tiles = {"mcl_barrels_barrel_top_open.png", "mcl_barrels_barrel_bottom.png", "mcl_barrels_barrel_side.png"},
|
||||
tiles = { "mcl_barrels_barrel_top_open.png", "mcl_barrels_barrel_bottom.png", "mcl_barrels_barrel_side.png" },
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
drop = "mcl_barrels:barrel_closed",
|
||||
stack_max = 64,
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
groups = {handy = 1, axey = 1, container = 2, material_wood = 1, flammable = -1, deco_block = 1, not_in_creative_inventory = 1},
|
||||
groups = {
|
||||
handy = 1,
|
||||
axey = 1,
|
||||
container = 2,
|
||||
material_wood = 1,
|
||||
flammable = -1,
|
||||
deco_block = 1,
|
||||
not_in_creative_inventory = 1
|
||||
},
|
||||
allow_metadata_inventory_move = protection_check_move,
|
||||
allow_metadata_inventory_take = protection_check_put_take,
|
||||
allow_metadata_inventory_put = protection_check_put_take,
|
||||
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
minetest.log("action", player:get_player_name()..
|
||||
" moves stuff in barrel at "..minetest.pos_to_string(pos))
|
||||
minetest.log("action", player:get_player_name() ..
|
||||
" moves stuff in barrel at " .. minetest.pos_to_string(pos))
|
||||
end,
|
||||
on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
minetest.log("action", player:get_player_name()..
|
||||
" moves stuff to barrel at "..minetest.pos_to_string(pos))
|
||||
minetest.log("action", player:get_player_name() ..
|
||||
" moves stuff to barrel at " .. minetest.pos_to_string(pos))
|
||||
end,
|
||||
on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
minetest.log("action", player:get_player_name()..
|
||||
" takes stuff from barrel at "..minetest.pos_to_string(pos))
|
||||
minetest.log("action", player:get_player_name() ..
|
||||
" takes stuff from barrel at " .. minetest.pos_to_string(pos))
|
||||
end,
|
||||
after_dig_node = drop_content,
|
||||
on_blast = on_blast,
|
||||
@ -193,10 +211,10 @@ end)
|
||||
minetest.register_craft({
|
||||
output = "mcl_barrels:barrel_closed",
|
||||
recipe = {
|
||||
{"group:wood", "group:wood_slab", "group:wood"},
|
||||
{"group:wood", "", "group:wood"},
|
||||
{"group:wood", "group:wood_slab", "group:wood"},
|
||||
}
|
||||
{ "group:wood", "group:wood_slab", "group:wood" },
|
||||
{ "group:wood", "", "group:wood" },
|
||||
{ "group:wood", "group:wood_slab", "group:wood" },
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
|
@ -1,5 +1,6 @@
|
||||
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
local C = minetest.colorize
|
||||
local F = minetest.formspec_escape
|
||||
|
||||
local LIGHT_ACTIVE_FURNACE = 13
|
||||
|
||||
@ -8,60 +9,82 @@ local LIGHT_ACTIVE_FURNACE = 13
|
||||
--
|
||||
|
||||
local function active_formspec(fuel_percent, item_percent)
|
||||
return "size[9,8.75]"..
|
||||
"label[0,4;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]"..
|
||||
"list[current_player;main;0,4.5;9,3;9]"..
|
||||
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
|
||||
"list[current_player;main;0,7.74;9,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(0,7.74,9,1)..
|
||||
"label[2.75,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Blast Furnace"))).."]"..
|
||||
"list[context;src;2.75,0.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(2.75,0.5,1,1)..
|
||||
"list[context;fuel;2.75,2.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(2.75,2.5,1,1)..
|
||||
"list[context;dst;5.75,1.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(5.75,1.5,1,1)..
|
||||
"image[2.75,1.5;1,1;default_furnace_fire_bg.png^[lowpart:"..
|
||||
(100-fuel_percent)..":default_furnace_fire_fg.png]"..
|
||||
"image[4.1,1.5;1.5,1;gui_furnace_arrow_bg.png^[lowpart:"..
|
||||
(item_percent)..":gui_furnace_arrow_fg.png^[transformR270]"..
|
||||
return table.concat({
|
||||
"formspec_version[4]",
|
||||
"size[11.75,10.425]",
|
||||
"label[0.375,0.375;" .. F(C(mcl_formspec.label_color, S("Blast Furnace"))) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(3.5, 0.75, 1, 1),
|
||||
"list[context;src;3.5,0.75;1,1;]",
|
||||
|
||||
"image[3.5,2;1,1;default_furnace_fire_bg.png^[lowpart:" ..
|
||||
(100 - fuel_percent) .. ":default_furnace_fire_fg.png]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(3.5, 3.25, 1, 1),
|
||||
"list[context;fuel;3.5,3.25;1,1;]",
|
||||
|
||||
"image[5.25,2;1.5,1;gui_furnace_arrow_bg.png^[lowpart:" ..
|
||||
(item_percent) .. ":gui_furnace_arrow_fg.png^[transformR270]",
|
||||
mcl_formspec.get_itemslot_bg_v4(7.875, 2, 1, 1, 0.2),
|
||||
"list[context;dst;7.875,2;1,1;]",
|
||||
|
||||
"label[0.375,4.7;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3),
|
||||
"list[current_player;main;0.375,5.1;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1),
|
||||
"list[current_player;main;0.375,9.05;9,1;]",
|
||||
|
||||
-- Craft guide button temporarily removed due to Minetest bug.
|
||||
-- TODO: Add it back when the Minetest bug is fixed.
|
||||
--"image_button[8,0;1,1;craftguide_book.png;craftguide;]"..
|
||||
--"tooltip[craftguide;"..minetest.formspec_escape(S("Recipe book")).."]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;fuel]"..
|
||||
"listring[current_player;main]"
|
||||
|
||||
"listring[context;dst]",
|
||||
"listring[current_player;main]",
|
||||
"listring[context;src]",
|
||||
"listring[current_player;main]",
|
||||
"listring[context;fuel]",
|
||||
"listring[current_player;main]",
|
||||
})
|
||||
end
|
||||
|
||||
local inactive_formspec = "size[9,8.75]"..
|
||||
"label[0,4;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]"..
|
||||
"list[current_player;main;0,4.5;9,3;9]"..
|
||||
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
|
||||
"list[current_player;main;0,7.74;9,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(0,7.74,9,1)..
|
||||
"label[2.75,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Blast Furnace"))).."]"..
|
||||
"list[context;src;2.75,0.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(2.75,0.5,1,1)..
|
||||
"list[context;fuel;2.75,2.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(2.75,2.5,1,1)..
|
||||
"list[context;dst;5.75,1.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(5.75,1.5,1,1)..
|
||||
"image[2.75,1.5;1,1;default_furnace_fire_bg.png]"..
|
||||
"image[4.1,1.5;1.5,1;gui_furnace_arrow_bg.png^[transformR270]"..
|
||||
local inactive_formspec = table.concat({
|
||||
"formspec_version[4]",
|
||||
"size[11.75,10.425]",
|
||||
"label[0.375,0.375;" .. F(C(mcl_formspec.label_color, S("Blast Furnace"))) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(3.5, 0.75, 1, 1),
|
||||
"list[context;src;3.5,0.75;1,1;]",
|
||||
|
||||
"image[3.5,2;1,1;default_furnace_fire_bg.png]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(3.5, 3.25, 1, 1),
|
||||
"list[context;fuel;3.5,3.25;1,1;]",
|
||||
|
||||
"image[5.25,2;1.5,1;gui_furnace_arrow_bg.png^[transformR270]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(7.875, 2, 1, 1, 0.2),
|
||||
"list[context;dst;7.875,2;1,1;]",
|
||||
|
||||
"label[0.375,4.7;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3),
|
||||
"list[current_player;main;0.375,5.1;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1),
|
||||
"list[current_player;main;0.375,9.05;9,1;]",
|
||||
|
||||
-- Craft guide button temporarily removed due to Minetest bug.
|
||||
-- TODO: Add it back when the Minetest bug is fixed.
|
||||
--"image_button[8,0;1,1;craftguide_book.png;craftguide;]"..
|
||||
--"tooltip[craftguide;"..minetest.formspec_escape(S("Recipe book")).."]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;fuel]"..
|
||||
"listring[current_player;main]"
|
||||
|
||||
"listring[context;dst]",
|
||||
"listring[current_player;main]",
|
||||
"listring[context;src]",
|
||||
"listring[current_player;main]",
|
||||
"listring[context;fuel]",
|
||||
"listring[current_player;main]",
|
||||
})
|
||||
|
||||
|
||||
local receive_fields = function(pos, formname, fields, sender)
|
||||
if fields.craftguide then
|
||||
@ -71,7 +94,7 @@ end
|
||||
|
||||
local function give_xp(pos, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local dir = vector.divide(minetest.facedir_to_dir(minetest.get_node(pos).param2),-1.95)
|
||||
local dir = vector.divide(minetest.facedir_to_dir(minetest.get_node(pos).param2), -1.95)
|
||||
local xp = meta:get_int("xp")
|
||||
if xp > 0 then
|
||||
if player then
|
||||
@ -99,7 +122,7 @@ local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
-- Test stack with size 1 because we burn one fuel at a time
|
||||
local teststack = ItemStack(stack)
|
||||
teststack:set_count(1)
|
||||
local output, decremented_input = minetest.get_craft_result({method="fuel", width=1, items={teststack}})
|
||||
local output, decremented_input = minetest.get_craft_result({ method = "fuel", width = 1, items = { teststack } })
|
||||
if output.time ~= 0 then
|
||||
-- Only allow to place 1 item if fuel get replaced by recipe.
|
||||
-- This is the case for lava buckets.
|
||||
@ -160,17 +183,17 @@ local function spawn_flames(pos, param2)
|
||||
local minrelpos, maxrelpos
|
||||
local dir = minetest.facedir_to_dir(param2)
|
||||
if dir.x > 0 then
|
||||
minrelpos = { x = -0.6, y = -0.05, z = -0.25 }
|
||||
maxrelpos = { x = -0.55, y = -0.45, z = 0.25 }
|
||||
minrelpos = vector.new(-0.6, -0.05, -0.25)
|
||||
maxrelpos = vector.new(-0.55, -0.45, 0.25)
|
||||
elseif dir.x < 0 then
|
||||
minrelpos = { x = 0.55, y = -0.05, z = -0.25 }
|
||||
maxrelpos = { x = 0.6, y = -0.45, z = 0.25 }
|
||||
minrelpos = vector.new(0.55, -0.05, -0.25)
|
||||
maxrelpos = vector.new(0.6, -0.45, 0.25)
|
||||
elseif dir.z > 0 then
|
||||
minrelpos = { x = -0.25, y = -0.05, z = -0.6 }
|
||||
maxrelpos = { x = 0.25, y = -0.45, z = -0.55 }
|
||||
minrelpos = vector.new(-0.25, -0.05, -0.6)
|
||||
maxrelpos = vector.new(0.25, 0.45, -0.55)
|
||||
elseif dir.z < 0 then
|
||||
minrelpos = { x = -0.25, y = -0.05, z = 0.55 }
|
||||
maxrelpos = { x = 0.25, y = -0.45, z = 0.6 }
|
||||
minrelpos = vector.new(-0.25, -0.05, 0.55)
|
||||
maxrelpos = vector.new(0.25, -0.45, 0.6)
|
||||
else
|
||||
return
|
||||
end
|
||||
@ -179,8 +202,8 @@ local function spawn_flames(pos, param2)
|
||||
time = 0,
|
||||
minpos = vector.add(pos, minrelpos),
|
||||
maxpos = vector.add(pos, maxrelpos),
|
||||
minvel = { x = -0.01, y = 0, z = -0.01 },
|
||||
maxvel = { x = 0.01, y = 0.1, z = 0.01 },
|
||||
minvel = vector.new(-0.01, 0, -0.01),
|
||||
maxvel = vector.new(0.01, 0.1, 0.01),
|
||||
minexptime = 0.3,
|
||||
maxexptime = 0.6,
|
||||
minsize = 0.4,
|
||||
@ -293,7 +316,7 @@ local function blast_furnace_node_timer(pos, elapsed)
|
||||
|
||||
-- Check if we have cookable content: cookable
|
||||
local aftercooked
|
||||
cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
|
||||
cooked, aftercooked = minetest.get_craft_result({ method = "cooking", width = 1, items = srclist })
|
||||
cookable = minetest.get_item_group(inv:get_stack("src", 1):get_name(), "blast_furnace_smeltable") == 1
|
||||
if cookable then
|
||||
-- Successful cooking requires space in dst slot and time
|
||||
@ -311,7 +334,7 @@ local function blast_furnace_node_timer(pos, elapsed)
|
||||
if cookable and not active then
|
||||
-- We need to get new fuel
|
||||
local afterfuel
|
||||
fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
|
||||
fuel, afterfuel = minetest.get_craft_result({ method = "fuel", width = 1, items = fuellist })
|
||||
|
||||
if fuel.time == 0 then
|
||||
-- No valid fuel in fuel list -- stop
|
||||
@ -415,12 +438,13 @@ end
|
||||
minetest.register_node("mcl_blast_furnace:blast_furnace", {
|
||||
description = S("Blast Furnace"),
|
||||
_tt_help = S("Smelts ores faster than furnace"),
|
||||
_doc_items_longdesc = S("Blast Furnaces smelt several items, mainly ores and armor, using a furnace fuel, but twice as fast as a normal furnace."),
|
||||
_doc_items_longdesc = S(
|
||||
"Blast Furnaces smelt several items, mainly ores and armor, using a furnace fuel, but twice as fast as a normal furnace."),
|
||||
_doc_items_usagehelp =
|
||||
S("Use the blast furnace to open the furnace menu.").."\n"..
|
||||
S("Place a furnace fuel in the lower slot and the source material in the upper slot.").."\n"..
|
||||
S("The blast furnace will slowly use its fuel to smelt the item.").."\n"..
|
||||
S("The result will be placed into the output slot at the right side.").."\n"..
|
||||
S("Use the blast furnace to open the furnace menu.") .. "\n" ..
|
||||
S("Place a furnace fuel in the lower slot and the source material in the upper slot.") .. "\n" ..
|
||||
S("The blast furnace will slowly use its fuel to smelt the item.") .. "\n" ..
|
||||
S("The result will be placed into the output slot at the right side.") .. "\n" ..
|
||||
S("Use the recipe book to see what ores you can smelt, what you can use as fuel and how long it will burn."),
|
||||
_doc_items_hidden = false,
|
||||
tiles = {
|
||||
@ -429,7 +453,7 @@ minetest.register_node("mcl_blast_furnace:blast_furnace", {
|
||||
"blast_furnace_side.png", "blast_furnace_front.png"
|
||||
},
|
||||
paramtype2 = "facedir",
|
||||
groups = {pickaxey=1, container=4, deco_block=1, material_stone=1},
|
||||
groups = { pickaxey = 1, container = 4, deco_block = 1, material_stone = 1 },
|
||||
is_ground_content = false,
|
||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
|
||||
@ -439,11 +463,10 @@ minetest.register_node("mcl_blast_furnace:blast_furnace", {
|
||||
local meta2 = meta:to_table()
|
||||
meta:from_table(oldmetadata)
|
||||
local inv = meta:get_inventory()
|
||||
for _, listname in ipairs({"src", "dst", "fuel"}) do
|
||||
for _, listname in ipairs({ "src", "dst", "fuel" }) do
|
||||
local stack = inv:get_stack(listname, 1)
|
||||
if not stack:is_empty() then
|
||||
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5}
|
||||
minetest.add_item(p, stack)
|
||||
minetest.add_item(vector.offset(pos, math.random(0, 10) / 10 - 0.5, 0, math.random(0, 10) / 10 - 0.5), stack)
|
||||
end
|
||||
end
|
||||
meta:from_table(meta2)
|
||||
@ -499,14 +522,16 @@ minetest.register_node("mcl_blast_furnace:blast_furnace_active", {
|
||||
tiles = {
|
||||
"blast_furnace_top.png", "blast_furnace_top.png",
|
||||
"blast_furnace_side.png", "blast_furnace_side.png",
|
||||
"blast_furnace_side.png", {name = "blast_furnace_front_on.png",
|
||||
animation = {type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 48}},
|
||||
"blast_furnace_side.png", {
|
||||
name = "blast_furnace_front_on.png",
|
||||
animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 48 }
|
||||
},
|
||||
},
|
||||
paramtype2 = "facedir",
|
||||
paramtype = "light",
|
||||
light_source = LIGHT_ACTIVE_FURNACE,
|
||||
drop = "mcl_blast_furnace:blast_furnace",
|
||||
groups = {pickaxey=1, container=4, deco_block=1, not_in_creative_inventory=1, material_stone=1},
|
||||
groups = { pickaxey = 1, container = 4, deco_block = 1, not_in_creative_inventory = 1, material_stone = 1 },
|
||||
is_ground_content = false,
|
||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
on_timer = blast_furnace_node_timer,
|
||||
@ -516,10 +541,14 @@ minetest.register_node("mcl_blast_furnace:blast_furnace_active", {
|
||||
local meta2 = meta
|
||||
meta:from_table(oldmetadata)
|
||||
local inv = meta:get_inventory()
|
||||
for _, listname in ipairs({"src", "dst", "fuel"}) do
|
||||
for _, listname in ipairs({ "src", "dst", "fuel" }) do
|
||||
local stack = inv:get_stack(listname, 1)
|
||||
if not stack:is_empty() then
|
||||
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5}
|
||||
local p = vector.new(
|
||||
pos.x + math.random(0, 10) / 10 - 0.5,
|
||||
pos.y,
|
||||
pos.z + math.random(0, 10) / 10 - 0.5
|
||||
)
|
||||
minetest.add_item(p, stack)
|
||||
end
|
||||
end
|
||||
@ -564,10 +593,9 @@ end
|
||||
minetest.register_lbm({
|
||||
label = "Active blast_furnace flame particles",
|
||||
name = "mcl_blast_furnace:flames",
|
||||
nodenames = {"mcl_blast_furnace:blast_furnace_active"},
|
||||
nodenames = { "mcl_blast_furnace:blast_furnace_active" },
|
||||
run_at_every_load = true,
|
||||
action = function(pos, node)
|
||||
spawn_flames(pos, node.param2)
|
||||
end,
|
||||
})
|
||||
|
||||
|
@ -5,7 +5,7 @@ local C = minetest.colorize
|
||||
local max_text_length = 4500 -- TODO: Increase to 12800 when scroll bar was added to written book
|
||||
local max_title_length = 64
|
||||
|
||||
local bookshelf_inv = minetest.settings:get_bool("mcl_bookshelf_inventories",true)
|
||||
local bookshelf_inv = minetest.settings:get_bool("mcl_bookshelf_inventories", true)
|
||||
|
||||
local header = ""
|
||||
if minetest.get_modpath("mcl_init") then
|
||||
@ -19,7 +19,7 @@ minetest.register_craftitem("mcl_books:book", {
|
||||
_doc_items_longdesc = S("Books are used to make bookshelves and book and quills."),
|
||||
inventory_image = "default_book.png",
|
||||
stack_max = 64,
|
||||
groups = { book=1, craftitem = 1, enchantability = 1 },
|
||||
groups = { book = 1, craftitem = 1, enchantability = 1 },
|
||||
_mcl_enchanting_enchanted_tool = "mcl_enchanting:book_enchanted",
|
||||
})
|
||||
|
||||
@ -85,18 +85,19 @@ local function write(itemstack, user, pointed_thing)
|
||||
local node = minetest.get_node(pointed_thing.under)
|
||||
if user and not user:get_player_control().sneak then
|
||||
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
|
||||
return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, user, itemstack) or itemstack
|
||||
return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, user, itemstack) or
|
||||
itemstack
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local text = get_text(itemstack)
|
||||
local formspec = "size[8,9]"..
|
||||
header..
|
||||
"background[-0.5,-0.5;9,10;mcl_books_book_bg.png]"..
|
||||
"textarea[0.75,0.1;7.25,9;text;;"..minetest.formspec_escape(text).."]"..
|
||||
"button[0.75,7.95;3,1;sign;"..minetest.formspec_escape(S("Sign")).."]"..
|
||||
"button_exit[4.25,7.95;3,1;ok;"..minetest.formspec_escape(S("Done")).."]"
|
||||
local formspec = "size[8,9]" ..
|
||||
header ..
|
||||
"background[-0.5,-0.5;9,10;mcl_books_book_bg.png]" ..
|
||||
"textarea[0.75,0.1;7.25,9;text;;" .. minetest.formspec_escape(text) .. "]" ..
|
||||
"button[0.75,7.95;3,1;sign;" .. minetest.formspec_escape(S("Sign")) .. "]" ..
|
||||
"button_exit[4.25,7.95;3,1;ok;" .. minetest.formspec_escape(S("Done")) .. "]"
|
||||
minetest.show_formspec(user:get_player_name(), "mcl_books:writable_book", formspec)
|
||||
end
|
||||
|
||||
@ -106,17 +107,18 @@ local function read(itemstack, user, pointed_thing)
|
||||
local node = minetest.get_node(pointed_thing.under)
|
||||
if user and not user:get_player_control().sneak then
|
||||
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
|
||||
return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, user, itemstack) or itemstack
|
||||
return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, user, itemstack) or
|
||||
itemstack
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local text = get_text(itemstack)
|
||||
local formspec = "size[8,9]"..
|
||||
header..
|
||||
"background[-0.5,-0.5;9,10;mcl_books_book_bg.png]"..
|
||||
"textarea[0.75,0.1;7.25,9;;"..minetest.formspec_escape(text)..";]"..
|
||||
"button_exit[2.25,7.95;3,1;ok;"..minetest.formspec_escape(S("Done")).."]"
|
||||
local formspec = "size[8,9]" ..
|
||||
header ..
|
||||
"background[-0.5,-0.5;9,10;mcl_books_book_bg.png]" ..
|
||||
"textarea[0.75,0.1;7.25,9;;" .. minetest.formspec_escape(text) .. ";]" ..
|
||||
"button_exit[2.25,7.95;3,1;ok;" .. minetest.formspec_escape(S("Done")) .. "]"
|
||||
minetest.show_formspec(user:get_player_name(), "mcl_books:written_book", formspec)
|
||||
end
|
||||
|
||||
@ -125,16 +127,18 @@ minetest.register_craftitem("mcl_books:writable_book", {
|
||||
description = S("Book and Quill"),
|
||||
_tt_help = S("Write down some notes"),
|
||||
_doc_items_longdesc = S("This item can be used to write down some notes."),
|
||||
_doc_items_usagehelp = S("Hold it in the hand, then rightclick to read the current notes and edit then. You can edit the text as often as you like. You can also sign the book which turns it into a written book which you can stack, but it can't be edited anymore.").."\n"..
|
||||
_doc_items_usagehelp = S(
|
||||
"Hold it in the hand, then rightclick to read the current notes and edit then. You can edit the text as often as you like. You can also sign the book which turns it into a written book which you can stack, but it can't be edited anymore.")
|
||||
.. "\n" ..
|
||||
S("A book can hold up to 4500 characters. The title length is limited to 64 characters."),
|
||||
inventory_image = "mcl_books_book_writable.png",
|
||||
groups = { book=1 },
|
||||
groups = { book = 1 },
|
||||
stack_max = 1,
|
||||
on_place = write,
|
||||
on_secondary_use = write,
|
||||
})
|
||||
|
||||
minetest.register_on_player_receive_fields(function ( player, formname, fields )
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if ((formname == "mcl_books:writable_book") and fields and fields.text) then
|
||||
local stack = player:get_wielded_item()
|
||||
if (stack:get_name() and (stack:get_name() == "mcl_books:writable_book")) then
|
||||
@ -148,14 +152,17 @@ minetest.register_on_player_receive_fields(function ( player, formname, fields )
|
||||
player:set_wielded_item(stack)
|
||||
|
||||
local name = player:get_player_name()
|
||||
local formspec = "size[8,9]"..
|
||||
header..
|
||||
"background[-0.5,-0.5;9,10;mcl_books_book_bg.png]"..
|
||||
"field[0.75,1;7.25,1;title;"..minetest.formspec_escape(minetest.colorize("#000000", S("Enter book title:")))..";]"..
|
||||
"label[0.75,1.5;"..minetest.formspec_escape(minetest.colorize("#404040", S("by @1", name))).."]"..
|
||||
"button_exit[0.75,7.95;3,1;sign;"..minetest.formspec_escape(S("Sign and Close")).."]"..
|
||||
"tooltip[sign;"..minetest.formspec_escape(S("Note: The book will no longer be editable after signing")).."]"..
|
||||
"button[4.25,7.95;3,1;cancel;"..minetest.formspec_escape(S("Cancel")).."]"
|
||||
local formspec = "size[8,9]" ..
|
||||
header ..
|
||||
"background[-0.5,-0.5;9,10;mcl_books_book_bg.png]" ..
|
||||
"field[0.75,1;7.25,1;title;" ..
|
||||
minetest.formspec_escape(minetest.colorize("#000000", S("Enter book title:"))) .. ";]" ..
|
||||
"label[0.75,1.5;" ..
|
||||
minetest.formspec_escape(minetest.colorize("#404040", S("by @1", name))) .. "]" ..
|
||||
"button_exit[0.75,7.95;3,1;sign;" .. minetest.formspec_escape(S("Sign and Close")) .. "]" ..
|
||||
"tooltip[sign;" ..
|
||||
minetest.formspec_escape(S("Note: The book will no longer be editable after signing")) .. "]" ..
|
||||
"button[4.25,7.95;3,1;cancel;" .. minetest.formspec_escape(S("Cancel")) .. "]"
|
||||
minetest.show_formspec(player:get_player_name(), "mcl_books:signing", formspec)
|
||||
end
|
||||
end
|
||||
@ -181,7 +188,7 @@ minetest.register_on_player_receive_fields(function ( player, formname, fields )
|
||||
|
||||
player:set_wielded_item(newbook)
|
||||
else
|
||||
minetest.log("error", "[mcl_books] "..name.." failed to sign a book!")
|
||||
minetest.log("error", "[mcl_books] " .. name .. " failed to sign a book!")
|
||||
end
|
||||
elseif ((formname == "mcl_books:signing") and fields and fields.cancel) then
|
||||
local book = player:get_wielded_item()
|
||||
@ -202,12 +209,16 @@ end
|
||||
-- Written Book
|
||||
minetest.register_craftitem("mcl_books:written_book", {
|
||||
description = S("Written Book"),
|
||||
_doc_items_longdesc = S("Written books contain some text written by someone. They can be read and copied, but not edited."),
|
||||
_doc_items_usagehelp = S("Hold it in your hand, then rightclick to read the book.").."\n\n"..
|
||||
|
||||
S("To copy the text of the written book, place it into the crafting grid together with a book and quill (or multiple of those) and craft. The written book will not be consumed. Copies of copies can not be copied."),
|
||||
_doc_items_longdesc = S(
|
||||
"Written books contain some text written by someone. They can be read and copied, but not edited."
|
||||
),
|
||||
_doc_items_usagehelp = S("Hold it in your hand, then rightclick to read the book.") ..
|
||||
"\n\n" ..
|
||||
S(
|
||||
"To copy the text of the written book, place it into the crafting grid together with a book and quill (or multiple of those) and craft. The written book will not be consumed. Copies of copies can not be copied."
|
||||
),
|
||||
inventory_image = "mcl_books_book_written.png",
|
||||
groups = { not_in_creative_inventory=1, book=1, no_rename=1 },
|
||||
groups = { not_in_creative_inventory = 1, book = 1, no_rename = 1 },
|
||||
stack_max = 16,
|
||||
on_place = read,
|
||||
on_secondary_use = read
|
||||
@ -219,19 +230,19 @@ S("To copy the text of the written book, place it into the crafting grid togethe
|
||||
local baq = "mcl_books:writable_book"
|
||||
local wb = "mcl_books:written_book"
|
||||
local recipes = {
|
||||
{wb, baq},
|
||||
{baq, baq, wb},
|
||||
{baq, baq, wb, baq},
|
||||
{baq, baq, baq, baq, wb},
|
||||
{baq, baq, baq, baq, wb, baq},
|
||||
{baq, baq, baq, baq, wb, baq, baq},
|
||||
{baq, baq, baq, baq, wb, baq, baq, baq},
|
||||
{baq, baq, baq, baq, wb, baq, baq, baq, baq},
|
||||
{ wb, baq },
|
||||
{ baq, baq, wb },
|
||||
{ baq, baq, wb, baq },
|
||||
{ baq, baq, baq, baq, wb },
|
||||
{ baq, baq, baq, baq, wb, baq },
|
||||
{ baq, baq, baq, baq, wb, baq, baq },
|
||||
{ baq, baq, baq, baq, wb, baq, baq, baq },
|
||||
{ baq, baq, baq, baq, wb, baq, baq, baq, baq },
|
||||
}
|
||||
for r=#recipes, 1, -1 do
|
||||
for r = #recipes, 1, -1 do
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "mcl_books:written_book "..r,
|
||||
output = "mcl_books:written_book " .. r,
|
||||
recipe = recipes[r],
|
||||
})
|
||||
end
|
||||
@ -367,6 +378,9 @@ local function protection_check_put_take(pos, listname, index, stack, player)
|
||||
end
|
||||
end
|
||||
|
||||
---@param pos Vector
|
||||
---@param node node
|
||||
---@param clicker ObjectRef
|
||||
local function bookshelf_gui(pos, node, clicker)
|
||||
if not bookshelf_inv then return end
|
||||
local name = minetest.get_meta(pos):get_string("name")
|
||||
@ -378,18 +392,22 @@ local function bookshelf_gui(pos, node, clicker)
|
||||
local playername = clicker:get_player_name()
|
||||
|
||||
minetest.show_formspec(playername,
|
||||
"mcl_books:bookshelf_"..pos.x.."_"..pos.y.."_"..pos.z,
|
||||
"mcl_books:bookshelf_" .. pos.x .. "_" .. pos.y .. "_" .. pos.z,
|
||||
table.concat({
|
||||
"size[9,8.75]",
|
||||
"label[0,0;"..F(C("#313131", name)).."]",
|
||||
"list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0,0.5;9,3;]",
|
||||
mcl_formspec.get_itemslot_bg(0, 0.5, 9, 3),
|
||||
"label[0,4.0;"..F(C("#313131", S("Inventory"))).."]",
|
||||
"list[current_player;main;0,4.5;9,3;9]",
|
||||
mcl_formspec.get_itemslot_bg(0, 4.5, 9, 3),
|
||||
"list[current_player;main;0,7.74;9,1;]",
|
||||
mcl_formspec.get_itemslot_bg(0, 7.74, 9, 1),
|
||||
"listring[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main]",
|
||||
"formspec_version[4]",
|
||||
"size[11.75,10.425]",
|
||||
|
||||
"label[0.375,0.375;" .. F(C(mcl_formspec.label_color, name)) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 0.75, 9, 3),
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 0.75, 9, 3, 0, "mcl_book_book_empty_slot.png"),
|
||||
"list[nodemeta:" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ";main;0.375,0.75;9,3;]",
|
||||
"label[0.375,4.7;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3),
|
||||
"list[current_player;main;0.375,5.1;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1),
|
||||
"list[current_player;main;0.375,9.05;9,1;]",
|
||||
"listring[nodemeta:" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ";main]",
|
||||
"listring[current_player;main]",
|
||||
})
|
||||
)
|
||||
@ -397,7 +415,7 @@ end
|
||||
|
||||
local function close_forms(pos)
|
||||
local players = minetest.get_connected_players()
|
||||
local formname = "mcl_books:bookshelf_"..pos.x.."_"..pos.y.."_"..pos.z
|
||||
local formname = "mcl_books:bookshelf_" .. pos.x .. "_" .. pos.y .. "_" .. pos.z
|
||||
for p = 1, #players do
|
||||
if vector.distance(players[p]:get_pos(), pos) <= 30 then
|
||||
minetest.close_formspec(players[p]:get_player_name(), formname)
|
||||
@ -409,12 +427,18 @@ end
|
||||
minetest.register_node("mcl_books:bookshelf", {
|
||||
description = S("Bookshelf"),
|
||||
_doc_items_longdesc = S("Bookshelves are used for decoration."),
|
||||
tiles = {"mcl_books_bookshelf_top.png", "mcl_books_bookshelf_top.png", "default_bookshelf.png"},
|
||||
tiles = { "mcl_books_bookshelf_top.png", "mcl_books_bookshelf_top.png", "default_bookshelf.png" },
|
||||
stack_max = 64,
|
||||
is_ground_content = false,
|
||||
groups = {
|
||||
handy=1, axey=1, deco_block=1, material_wood=1,
|
||||
flammable=3, fire_encouragement=30, fire_flammability=20, container=1
|
||||
handy = 1,
|
||||
axey = 1,
|
||||
deco_block = 1,
|
||||
material_wood = 1,
|
||||
flammable = 3,
|
||||
fire_encouragement = 30,
|
||||
fire_flammability = 20,
|
||||
container = 1
|
||||
},
|
||||
drop = "mcl_books:book 3",
|
||||
sounds = wood_sound,
|
||||
@ -424,7 +448,7 @@ minetest.register_node("mcl_books:bookshelf", {
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size("main", 9*3)
|
||||
inv:set_size("main", 9 * 3)
|
||||
end,
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
minetest.get_meta(pos):set_string("name", itemstack:get_meta():get_string("name"))
|
||||
@ -433,16 +457,16 @@ minetest.register_node("mcl_books:bookshelf", {
|
||||
allow_metadata_inventory_take = protection_check_put_take,
|
||||
allow_metadata_inventory_put = protection_check_put_take,
|
||||
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
minetest.log("action", player:get_player_name()..
|
||||
" moves stuff in bookshelf at "..minetest.pos_to_string(pos))
|
||||
minetest.log("action", player:get_player_name() ..
|
||||
" moves stuff in bookshelf at " .. minetest.pos_to_string(pos))
|
||||
end,
|
||||
on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
minetest.log("action", player:get_player_name()..
|
||||
" moves stuff to bookshelf at "..minetest.pos_to_string(pos))
|
||||
minetest.log("action", player:get_player_name() ..
|
||||
" moves stuff to bookshelf at " .. minetest.pos_to_string(pos))
|
||||
end,
|
||||
on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
minetest.log("action", player:get_player_name()..
|
||||
" takes stuff from bookshelf at "..minetest.pos_to_string(pos))
|
||||
minetest.log("action", player:get_player_name() ..
|
||||
" takes stuff from bookshelf at " .. minetest.pos_to_string(pos))
|
||||
end,
|
||||
after_dig_node = drop_content,
|
||||
on_blast = on_blast,
|
||||
@ -453,9 +477,9 @@ minetest.register_node("mcl_books:bookshelf", {
|
||||
minetest.register_craft({
|
||||
output = "mcl_books:bookshelf",
|
||||
recipe = {
|
||||
{"group:wood", "group:wood", "group:wood"},
|
||||
{"mcl_books:book", "mcl_books:book", "mcl_books:book"},
|
||||
{"group:wood", "group:wood", "group:wood"},
|
||||
{ "group:wood", "group:wood", "group:wood" },
|
||||
{ "mcl_books:book", "mcl_books:book", "mcl_books:book" },
|
||||
{ "group:wood", "group:wood", "group:wood" },
|
||||
}
|
||||
})
|
||||
|
||||
@ -464,4 +488,3 @@ minetest.register_craft({
|
||||
recipe = "mcl_books:bookshelf",
|
||||
burntime = 15,
|
||||
})
|
||||
|
||||
|
@ -1,34 +1,51 @@
|
||||
---@diagnostic disable lowercase-global
|
||||
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
local formspec_escape = minetest.formspec_escape
|
||||
local show_formspec = minetest.show_formspec
|
||||
local F = minetest.formspec_escape
|
||||
local C = minetest.colorize
|
||||
local text_color = "#313131"
|
||||
local itemslot_bg = mcl_formspec.get_itemslot_bg
|
||||
local show_formspec = minetest.show_formspec
|
||||
|
||||
mcl_crafting_table = {}
|
||||
|
||||
function mcl_crafting_table.show_crafting_form(player)
|
||||
player:get_inventory():set_width("craft", 3)
|
||||
player:get_inventory():set_size("craft", 9)
|
||||
mcl_crafting_table.formspec = table.concat({
|
||||
"formspec_version[4]",
|
||||
"size[11.75,10.425]",
|
||||
|
||||
show_formspec(player:get_player_name(), "main",
|
||||
"size[9,8.75]"..
|
||||
"image[4.7,1.5;1.5,1;gui_crafting_arrow.png]"..
|
||||
"label[0,4;"..formspec_escape(C(text_color, S("Inventory"))).."]"..
|
||||
"list[current_player;main;0,4.5;9,3;9]"..
|
||||
itemslot_bg(0,4.5,9,3)..
|
||||
"list[current_player;main;0,7.74;9,1;]"..
|
||||
itemslot_bg(0,7.74,9,1)..
|
||||
"label[1.75,0;"..formspec_escape(C(text_color, S("Crafting"))).."]"..
|
||||
"list[current_player;craft;1.75,0.5;3,3;]"..
|
||||
itemslot_bg(1.75,0.5,3,3)..
|
||||
"list[current_player;craftpreview;6.1,1.5;1,1;]"..
|
||||
itemslot_bg(6.1,1.5,1,1)..
|
||||
"image_button[0.75,1.5;1,1;craftguide_book.png;__mcl_craftguide;]"..
|
||||
"tooltip[__mcl_craftguide;"..formspec_escape(S("Recipe book")).."]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[current_player;craft]"
|
||||
)
|
||||
"label[2.25,0.375;" .. F(C(mcl_formspec.label_color, S("Crafting"))) .. "]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(2.25, 0.75, 3, 3),
|
||||
"list[current_player;craft;2.25,0.75;3,3;]",
|
||||
|
||||
"image[6.125,2;1.5,1;gui_crafting_arrow.png]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(8.2, 2, 1, 1, 0.2),
|
||||
"list[current_player;craftpreview;8.2,2;1,1;]",
|
||||
|
||||
"label[0.375,4.7;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3),
|
||||
"list[current_player;main;0.375,5.1;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1),
|
||||
"list[current_player;main;0.375,9.05;9,1;]",
|
||||
|
||||
"listring[current_player;craft]",
|
||||
"listring[current_player;main]",
|
||||
|
||||
--Crafting guide button
|
||||
"image_button[0.325,1.95;1.1,1.1;craftguide_book.png;__mcl_craftguide;]",
|
||||
"tooltip[__mcl_craftguide;" .. F(S("Recipe book")) .. "]",
|
||||
})
|
||||
|
||||
---@param player ObjectRef
|
||||
function mcl_crafting_table.show_crafting_form(player)
|
||||
local inv = player:get_inventory()
|
||||
if inv then
|
||||
inv:set_width("craft", 3)
|
||||
inv:set_size("craft", 9)
|
||||
end
|
||||
|
||||
show_formspec(player:get_player_name(), "main", mcl_crafting_table.formspec)
|
||||
end
|
||||
|
||||
minetest.register_node("mcl_crafting_table:crafting_table", {
|
||||
@ -38,10 +55,10 @@ minetest.register_node("mcl_crafting_table:crafting_table", {
|
||||
_doc_items_usagehelp = S("Rightclick the crafting table to access the 3×3 crafting grid."),
|
||||
_doc_items_hidden = false,
|
||||
is_ground_content = false,
|
||||
tiles = {"crafting_workbench_top.png", "default_wood.png", "crafting_workbench_side.png",
|
||||
"crafting_workbench_side.png", "crafting_workbench_front.png", "crafting_workbench_front.png"},
|
||||
tiles = { "crafting_workbench_top.png", "default_wood.png", "crafting_workbench_side.png",
|
||||
"crafting_workbench_side.png", "crafting_workbench_front.png", "crafting_workbench_front.png" },
|
||||
paramtype2 = "facedir",
|
||||
groups = {handy=1,axey=1, deco_block=1, material_wood=1,flammable=-1},
|
||||
groups = { handy = 1, axey = 1, deco_block = 1, material_wood = 1, flammable = -1 },
|
||||
on_rightclick = function(pos, node, player, itemstack)
|
||||
if not player:get_player_control().sneak then
|
||||
mcl_crafting_table.show_crafting_form(player)
|
||||
@ -55,9 +72,9 @@ minetest.register_node("mcl_crafting_table:crafting_table", {
|
||||
minetest.register_craft({
|
||||
output = "mcl_crafting_table:crafting_table",
|
||||
recipe = {
|
||||
{"group:wood", "group:wood"},
|
||||
{"group:wood", "group:wood"}
|
||||
}
|
||||
{ "group:wood", "group:wood" },
|
||||
{ "group:wood", "group:wood" }
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
|
@ -2,7 +2,8 @@ local S = minetest.get_translator(minetest.get_current_modname())
|
||||
local F = minetest.formspec_escape
|
||||
|
||||
function mcl_enchanting.is_book(itemname)
|
||||
return itemname == "mcl_books:book" or itemname == "mcl_enchanting:book_enchanted" or itemname == "mcl_books:book_enchanted"
|
||||
return itemname == "mcl_books:book" or itemname == "mcl_enchanting:book_enchanted" or
|
||||
itemname == "mcl_books:book_enchanted"
|
||||
end
|
||||
|
||||
function mcl_enchanting.get_enchantments(itemstack)
|
||||
@ -54,11 +55,13 @@ end
|
||||
|
||||
function mcl_enchanting.get_enchantment_description(enchantment, level)
|
||||
local enchantment_def = mcl_enchanting.enchantments[enchantment]
|
||||
return enchantment_def.name .. (enchantment_def.max_level == 1 and "" or " " .. mcl_enchanting.roman_numerals.toRoman(level))
|
||||
return enchantment_def.name ..
|
||||
(enchantment_def.max_level == 1 and "" or " " .. mcl_enchanting.roman_numerals.toRoman(level))
|
||||
end
|
||||
|
||||
function mcl_enchanting.get_colorized_enchantment_description(enchantment, level)
|
||||
return minetest.colorize(mcl_enchanting.enchantments[enchantment].curse and mcl_colors.RED or mcl_colors.GRAY, mcl_enchanting.get_enchantment_description(enchantment, level))
|
||||
return minetest.colorize(mcl_enchanting.enchantments[enchantment].curse and mcl_colors.RED or mcl_colors.GRAY,
|
||||
mcl_enchanting.get_enchantment_description(enchantment, level))
|
||||
end
|
||||
|
||||
function mcl_enchanting.get_enchanted_itemstring(itemname)
|
||||
@ -79,7 +82,8 @@ function mcl_enchanting.not_enchantable_on_enchanting_table(itemname)
|
||||
end
|
||||
|
||||
function mcl_enchanting.is_enchantable(itemname)
|
||||
return mcl_enchanting.get_enchantability(itemname) > 0 or mcl_enchanting.not_enchantable_on_enchanting_table(itemname)
|
||||
return mcl_enchanting.get_enchantability(itemname) > 0 or
|
||||
mcl_enchanting.not_enchantable_on_enchanting_table(itemname)
|
||||
end
|
||||
|
||||
function mcl_enchanting.can_enchant_freshly(itemname)
|
||||
@ -150,7 +154,8 @@ function mcl_enchanting.can_enchant(itemstack, enchantment, level)
|
||||
for incompatible in pairs(enchantment_def.incompatible) do
|
||||
local incompatible_level = item_enchantments[incompatible]
|
||||
if incompatible_level then
|
||||
return false, "incompatible", mcl_enchanting.get_enchantment_description(incompatible, incompatible_level)
|
||||
return false, "incompatible",
|
||||
mcl_enchanting.get_enchantment_description(incompatible, incompatible_level)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -169,7 +174,9 @@ function mcl_enchanting.combine(itemstack, combine_with)
|
||||
local itemname = itemstack:get_name()
|
||||
local combine_name = combine_with:get_name()
|
||||
local enchanted_itemname = mcl_enchanting.get_enchanted_itemstring(itemname)
|
||||
if not enchanted_itemname or enchanted_itemname ~= mcl_enchanting.get_enchanted_itemstring(combine_name) and not mcl_enchanting.is_book(combine_name) then
|
||||
if not enchanted_itemname or
|
||||
enchanted_itemname ~= mcl_enchanting.get_enchanted_itemstring(combine_name) and
|
||||
not mcl_enchanting.is_book(combine_name) then
|
||||
return false
|
||||
end
|
||||
local enchantments = mcl_enchanting.get_enchantments(itemstack)
|
||||
@ -267,7 +274,7 @@ function mcl_enchanting.initialize()
|
||||
for itemname, itemdef in pairs(minetest.registered_items) do
|
||||
if mcl_enchanting.can_enchant_freshly(itemname) and not mcl_enchanting.is_book(itemname) then
|
||||
local new_name = itemname .. "_enchanted"
|
||||
minetest.override_item(itemname, {_mcl_enchanting_enchanted_tool = new_name})
|
||||
minetest.override_item(itemname, { _mcl_enchanting_enchanted_tool = new_name })
|
||||
local new_def = table.copy(itemdef)
|
||||
new_def.inventory_image = itemdef.inventory_image .. mcl_enchanting.overlay
|
||||
if new_def.wield_image then
|
||||
@ -303,7 +310,7 @@ end
|
||||
function mcl_enchanting.random(pr, ...)
|
||||
local r = pr and pr:next(...) or math.random(...)
|
||||
|
||||
if pr and not ({...})[1] then
|
||||
if pr and not ({ ... })[1] then
|
||||
r = r / 32767
|
||||
end
|
||||
|
||||
@ -328,20 +335,24 @@ function mcl_enchanting.get_random_enchantment(itemstack, treasure, weighted, ex
|
||||
return #possible > 0 and possible[mcl_enchanting.random(pr, 1, #possible)]
|
||||
end
|
||||
|
||||
function mcl_enchanting.generate_random_enchantments(itemstack, enchantment_level, treasure, no_reduced_bonus_chance, ignore_already_enchanted, pr)
|
||||
function mcl_enchanting.generate_random_enchantments(itemstack, enchantment_level, treasure, no_reduced_bonus_chance,
|
||||
ignore_already_enchanted, pr)
|
||||
local itemname = itemstack:get_name()
|
||||
|
||||
if (not mcl_enchanting.can_enchant_freshly(itemname) and not ignore_already_enchanted) or mcl_enchanting.not_enchantable_on_enchanting_table(itemname) then
|
||||
if (not mcl_enchanting.can_enchant_freshly(itemname) and not ignore_already_enchanted) or
|
||||
mcl_enchanting.not_enchantable_on_enchanting_table(itemname) then
|
||||
return
|
||||
end
|
||||
|
||||
itemstack = ItemStack(itemstack)
|
||||
|
||||
local enchantability = minetest.get_item_group(itemname, "enchantability")
|
||||
enchantability = 1 + mcl_enchanting.random(pr, 0, math.floor(enchantability / 4)) + mcl_enchanting.random(pr, 0, math.floor(enchantability / 4))
|
||||
enchantability = 1 + mcl_enchanting.random(pr, 0, math.floor(enchantability / 4)) +
|
||||
mcl_enchanting.random(pr, 0, math.floor(enchantability / 4))
|
||||
|
||||
enchantment_level = enchantment_level + enchantability
|
||||
enchantment_level = enchantment_level + enchantment_level * (mcl_enchanting.random(pr) + mcl_enchanting.random(pr) - 1) * 0.15
|
||||
enchantment_level = enchantment_level +
|
||||
enchantment_level * (mcl_enchanting.random(pr) + mcl_enchanting.random(pr) - 1) * 0.15
|
||||
enchantment_level = math.max(math.floor(enchantment_level + 0.5), 1)
|
||||
|
||||
local enchantments = {}
|
||||
@ -387,7 +398,6 @@ function mcl_enchanting.generate_random_enchantments(itemstack, enchantment_leve
|
||||
enchantments[selected_enchantment] = enchantment_power
|
||||
mcl_enchanting.enchant(itemstack, selected_enchantment, enchantment_power)
|
||||
end
|
||||
|
||||
until not no_reduced_bonus_chance and mcl_enchanting.random(pr) >= (enchantment_level + 1) / 50
|
||||
|
||||
return enchantments, description
|
||||
@ -397,13 +407,15 @@ function mcl_enchanting.generate_random_enchantments_reliable(itemstack, enchant
|
||||
local enchantments
|
||||
|
||||
repeat
|
||||
enchantments = mcl_enchanting.generate_random_enchantments(itemstack, enchantment_level, treasure, no_reduced_bonus_chance, ignore_already_enchanted, pr)
|
||||
enchantments = mcl_enchanting.generate_random_enchantments(itemstack, enchantment_level, treasure,
|
||||
no_reduced_bonus_chance, ignore_already_enchanted, pr)
|
||||
until enchantments
|
||||
|
||||
return enchantments
|
||||
end
|
||||
|
||||
function mcl_enchanting.enchant_randomly(itemstack, enchantment_level, treasure, no_reduced_bonus_chance, ignore_already_enchanted, pr)
|
||||
function mcl_enchanting.enchant_randomly(itemstack, enchantment_level, treasure, no_reduced_bonus_chance,
|
||||
ignore_already_enchanted, pr)
|
||||
local enchantments = mcl_enchanting.generate_random_enchantments_reliable(itemstack, enchantment_level, treasure, no_reduced_bonus_chance, ignore_already_enchanted, pr)
|
||||
|
||||
mcl_enchanting.set_enchanted_itemstring(itemstack)
|
||||
@ -416,7 +428,8 @@ function mcl_enchanting.enchant_uniform_randomly(stack, exclude, pr)
|
||||
local enchantment = mcl_enchanting.get_random_enchantment(stack, true, false, exclude, pr)
|
||||
|
||||
if enchantment then
|
||||
mcl_enchanting.enchant(stack, enchantment, mcl_enchanting.random(pr, 1, mcl_enchanting.enchantments[enchantment].max_level))
|
||||
mcl_enchanting.enchant(stack, enchantment,
|
||||
mcl_enchanting.random(pr, 1, mcl_enchanting.enchantments[enchantment].max_level))
|
||||
end
|
||||
|
||||
return stack
|
||||
@ -426,7 +439,8 @@ function mcl_enchanting.get_random_glyph_row()
|
||||
local glyphs = ""
|
||||
local x = 1.3
|
||||
for i = 1, 9 do
|
||||
glyphs = glyphs .. "image[".. x .. ",0.1;0.5,0.5;mcl_enchanting_glyph_" .. math.random(18) .. ".png^[colorize:#675D49:255]"
|
||||
glyphs = glyphs ..
|
||||
"image[" .. x .. ",0.1;0.5,0.5;mcl_enchanting_glyph_" .. math.random(18) .. ".png^[colorize:#675D49:255]"
|
||||
x = x + 0.6
|
||||
end
|
||||
return glyphs
|
||||
@ -459,7 +473,7 @@ end
|
||||
function mcl_enchanting.get_table_slots(player, itemstack, num_bookshelves)
|
||||
local itemname = itemstack:get_name()
|
||||
if (not mcl_enchanting.can_enchant_freshly(itemname)) or mcl_enchanting.not_enchantable_on_enchanting_table(itemname) then
|
||||
return {false, false, false}
|
||||
return { false, false, false }
|
||||
end
|
||||
local meta = player:get_meta()
|
||||
local player_slots = minetest.deserialize(meta:get_string("mcl_enchanting:slots")) or {}
|
||||
@ -475,7 +489,7 @@ function mcl_enchanting.get_table_slots(player, itemstack, num_bookshelves)
|
||||
meta:set_string("mcl_enchanting:slots", minetest.serialize(player_slots))
|
||||
return player_bookshelves_item_slots
|
||||
else
|
||||
return {false, false, false}
|
||||
return { false, false, false }
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -491,28 +505,33 @@ function mcl_enchanting.show_enchanting_formspec(player)
|
||||
local inv = player:get_inventory()
|
||||
local num_bookshelves = meta:get_int("mcl_enchanting:num_bookshelves")
|
||||
local table_name = meta:get_string("mcl_enchanting:table_name")
|
||||
local formspec = ""
|
||||
.. "size[9.07,8.6;]"
|
||||
.. "formspec_version[3]"
|
||||
.. "label[0,0;" .. C("#313131") .. F(table_name) .. "]"
|
||||
.. mcl_formspec.get_itemslot_bg(0.2, 2.4, 1, 1)
|
||||
.. "list[current_player;enchanting_item;0.2,2.4;1,1]"
|
||||
.. mcl_formspec.get_itemslot_bg(1.1, 2.4, 1, 1)
|
||||
.. "image[1.1,2.4;1,1;mcl_enchanting_lapis_background.png]"
|
||||
.. "list[current_player;enchanting_lapis;1.1,2.4;1,1]"
|
||||
.. "label[0,4;" .. C("#313131") .. F(S("Inventory")).."]"
|
||||
.. mcl_formspec.get_itemslot_bg(0, 4.5, 9, 3)
|
||||
.. mcl_formspec.get_itemslot_bg(0, 7.74, 9, 1)
|
||||
.. "list[current_player;main;0,4.5;9,3;9]"
|
||||
.. "listring[current_player;enchanting_item]"
|
||||
.. "listring[current_player;main]"
|
||||
.. "listring[current_player;enchanting]"
|
||||
.. "listring[current_player;main]"
|
||||
.. "listring[current_player;enchanting_lapis]"
|
||||
.. "listring[current_player;main]"
|
||||
.. "list[current_player;main;0,7.74;9,1;]"
|
||||
.. "real_coordinates[true]"
|
||||
.. "image[3.15,0.6;7.6,4.1;mcl_enchanting_button_background.png]"
|
||||
|
||||
local formspec = table.concat({
|
||||
"formspec_version[4]",
|
||||
"size[11.75,10.425]",
|
||||
|
||||
"label[0.375,0.375;" .. F(C(mcl_formspec.label_color) .. table_name) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(1, 3.25, 1, 1),
|
||||
"list[current_player;enchanting_item;1,3.25;1,1]",
|
||||
mcl_formspec.get_itemslot_bg_v4(2.25, 3.25, 1, 1),
|
||||
"image[2.25,3.25;1,1;mcl_enchanting_lapis_background.png]",
|
||||
"list[current_player;enchanting_lapis;2.25,3.25;1,1]",
|
||||
"image[4.125,0.56;7.25,4.1;mcl_enchanting_button_background.png]",
|
||||
"label[0.375,4.7;" .. F(C(mcl_formspec.label_color) .. S("Inventory")) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3),
|
||||
"list[current_player;main;0.375,5.1;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1),
|
||||
"list[current_player;main;0.375,9.05;9,1;]",
|
||||
|
||||
"listring[current_player;enchanting_item]",
|
||||
"listring[current_player;main]",
|
||||
"listring[current_player;enchanting]",
|
||||
"listring[current_player;main]",
|
||||
"listring[current_player;enchanting_lapis]",
|
||||
"listring[current_player;main]",
|
||||
})
|
||||
|
||||
local itemstack = inv:get_stack("enchanting_item", 1)
|
||||
local player_levels = mcl_experience.get_level(player)
|
||||
local y = 0.65
|
||||
@ -520,24 +539,50 @@ function mcl_enchanting.show_enchanting_formspec(player)
|
||||
local table_slots = mcl_enchanting.get_table_slots(player, itemstack, num_bookshelves)
|
||||
for i, slot in ipairs(table_slots) do
|
||||
any_enchantment = any_enchantment or slot
|
||||
local enough_lapis = inv:contains_item("enchanting_lapis", ItemStack({name = "mcl_core:lapis", count = i}))
|
||||
local enough_lapis = inv:contains_item("enchanting_lapis", ItemStack({ name = "mcl_core:lapis", count = i }))
|
||||
local enough_levels = slot and slot.level_requirement <= player_levels
|
||||
local can_enchant = (slot and enough_lapis and enough_levels)
|
||||
local ending = (can_enchant and "" or "_off")
|
||||
local hover_ending = (can_enchant and "_hovered" or "_off")
|
||||
formspec = formspec
|
||||
.. "container[3.2," .. y .. "]"
|
||||
.. (slot and "tooltip[button_" .. i .. ";" .. C("#818181") .. ((slot.description and F(slot.description)) or "") .. " " .. C("#FFFFFF") .. " . . . ?\n\n" .. (enough_levels and C(enough_lapis and "#818181" or "#FC5454") .. F(S("@1 Lapis Lazuli", i)) .. "\n" .. C("#818181") .. F(S("@1 Enchantment Levels", i)) or C("#FC5454") .. F(S("Level requirement: @1", slot.level_requirement))) .. "]" or "")
|
||||
.. "style[button_" .. i .. ";bgimg=mcl_enchanting_button" .. ending .. ".png;bgimg_hovered=mcl_enchanting_button" .. hover_ending .. ".png;bgimg_pressed=mcl_enchanting_button" .. hover_ending .. ".png]"
|
||||
.. "button[0,0;7.5,1.3;button_" .. i .. ";]"
|
||||
.. "container[4.125," .. y .. "]"
|
||||
..
|
||||
(
|
||||
slot and
|
||||
"tooltip[button_" ..
|
||||
i ..
|
||||
";" ..
|
||||
C("#818181") ..
|
||||
((slot.description and F(slot.description)) or "") ..
|
||||
" " ..
|
||||
C("#FFFFFF") ..
|
||||
" . . . ?\n\n" ..
|
||||
(
|
||||
enough_levels and
|
||||
C(enough_lapis and "#818181" or "#FC5454") ..
|
||||
F(S("@1 Lapis Lazuli", i)) .. "\n" .. C("#818181") .. F(S("@1 Enchantment Levels", i)) or
|
||||
C("#FC5454") .. F(S("Level requirement: @1", slot.level_requirement))) .. "]" or "")
|
||||
..
|
||||
"style[button_" ..
|
||||
i ..
|
||||
";bgimg=mcl_enchanting_button" ..
|
||||
ending ..
|
||||
".png;bgimg_hovered=mcl_enchanting_button" ..
|
||||
hover_ending .. ".png;bgimg_pressed=mcl_enchanting_button" .. hover_ending .. ".png]"
|
||||
.. "button[0,0;7.25,1.3;button_" .. i .. ";]"
|
||||
.. (slot and "image[0,0;1.3,1.3;mcl_enchanting_number_" .. i .. ending .. ".png]" or "")
|
||||
.. (slot and "label[7.2,1.1;" .. C(can_enchant and "#80FF20" or "#407F10") .. slot.level_requirement .. "]" or "")
|
||||
.. (slot and "label[6.8,1;" .. C(can_enchant and "#80FF20" or "#407F10") .. slot.level_requirement .. "]" or "")
|
||||
.. (slot and slot.glyphs or "")
|
||||
.. "container_end[]"
|
||||
y = y + 1.35
|
||||
y = y + 1.3
|
||||
end
|
||||
formspec = formspec
|
||||
.. "image[" .. (any_enchantment and 0.58 or 1.15) .. ",1.2;" .. (any_enchantment and 2 or 0.87) .. ",1.43;mcl_enchanting_book_" .. (any_enchantment and "open" or "closed") .. ".png]"
|
||||
..
|
||||
"image[" ..
|
||||
(any_enchantment and 1.1 or 1.67) ..
|
||||
",1.2;" ..
|
||||
(any_enchantment and 2 or 0.87) ..
|
||||
",1.43;mcl_enchanting_book_" .. (any_enchantment and "open" or "closed") .. ".png]"
|
||||
minetest.show_formspec(name, "mcl_enchanting:table", formspec)
|
||||
end
|
||||
|
||||
@ -555,7 +600,7 @@ function mcl_enchanting.handle_formspec_fields(player, formname, fields)
|
||||
local meta = player:get_meta()
|
||||
local num_bookshelfes = meta:get_int("mcl_enchanting:num_bookshelves")
|
||||
local itemstack = inv:get_stack("enchanting_item", 1)
|
||||
local cost = ItemStack({name = "mcl_core:lapis", count = button_pressed})
|
||||
local cost = ItemStack({ name = "mcl_core:lapis", count = button_pressed })
|
||||
if not inv:contains_item("enchanting_lapis", cost) then
|
||||
return
|
||||
end
|
||||
@ -573,7 +618,7 @@ function mcl_enchanting.handle_formspec_fields(player, formname, fields)
|
||||
mcl_enchanting.set_enchanted_itemstring(itemstack)
|
||||
mcl_enchanting.set_enchantments(itemstack, slot.enchantments)
|
||||
inv:set_stack("enchanting_item", 1, itemstack)
|
||||
minetest.sound_play("mcl_enchanting_enchant", {to_player = name, gain = 5.0})
|
||||
minetest.sound_play("mcl_enchanting_enchant", { to_player = name, gain = 5.0 })
|
||||
mcl_enchanting.reset_table_slots(player)
|
||||
mcl_enchanting.show_enchanting_formspec(player)
|
||||
awards.unlock(player:get_player_name(), "mcl:enchanter")
|
||||
@ -603,7 +648,8 @@ function mcl_enchanting.is_enchanting_inventory_action(action, inventory, invent
|
||||
end
|
||||
|
||||
function mcl_enchanting.allow_inventory_action(player, action, inventory, inventory_info)
|
||||
local is_enchanting_action, do_limit = mcl_enchanting.is_enchanting_inventory_action(action, inventory, inventory_info)
|
||||
local is_enchanting_action, do_limit = mcl_enchanting.is_enchanting_inventory_action(action, inventory,
|
||||
inventory_info)
|
||||
if is_enchanting_action and do_limit then
|
||||
if action == "move" then
|
||||
local listname = inventory_info.to_list
|
||||
@ -645,13 +691,15 @@ function mcl_enchanting.on_inventory_action(player, action, inventory, inventory
|
||||
end
|
||||
|
||||
function mcl_enchanting.schedule_book_animation(self, anim)
|
||||
self.scheduled_anim = {timer = self.anim_length, anim = anim}
|
||||
self.scheduled_anim = { timer = self.anim_length, anim = anim }
|
||||
end
|
||||
|
||||
function mcl_enchanting.set_book_animation(self, anim)
|
||||
local anim_index = mcl_enchanting.book_animations[anim]
|
||||
local start, stop = mcl_enchanting.book_animation_steps[anim_index], mcl_enchanting.book_animation_steps[anim_index + 1]
|
||||
self.object:set_animation({x = start, y = stop}, mcl_enchanting.book_animation_speed, 0, mcl_enchanting.book_animation_loop[anim] or false)
|
||||
local start, stop = mcl_enchanting.book_animation_steps[anim_index],
|
||||
mcl_enchanting.book_animation_steps[anim_index + 1]
|
||||
self.object:set_animation({ x = start, y = stop }, mcl_enchanting.book_animation_speed, 0,
|
||||
mcl_enchanting.book_animation_loop[anim] or false)
|
||||
self.scheduled_anim = nil
|
||||
self.anim_length = (stop - start) / 40
|
||||
end
|
||||
@ -669,7 +717,7 @@ end
|
||||
function mcl_enchanting.look_at(self, pos2)
|
||||
local pos1 = self.object:get_pos()
|
||||
local vec = vector.subtract(pos1, pos2)
|
||||
local yaw = math.atan(vec.z / vec.x) - math.pi/2
|
||||
local yaw = math.atan(vec.z / vec.x) - math.pi / 2
|
||||
yaw = yaw + (pos1.x >= pos2.x and math.pi or 0)
|
||||
self.object:set_yaw(yaw + math.pi)
|
||||
end
|
||||
|
@ -1,5 +1,6 @@
|
||||
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
local C = minetest.colorize
|
||||
local F = minetest.formspec_escape
|
||||
|
||||
local LIGHT_ACTIVE_FURNACE = 13
|
||||
|
||||
@ -8,60 +9,82 @@ local LIGHT_ACTIVE_FURNACE = 13
|
||||
--
|
||||
|
||||
local function active_formspec(fuel_percent, item_percent)
|
||||
return "size[9,8.75]"..
|
||||
"label[0,4;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]"..
|
||||
"list[current_player;main;0,4.5;9,3;9]"..
|
||||
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
|
||||
"list[current_player;main;0,7.74;9,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(0,7.74,9,1)..
|
||||
"label[2.75,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Furnace"))).."]"..
|
||||
"list[context;src;2.75,0.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(2.75,0.5,1,1)..
|
||||
"list[context;fuel;2.75,2.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(2.75,2.5,1,1)..
|
||||
"list[context;dst;5.75,1.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(5.75,1.5,1,1)..
|
||||
"image[2.75,1.5;1,1;default_furnace_fire_bg.png^[lowpart:"..
|
||||
(100-fuel_percent)..":default_furnace_fire_fg.png]"..
|
||||
"image[4.1,1.5;1.5,1;gui_furnace_arrow_bg.png^[lowpart:"..
|
||||
(item_percent)..":gui_furnace_arrow_fg.png^[transformR270]"..
|
||||
return table.concat({
|
||||
"formspec_version[4]",
|
||||
"size[11.75,10.425]",
|
||||
"label[0.375,0.375;" .. F(C(mcl_formspec.label_color, S("Furnace"))) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(3.5, 0.75, 1, 1),
|
||||
"list[context;src;3.5,0.75;1,1;]",
|
||||
|
||||
"image[3.5,2;1,1;default_furnace_fire_bg.png^[lowpart:" ..
|
||||
(100 - fuel_percent) .. ":default_furnace_fire_fg.png]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(3.5, 3.25, 1, 1),
|
||||
"list[context;fuel;3.5,3.25;1,1;]",
|
||||
|
||||
"image[5.25,2;1.5,1;gui_furnace_arrow_bg.png^[lowpart:" ..
|
||||
(item_percent) .. ":gui_furnace_arrow_fg.png^[transformR270]",
|
||||
mcl_formspec.get_itemslot_bg_v4(7.875, 2, 1, 1, 0.2),
|
||||
"list[context;dst;7.875,2;1,1;]",
|
||||
|
||||
"label[0.375,4.7;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3),
|
||||
"list[current_player;main;0.375,5.1;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1),
|
||||
"list[current_player;main;0.375,9.05;9,1;]",
|
||||
|
||||
-- Craft guide button temporarily removed due to Minetest bug.
|
||||
-- TODO: Add it back when the Minetest bug is fixed.
|
||||
--"image_button[8,0;1,1;craftguide_book.png;craftguide;]"..
|
||||
--"tooltip[craftguide;"..minetest.formspec_escape(S("Recipe book")).."]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;fuel]"..
|
||||
"listring[current_player;main]"
|
||||
|
||||
"listring[context;dst]",
|
||||
"listring[current_player;main]",
|
||||
"listring[context;src]",
|
||||
"listring[current_player;main]",
|
||||
"listring[context;fuel]",
|
||||
"listring[current_player;main]",
|
||||
})
|
||||
end
|
||||
|
||||
local inactive_formspec = "size[9,8.75]"..
|
||||
"label[0,4;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]"..
|
||||
"list[current_player;main;0,4.5;9,3;9]"..
|
||||
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
|
||||
"list[current_player;main;0,7.74;9,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(0,7.74,9,1)..
|
||||
"label[2.75,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Furnace"))).."]"..
|
||||
"list[context;src;2.75,0.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(2.75,0.5,1,1)..
|
||||
"list[context;fuel;2.75,2.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(2.75,2.5,1,1)..
|
||||
"list[context;dst;5.75,1.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(5.75,1.5,1,1)..
|
||||
"image[2.75,1.5;1,1;default_furnace_fire_bg.png]"..
|
||||
"image[4.1,1.5;1.5,1;gui_furnace_arrow_bg.png^[transformR270]"..
|
||||
local inactive_formspec = table.concat({
|
||||
"formspec_version[4]",
|
||||
"size[11.75,10.425]",
|
||||
"label[0.375,0.375;" .. F(C(mcl_formspec.label_color, S("Furnace"))) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(3.5, 0.75, 1, 1),
|
||||
"list[context;src;3.5,0.75;1,1;]",
|
||||
|
||||
"image[3.5,2;1,1;default_furnace_fire_bg.png]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(3.5, 3.25, 1, 1),
|
||||
"list[context;fuel;3.5,3.25;1,1;]",
|
||||
|
||||
"image[5.25,2;1.5,1;gui_furnace_arrow_bg.png^[transformR270]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(7.875, 2, 1, 1, 0.2),
|
||||
"list[context;dst;7.875,2;1,1;]",
|
||||
|
||||
"label[0.375,4.7;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3),
|
||||
"list[current_player;main;0.375,5.1;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1),
|
||||
"list[current_player;main;0.375,9.05;9,1;]",
|
||||
|
||||
-- Craft guide button temporarily removed due to Minetest bug.
|
||||
-- TODO: Add it back when the Minetest bug is fixed.
|
||||
--"image_button[8,0;1,1;craftguide_book.png;craftguide;]"..
|
||||
--"tooltip[craftguide;"..minetest.formspec_escape(S("Recipe book")).."]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;fuel]"..
|
||||
"listring[current_player;main]"
|
||||
|
||||
"listring[context;dst]",
|
||||
"listring[current_player;main]",
|
||||
"listring[context;src]",
|
||||
"listring[current_player;main]",
|
||||
"listring[context;fuel]",
|
||||
"listring[current_player;main]",
|
||||
})
|
||||
|
||||
|
||||
local receive_fields = function(pos, formname, fields, sender)
|
||||
if fields.craftguide then
|
||||
@ -71,7 +94,7 @@ end
|
||||
|
||||
local function give_xp(pos, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local dir = vector.divide(minetest.facedir_to_dir(minetest.get_node(pos).param2),-1.95)
|
||||
local dir = vector.divide(minetest.facedir_to_dir(minetest.get_node(pos).param2), -1.95)
|
||||
local xp = meta:get_int("xp")
|
||||
if xp > 0 then
|
||||
if player then
|
||||
@ -108,7 +131,7 @@ local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
-- Test stack with size 1 because we burn one fuel at a time
|
||||
local teststack = ItemStack(stack)
|
||||
teststack:set_count(1)
|
||||
local output, decremented_input = minetest.get_craft_result({method="fuel", width=1, items={teststack}})
|
||||
local output, decremented_input = minetest.get_craft_result({ method = "fuel", width = 1, items = { teststack } })
|
||||
if output.time ~= 0 then
|
||||
-- Only allow to place 1 item if fuel get replaced by recipe.
|
||||
-- This is the case for lava buckets.
|
||||
@ -303,7 +326,7 @@ local function furnace_node_timer(pos, elapsed)
|
||||
|
||||
-- Check if we have cookable content: cookable
|
||||
local aftercooked
|
||||
cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
|
||||
cooked, aftercooked = minetest.get_craft_result({ method = "cooking", width = 1, items = srclist })
|
||||
cookable = cooked.time ~= 0
|
||||
if cookable then
|
||||
-- Successful cooking requires space in dst slot and time
|
||||
@ -321,7 +344,7 @@ local function furnace_node_timer(pos, elapsed)
|
||||
if cookable and not active then
|
||||
-- We need to get new fuel
|
||||
local afterfuel
|
||||
fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
|
||||
fuel, afterfuel = minetest.get_craft_result({ method = "fuel", width = 1, items = fuellist })
|
||||
|
||||
if fuel.time == 0 then
|
||||
-- No valid fuel in fuel list -- stop
|
||||
@ -440,10 +463,10 @@ minetest.register_node("mcl_furnaces:furnace", {
|
||||
_tt_help = S("Uses fuel to smelt or cook items"),
|
||||
_doc_items_longdesc = S("Furnaces cook or smelt several items, using a furnace fuel, into something else."),
|
||||
_doc_items_usagehelp =
|
||||
S("Use the furnace to open the furnace menu.").."\n"..
|
||||
S("Place a furnace fuel in the lower slot and the source material in the upper slot.").."\n"..
|
||||
S("The furnace will slowly use its fuel to smelt the item.").."\n"..
|
||||
S("The result will be placed into the output slot at the right side.").."\n"..
|
||||
S("Use the furnace to open the furnace menu.") .. "\n" ..
|
||||
S("Place a furnace fuel in the lower slot and the source material in the upper slot.") .. "\n" ..
|
||||
S("The furnace will slowly use its fuel to smelt the item.") .. "\n" ..
|
||||
S("The result will be placed into the output slot at the right side.") .. "\n" ..
|
||||
S("Use the recipe book to see what you can smelt, what you can use as fuel and how long it will burn."),
|
||||
_doc_items_hidden = false,
|
||||
tiles = {
|
||||
@ -452,7 +475,7 @@ minetest.register_node("mcl_furnaces:furnace", {
|
||||
"default_furnace_side.png", "default_furnace_front.png"
|
||||
},
|
||||
paramtype2 = "facedir",
|
||||
groups = {pickaxey=1, container=4, deco_block=1, material_stone=1},
|
||||
groups = { pickaxey = 1, container = 4, deco_block = 1, material_stone = 1 },
|
||||
is_ground_content = false,
|
||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
|
||||
@ -462,10 +485,11 @@ minetest.register_node("mcl_furnaces:furnace", {
|
||||
local meta2 = meta:to_table()
|
||||
meta:from_table(oldmetadata)
|
||||
local inv = meta:get_inventory()
|
||||
for _, listname in ipairs({"src", "dst", "fuel"}) do
|
||||
for _, listname in ipairs({ "src", "dst", "fuel" }) do
|
||||
local stack = inv:get_stack(listname, 1)
|
||||
if not stack:is_empty() then
|
||||
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5}
|
||||
local p = { x = pos.x + math.random(0, 10) / 10 - 0.5, y = pos.y,
|
||||
z = pos.z + math.random(0, 10) / 10 - 0.5 }
|
||||
minetest.add_item(p, stack)
|
||||
end
|
||||
end
|
||||
@ -528,7 +552,7 @@ minetest.register_node("mcl_furnaces:furnace_active", {
|
||||
paramtype = "light",
|
||||
light_source = LIGHT_ACTIVE_FURNACE,
|
||||
drop = "mcl_furnaces:furnace",
|
||||
groups = {pickaxey=1, container=4, deco_block=1, not_in_creative_inventory=1, material_stone=1},
|
||||
groups = { pickaxey = 1, container = 4, deco_block = 1, not_in_creative_inventory = 1, material_stone = 1 },
|
||||
is_ground_content = false,
|
||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
on_timer = furnace_node_timer,
|
||||
@ -538,10 +562,11 @@ minetest.register_node("mcl_furnaces:furnace_active", {
|
||||
local meta2 = meta
|
||||
meta:from_table(oldmetadata)
|
||||
local inv = meta:get_inventory()
|
||||
for _, listname in ipairs({"src", "dst", "fuel"}) do
|
||||
for _, listname in ipairs({ "src", "dst", "fuel" }) do
|
||||
local stack = inv:get_stack(listname, 1)
|
||||
if not stack:is_empty() then
|
||||
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5}
|
||||
local p = { x = pos.x + math.random(0, 10) / 10 - 0.5, y = pos.y,
|
||||
z = pos.z + math.random(0, 10) / 10 - 0.5 }
|
||||
minetest.add_item(p, stack)
|
||||
end
|
||||
end
|
||||
@ -586,7 +611,7 @@ end
|
||||
minetest.register_lbm({
|
||||
label = "Active furnace flame particles",
|
||||
name = "mcl_furnaces:flames",
|
||||
nodenames = {"mcl_furnaces:furnace_active"},
|
||||
nodenames = { "mcl_furnaces:furnace_active" },
|
||||
run_at_every_load = true,
|
||||
action = function(pos, node)
|
||||
spawn_flames(pos, node.param2)
|
||||
|
@ -1,31 +1,46 @@
|
||||
-- Code based from mcl_anvils
|
||||
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
local F = minetest.formspec_escape
|
||||
local C = minetest.colorize
|
||||
|
||||
local MAX_WEAR = 65535
|
||||
|
||||
-- formspecs
|
||||
local function get_grindstone_formspec()
|
||||
return "size[9,8.75]"..
|
||||
"image[3,1.5;1.5,1;gui_crafting_arrow.png]"..
|
||||
"label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]"..
|
||||
"label[1,0.1;"..minetest.formspec_escape(minetest.colorize("#313131", S("Repair & Disenchant"))).."]"..
|
||||
"list[context;main;0,0;8,4;]"..
|
||||
"list[current_player;main;0,4.5;9,3;9]"..
|
||||
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
|
||||
"list[current_player;main;0,7.74;9,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(0,7.74,9,1)..
|
||||
"list[context;input;1,1;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(1,1,1,1)..
|
||||
"list[context;input;1,2;1,1;1]"..
|
||||
mcl_formspec.get_itemslot_bg(1,2,1,1)..
|
||||
"list[context;output;6,1.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(6,1.5,1,1)..
|
||||
"listring[context;output]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;input]"..
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
local grindstone_formspec = table.concat({
|
||||
"formspec_version[6]",
|
||||
"size[11.75,10.425]",
|
||||
|
||||
"label[0.375,0.375;" .. F(C(mcl_formspec.label_color, S("Repair & Disenchant"))) .. "]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(2.875, 1.25, 1, 1),
|
||||
"list[context;input;2.875,1.25;1,1;]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(2.875, 2.625, 1, 1),
|
||||
"list[context;input;2.875,2.625;1,1;1]",
|
||||
|
||||
"image[2.375,1;2,2.875;grindstone_gui_9.png;2]",
|
||||
|
||||
"image[1.875,1.5;0.5,2.875;grindstone_gui_9.png;2]",
|
||||
"image[4.375,1.5;0.5,2.875;grindstone_gui_9.png;2]",
|
||||
|
||||
"image[5.5,1.95;1.5,1;gui_crafting_arrow.png]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(7.875, 1.9375, 1, 1),
|
||||
"list[context;output;7.875,1.9375;1,1;]",
|
||||
|
||||
"label[0.375,4.7;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3),
|
||||
"list[current_player;main;0.375,5.1;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1),
|
||||
"list[current_player;main;0.375,9.05;9,1;]",
|
||||
|
||||
"listring[context;output]",
|
||||
"listring[current_player;main]",
|
||||
"listring[context;input]",
|
||||
"listring[current_player;main]",
|
||||
})
|
||||
|
||||
-- Creates a new item with the wear of the items and custom name
|
||||
local function create_new_item(name_item, meta, wear)
|
||||
@ -86,7 +101,6 @@ local function fix_stack_size(stack)
|
||||
return count
|
||||
end
|
||||
|
||||
|
||||
-- Update the inventory slots of an grindstone node.
|
||||
-- meta: Metadata of grindstone node
|
||||
local function update_grindstone_slots(meta)
|
||||
@ -168,10 +182,10 @@ end
|
||||
-- Drop any items inside the grindstone if destroyed
|
||||
local function drop_grindstone_items(pos, meta)
|
||||
local inv = meta:get_inventory()
|
||||
for i=1, inv:get_size("input") do
|
||||
for i = 1, inv:get_size("input") do
|
||||
local stack = inv:get_stack("input", i)
|
||||
if not stack:is_empty() then
|
||||
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5}
|
||||
local p = { x = pos.x + math.random(0, 10) / 10 - 0.5, y = pos.y, z = pos.z + math.random(0, 10) / 10 - 0.5 }
|
||||
minetest.add_item(p, stack)
|
||||
end
|
||||
end
|
||||
@ -181,11 +195,11 @@ local node_box = {
|
||||
type = "fixed",
|
||||
-- created with nodebox editor
|
||||
fixed = {
|
||||
{-0.25, -0.25, -0.375, 0.25, 0.5, 0.375},
|
||||
{-0.375, -0.0625, -0.1875, -0.25, 0.3125, 0.1875},
|
||||
{0.25, -0.0625, -0.1875, 0.375, 0.3125, 0.1875},
|
||||
{0.25, -0.5, -0.125, 0.375, -0.0625, 0.125},
|
||||
{-0.375, -0.5, -0.125, -0.25, -0.0625, 0.125},
|
||||
{ -0.25, -0.25, -0.375, 0.25, 0.5, 0.375 },
|
||||
{ -0.375, -0.0625, -0.1875, -0.25, 0.3125, 0.1875 },
|
||||
{ 0.25, -0.0625, -0.1875, 0.375, 0.3125, 0.1875 },
|
||||
{ 0.25, -0.5, -0.125, 0.375, -0.0625, 0.125 },
|
||||
{ -0.375, -0.5, -0.125, -0.25, -0.0625, 0.125 },
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,10 +207,10 @@ minetest.register_node("mcl_grindstone:grindstone", {
|
||||
description = S("Grindstone"),
|
||||
_tt_help = S("Used to disenchant/fix tools"),
|
||||
_doc_items_longdesc = S("Grindstone disenchants tools and armour except for curses, and repairs two items of the same type it is also the weapon smith's work station."),
|
||||
_doc_items_usagehelp = S("To use the grindstone, rightclick it, Two input slots (on the left) and a single output slot.").."\n"..
|
||||
S("To disenchant an item place enchanted item in one of the input slots and take the disenchanted item from the output.").."\n"..
|
||||
S("To repair a tool you need a tool of the same type and material, put both items in the input slot and the output slot will combine two items durabilities with 5% bonus.").."\n"..
|
||||
S("If both items have enchantments the player will get xp from both items from the disenchant.").."\n"..
|
||||
_doc_items_usagehelp = S("To use the grindstone, rightclick it, Two input slots (on the left) and a single output slot.") .. "\n" ..
|
||||
S("To disenchant an item place enchanted item in one of the input slots and take the disenchanted item from the output.") .. "\n" ..
|
||||
S("To repair a tool you need a tool of the same type and material, put both items in the input slot and the output slot will combine two items durabilities with 5% bonus.") .. "\n" ..
|
||||
S("If both items have enchantments the player will get xp from both items from the disenchant.") .. "\n" ..
|
||||
S("Curses cannot be removed and will be transfered to the new repaired item, if both items have a different curse the curses will be combined."),
|
||||
tiles = {
|
||||
"grindstone_top.png",
|
||||
@ -212,7 +226,7 @@ minetest.register_node("mcl_grindstone:grindstone", {
|
||||
selection_box = node_box,
|
||||
collision_box = node_box,
|
||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
groups = {pickaxey = 1, deco_block = 1},
|
||||
groups = { pickaxey = 1, deco_block = 1 },
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
local meta = minetest.get_meta(pos)
|
||||
@ -268,7 +282,7 @@ minetest.register_node("mcl_grindstone:grindstone", {
|
||||
local meta = minetest.get_meta(pos)
|
||||
if from_list == "output" and to_list == "input" then
|
||||
local inv = meta:get_inventory()
|
||||
for i=1, inv:get_size("input") do
|
||||
for i = 1, inv:get_size("input") do
|
||||
if i ~= to_index then
|
||||
local istack = inv:get_stack("input", i)
|
||||
istack:set_count(math.max(0, istack:get_count() - count))
|
||||
@ -289,8 +303,8 @@ minetest.register_node("mcl_grindstone:grindstone", {
|
||||
if not input1:is_empty() and not input2:is_empty() then
|
||||
-- Get xp earnt from the enchanted items
|
||||
xp_earnt = calculate_xp(input1) + calculate_xp(input1)
|
||||
input1:take_item()
|
||||
input2:take_item()
|
||||
input1:take_item(1)
|
||||
input2:take_item(1)
|
||||
inv:set_stack("input", 1, input1)
|
||||
inv:set_stack("input", 2, input2)
|
||||
else
|
||||
@ -320,14 +334,13 @@ minetest.register_node("mcl_grindstone:grindstone", {
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size("input", 2)
|
||||
inv:set_size("output", 1)
|
||||
local form = get_grindstone_formspec()
|
||||
meta:set_string("formspec", form)
|
||||
meta:set_string("formspec", grindstone_formspec)
|
||||
end,
|
||||
on_rightclick = function(pos, node, player, itemstack)
|
||||
if not player:get_player_control().sneak then
|
||||
local meta = minetest.get_meta(pos)
|
||||
update_grindstone_slots(meta)
|
||||
meta:set_string("formspec", get_grindstone_formspec())
|
||||
meta:set_string("formspec", grindstone_formspec)
|
||||
end
|
||||
end,
|
||||
_mcl_blast_resistance = 6,
|
||||
@ -337,7 +350,7 @@ minetest.register_node("mcl_grindstone:grindstone", {
|
||||
minetest.register_craft({
|
||||
output = "mcl_grindstone:grindstone",
|
||||
recipe = {
|
||||
{ "mcl_core:stick", "mcl_stairs:slab_stone_rough", "mcl_core:stick"},
|
||||
{ "group:wood", "", "group:wood"},
|
||||
{ "mcl_core:stick", "mcl_stairs:slab_stone_rough", "mcl_core:stick" },
|
||||
{ "group:wood", "", "group:wood" },
|
||||
}
|
||||
})
|
||||
|
@ -12,15 +12,22 @@ end
|
||||
--[[ BEGIN OF NODE DEFINITIONS ]]
|
||||
|
||||
local mcl_hoppers_formspec = table.concat({
|
||||
"size[9,7]",
|
||||
"label[2,0;" .. F(C("#313131", S("Hopper"))) .. "]",
|
||||
"list[context;main;2,0.5;5,1;]",
|
||||
mcl_formspec.get_itemslot_bg(2, 0.5, 5, 1),
|
||||
"label[0,2;" .. F(C("#313131", S("Inventory"))) .. "]",
|
||||
"list[current_player;main;0,2.5;9,3;9]",
|
||||
mcl_formspec.get_itemslot_bg(0, 2.5, 9, 3),
|
||||
"list[current_player;main;0,5.74;9,1;]",
|
||||
mcl_formspec.get_itemslot_bg(0, 5.74, 9, 1),
|
||||
"formspec_version[4]",
|
||||
"size[11.75,8.175]",
|
||||
|
||||
"label[0.375,0.375;" .. F(C(mcl_formspec.label_color, S("Hopper"))) .. "]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(2.875, 0.75, 5, 1),
|
||||
"list[context;main;2.875,0.75;5,1;]",
|
||||
|
||||
"label[0.375,2.45;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 2.85, 9, 3),
|
||||
"list[current_player;main;0.375,2.85;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 6.8, 9, 1),
|
||||
"list[current_player;main;0.375,6.8;9,1;]",
|
||||
|
||||
"listring[context;main]",
|
||||
"listring[current_player;main]",
|
||||
})
|
||||
@ -31,7 +38,7 @@ local mcl_hoppers_formspec = table.concat({
|
||||
local def_hopper = {
|
||||
inventory_image = "mcl_hoppers_item.png",
|
||||
wield_image = "mcl_hoppers_item.png",
|
||||
groups = {pickaxey = 1, container = 2, deco_block = 1, hopper = 1},
|
||||
groups = { pickaxey = 1, container = 2, deco_block = 1, hopper = 1 },
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
-- FIXME: mcl_hoppers_hopper_inside.png is unused by hoppers.
|
||||
@ -47,25 +54,25 @@ local def_hopper = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
--funnel walls
|
||||
{-0.5, 0.0, 0.4, 0.5, 0.5, 0.5},
|
||||
{0.4, 0.0, -0.5, 0.5, 0.5, 0.5},
|
||||
{-0.5, 0.0, -0.5, -0.4, 0.5, 0.5},
|
||||
{-0.5, 0.0, -0.5, 0.5, 0.5, -0.4},
|
||||
{ -0.5, 0.0, 0.4, 0.5, 0.5, 0.5 },
|
||||
{ 0.4, 0.0, -0.5, 0.5, 0.5, 0.5 },
|
||||
{ -0.5, 0.0, -0.5, -0.4, 0.5, 0.5 },
|
||||
{ -0.5, 0.0, -0.5, 0.5, 0.5, -0.4 },
|
||||
--funnel base
|
||||
{-0.5, 0.0, -0.5, 0.5, 0.1, 0.5},
|
||||
{ -0.5, 0.0, -0.5, 0.5, 0.1, 0.5 },
|
||||
--spout
|
||||
{-0.3, -0.3, -0.3, 0.3, 0.0, 0.3},
|
||||
{-0.1, -0.3, -0.1, 0.1, -0.5, 0.1},
|
||||
{ -0.3, -0.3, -0.3, 0.3, 0.0, 0.3 },
|
||||
{ -0.1, -0.3, -0.1, 0.1, -0.5, 0.1 },
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
--funnel
|
||||
{-0.5, 0.0, -0.5, 0.5, 0.5, 0.5},
|
||||
{ -0.5, 0.0, -0.5, 0.5, 0.5, 0.5 },
|
||||
--spout
|
||||
{-0.3, -0.3, -0.3, 0.3, 0.0, 0.3},
|
||||
{-0.1, -0.3, -0.1, 0.1, -0.5, 0.1},
|
||||
{ -0.3, -0.3, -0.3, 0.3, 0.0, 0.3 },
|
||||
{ -0.1, -0.3, -0.1, 0.1, -0.5, 0.1 },
|
||||
},
|
||||
},
|
||||
is_ground_content = false,
|
||||
@ -248,25 +255,25 @@ local def_hopper_side = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
--funnel walls
|
||||
{-0.5, 0.0, 0.4, 0.5, 0.5, 0.5},
|
||||
{0.4, 0.0, -0.5, 0.5, 0.5, 0.5},
|
||||
{-0.5, 0.0, -0.5, -0.4, 0.5, 0.5},
|
||||
{-0.5, 0.0, -0.5, 0.5, 0.5, -0.4},
|
||||
{ -0.5, 0.0, 0.4, 0.5, 0.5, 0.5 },
|
||||
{ 0.4, 0.0, -0.5, 0.5, 0.5, 0.5 },
|
||||
{ -0.5, 0.0, -0.5, -0.4, 0.5, 0.5 },
|
||||
{ -0.5, 0.0, -0.5, 0.5, 0.5, -0.4 },
|
||||
--funnel base
|
||||
{-0.5, 0.0, -0.5, 0.5, 0.1, 0.5},
|
||||
{ -0.5, 0.0, -0.5, 0.5, 0.1, 0.5 },
|
||||
--spout
|
||||
{-0.3, -0.3, -0.3, 0.3, 0.0, 0.3},
|
||||
{-0.5, -0.3, -0.1, 0.1, -0.1, 0.1},
|
||||
{ -0.3, -0.3, -0.3, 0.3, 0.0, 0.3 },
|
||||
{ -0.5, -0.3, -0.1, 0.1, -0.1, 0.1 },
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
--funnel
|
||||
{-0.5, 0.0, -0.5, 0.5, 0.5, 0.5},
|
||||
{ -0.5, 0.0, -0.5, 0.5, 0.5, 0.5 },
|
||||
--spout
|
||||
{-0.3, -0.3, -0.3, 0.3, 0.0, 0.3},
|
||||
{-0.5, -0.3, -0.1, 0.1, -0.1, 0.1},
|
||||
{ -0.3, -0.3, -0.3, 0.3, 0.0, 0.3 },
|
||||
{ -0.5, -0.3, -0.1, 0.1, -0.1, 0.1 },
|
||||
},
|
||||
},
|
||||
is_ground_content = false,
|
||||
@ -559,8 +566,8 @@ end
|
||||
|
||||
minetest.register_abm({
|
||||
label = "Hopper/container item exchange",
|
||||
nodenames = {"mcl_hoppers:hopper"},
|
||||
neighbors = {"group:container"},
|
||||
nodenames = { "mcl_hoppers:hopper" },
|
||||
neighbors = { "group:container" },
|
||||
interval = 1.0,
|
||||
chance = 1,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
@ -591,8 +598,8 @@ minetest.register_abm({
|
||||
|
||||
minetest.register_abm({
|
||||
label = "Side-hopper/container item exchange",
|
||||
nodenames = {"mcl_hoppers:hopper_side"},
|
||||
neighbors = {"group:container"},
|
||||
nodenames = { "mcl_hoppers:hopper_side" },
|
||||
neighbors = { "group:container" },
|
||||
interval = 1.0,
|
||||
chance = 1,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
|
@ -1,11 +1,13 @@
|
||||
--[[
|
||||
By EliasFleckenstein03 and Code-Sploit
|
||||
]]
|
||||
-- By EliasFleckenstein03 and Code-Sploit
|
||||
|
||||
local S = minetest.get_translator("mcl_smithing_table")
|
||||
local F = minetest.formspec_escape
|
||||
local C = minetest.colorize
|
||||
|
||||
mcl_smithing_table = {}
|
||||
|
||||
-- Function to upgrade diamond tool/armor to netherite tool/armor
|
||||
---Function to upgrade diamond tool/armor to netherite tool/armor
|
||||
---@param itemstack ItemStack
|
||||
function mcl_smithing_table.upgrade_item(itemstack)
|
||||
local def = itemstack:get_definition()
|
||||
|
||||
@ -29,28 +31,48 @@ function mcl_smithing_table.upgrade_item(itemstack)
|
||||
return itemstack
|
||||
end
|
||||
|
||||
-- Badly copied over from mcl_anvils
|
||||
-- ToDo: Make better formspec
|
||||
local formspec = table.concat({
|
||||
"formspec_version[4]",
|
||||
"size[11.75,10.425]",
|
||||
|
||||
local formspec = "size[9,9]" ..
|
||||
"background[-0.19,-0.25;9.41,9.49;mcl_smithing_table_inventory.png]"..
|
||||
"label[0,4.0;" .. minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Inventory"))) .. "]" ..
|
||||
"list[current_player;main;0,4.5;9,3;9]" ..
|
||||
mcl_formspec.get_itemslot_bg(0,4.5,9,3) ..
|
||||
"list[current_player;main;0,7.74;9,1;]" ..
|
||||
mcl_formspec.get_itemslot_bg(0,7.74,9,1) ..
|
||||
"list[context;diamond_item;1,2.5;1,1;]" ..
|
||||
mcl_formspec.get_itemslot_bg(1,2.5,1,1) ..
|
||||
"list[context;netherite;4,2.5;1,1;]" ..
|
||||
mcl_formspec.get_itemslot_bg(4,2.5,1,1) ..
|
||||
"list[context;upgraded_item;8,2.5;1,1;]" ..
|
||||
mcl_formspec.get_itemslot_bg(8,2.5,1,1) ..
|
||||
"label[3,0.1;" .. minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Upgrade Gear"))) .. "]" ..
|
||||
"listring[context;output]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;input]"..
|
||||
"listring[current_player;main]"
|
||||
"label[4.125,0.375;" .. F(C(mcl_formspec.label_color, S("Upgrade Gear"))) .. "]",
|
||||
|
||||
"image[0.875,0.375;1.75,1.75;mcl_smithing_table_inventory_hammer.png]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(1.625, 2.6, 1, 1),
|
||||
"list[context;diamond_item;1.625,2.6;1,1;]",
|
||||
|
||||
"image[3.5,2.6;1,1;mcl_anvils_inventory_cross.png]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(5.375, 2.6, 1, 1),
|
||||
"list[context;netherite;5.375,2.6;1,1;]",
|
||||
|
||||
"image[6.75,2.6;2,1;mcl_anvils_inventory_arrow.png]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(9.125, 2.6, 1, 1),
|
||||
"list[context;upgraded_item;9.125,2.6;1,1;]",
|
||||
|
||||
-- Player Inventory
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3),
|
||||
"list[current_player;main;0.375,5.1;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1),
|
||||
"list[current_player;main;0.375,9.05;9,1;]",
|
||||
|
||||
-- Listrings
|
||||
|
||||
"listring[context;diamond_item]",
|
||||
"listring[current_player;main]",
|
||||
"listring[context;netherite]",
|
||||
"listring[current_player;main]",
|
||||
"listring[context;upgraded_item]",
|
||||
"listring[current_player;main]",
|
||||
"listring[current_player;main]",
|
||||
"listring[context;diamond_item]",
|
||||
})
|
||||
|
||||
---@param pos Vector
|
||||
local function reset_upgraded_item(pos)
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
local upgraded_item
|
||||
@ -66,8 +88,7 @@ minetest.register_node("mcl_smithing_table:table", {
|
||||
description = S("Smithing table"),
|
||||
-- ToDo: Add _doc_items_longdesc and _doc_items_usagehelp
|
||||
|
||||
stack_max = 64,
|
||||
groups = {pickaxey = 2, deco_block = 1},
|
||||
groups = { pickaxey = 2, deco_block = 1 },
|
||||
|
||||
tiles = {
|
||||
"mcl_smithing_table_top.png",
|
||||
@ -92,7 +113,8 @@ minetest.register_node("mcl_smithing_table:table", {
|
||||
end,
|
||||
|
||||
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
if listname == "diamond_item" and mcl_smithing_table.upgrade_item(stack) or listname == "netherite" and stack:get_name() == "mcl_nether:netherite_ingot" then
|
||||
if listname == "diamond_item" and mcl_smithing_table.upgrade_item(stack) or
|
||||
listname == "netherite" and stack:get_name() == "mcl_nether:netherite_ingot" then
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
@ -119,7 +141,7 @@ minetest.register_node("mcl_smithing_table:table", {
|
||||
take_item("netherite")
|
||||
|
||||
-- ToDo: make epic sound
|
||||
minetest.sound_play("mcl_smithing_table_upgrade", {pos = pos, max_hear_distance = 16})
|
||||
minetest.sound_play("mcl_smithing_table_upgrade", { pos = pos, max_hear_distance = 16 })
|
||||
end
|
||||
if listname == "upgraded_item" then
|
||||
if stack:get_name() == "mcl_farming:hoe_netherite" then
|
||||
@ -138,8 +160,8 @@ minetest.register_node("mcl_smithing_table:table", {
|
||||
minetest.register_craft({
|
||||
output = "mcl_smithing_table:table",
|
||||
recipe = {
|
||||
{"mcl_core:iron_ingot", "mcl_core:iron_ingot", ""},
|
||||
{"group:wood", "group:wood", ""},
|
||||
{"group:wood", "group:wood", ""}
|
||||
}
|
||||
{ "mcl_core:iron_ingot", "mcl_core:iron_ingot", "" },
|
||||
{ "group:wood", "group:wood", "" },
|
||||
{ "group:wood", "group:wood", "" }
|
||||
},
|
||||
})
|
||||
|
@ -1,2 +1,2 @@
|
||||
name = mcl_smithing_table
|
||||
depends = mcl_colors, mcl_formspec
|
||||
depends = mcl_colors, mcl_formspec, mcl_anvils
|
||||
|
@ -1,5 +1,6 @@
|
||||
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
local C = minetest.colorize
|
||||
local F = minetest.formspec_escape
|
||||
|
||||
local LIGHT_ACTIVE_FURNACE = 13
|
||||
|
||||
@ -8,60 +9,82 @@ local LIGHT_ACTIVE_FURNACE = 13
|
||||
--
|
||||
|
||||
local function active_formspec(fuel_percent, item_percent)
|
||||
return "size[9,8.75]"..
|
||||
"label[0,4;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]"..
|
||||
"list[current_player;main;0,4.5;9,3;9]"..
|
||||
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
|
||||
"list[current_player;main;0,7.74;9,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(0,7.74,9,1)..
|
||||
"label[2.75,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Smoker"))).."]"..
|
||||
"list[context;src;2.75,0.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(2.75,0.5,1,1)..
|
||||
"list[context;fuel;2.75,2.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(2.75,2.5,1,1)..
|
||||
"list[context;dst;5.75,1.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(5.75,1.5,1,1)..
|
||||
"image[2.75,1.5;1,1;default_furnace_fire_bg.png^[lowpart:"..
|
||||
(100-fuel_percent)..":default_furnace_fire_fg.png]"..
|
||||
"image[4.1,1.5;1.5,1;gui_furnace_arrow_bg.png^[lowpart:"..
|
||||
(item_percent)..":gui_furnace_arrow_fg.png^[transformR270]"..
|
||||
return table.concat({
|
||||
"formspec_version[4]",
|
||||
"size[11.75,10.425]",
|
||||
"label[0.375,0.375;" .. F(C(mcl_formspec.label_color, S("Smoker"))) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(3.5, 0.75, 1, 1),
|
||||
"list[context;src;3.5,0.75;1,1;]",
|
||||
|
||||
"image[3.5,2;1,1;default_furnace_fire_bg.png^[lowpart:" ..
|
||||
(100 - fuel_percent) .. ":default_furnace_fire_fg.png]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(3.5, 3.25, 1, 1),
|
||||
"list[context;fuel;3.5,3.25;1,1;]",
|
||||
|
||||
"image[5.25,2;1.5,1;gui_furnace_arrow_bg.png^[lowpart:" ..
|
||||
(item_percent) .. ":gui_furnace_arrow_fg.png^[transformR270]",
|
||||
mcl_formspec.get_itemslot_bg_v4(7.875, 2, 1, 1, 0.2),
|
||||
"list[context;dst;7.875,2;1,1;]",
|
||||
|
||||
"label[0.375,4.7;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3),
|
||||
"list[current_player;main;0.375,5.1;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1),
|
||||
"list[current_player;main;0.375,9.05;9,1;]",
|
||||
|
||||
-- Craft guide button temporarily removed due to Minetest bug.
|
||||
-- TODO: Add it back when the Minetest bug is fixed.
|
||||
--"image_button[8,0;1,1;craftguide_book.png;craftguide;]"..
|
||||
--"tooltip[craftguide;"..minetest.formspec_escape(S("Recipe book")).."]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;fuel]"..
|
||||
"listring[current_player;main]"
|
||||
|
||||
"listring[context;dst]",
|
||||
"listring[current_player;main]",
|
||||
"listring[context;src]",
|
||||
"listring[current_player;main]",
|
||||
"listring[context;fuel]",
|
||||
"listring[current_player;main]",
|
||||
})
|
||||
end
|
||||
|
||||
local inactive_formspec = "size[9,8.75]"..
|
||||
"label[0,4;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]"..
|
||||
"list[current_player;main;0,4.5;9,3;9]"..
|
||||
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
|
||||
"list[current_player;main;0,7.74;9,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(0,7.74,9,1)..
|
||||
"label[2.75,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Smoker"))).."]"..
|
||||
"list[context;src;2.75,0.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(2.75,0.5,1,1)..
|
||||
"list[context;fuel;2.75,2.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(2.75,2.5,1,1)..
|
||||
"list[context;dst;5.75,1.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(5.75,1.5,1,1)..
|
||||
"image[2.75,1.5;1,1;default_furnace_fire_bg.png]"..
|
||||
"image[4.1,1.5;1.5,1;gui_furnace_arrow_bg.png^[transformR270]"..
|
||||
local inactive_formspec = table.concat({
|
||||
"formspec_version[4]",
|
||||
"size[11.75,10.425]",
|
||||
"label[0.375,0.375;" .. F(C(mcl_formspec.label_color, S("Smoker"))) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(3.5, 0.75, 1, 1),
|
||||
"list[context;src;3.5,0.75;1,1;]",
|
||||
|
||||
"image[3.5,2;1,1;default_furnace_fire_bg.png]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(3.5, 3.25, 1, 1),
|
||||
"list[context;fuel;3.5,3.25;1,1;]",
|
||||
|
||||
"image[5.25,2;1.5,1;gui_furnace_arrow_bg.png^[transformR270]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(7.875, 2, 1, 1, 0.2),
|
||||
"list[context;dst;7.875,2;1,1;]",
|
||||
|
||||
"label[0.375,4.7;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3),
|
||||
"list[current_player;main;0.375,5.1;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1),
|
||||
"list[current_player;main;0.375,9.05;9,1;]",
|
||||
|
||||
-- Craft guide button temporarily removed due to Minetest bug.
|
||||
-- TODO: Add it back when the Minetest bug is fixed.
|
||||
--"image_button[8,0;1,1;craftguide_book.png;craftguide;]"..
|
||||
--"tooltip[craftguide;"..minetest.formspec_escape(S("Recipe book")).."]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;fuel]"..
|
||||
"listring[current_player;main]"
|
||||
|
||||
"listring[context;dst]",
|
||||
"listring[current_player;main]",
|
||||
"listring[context;src]",
|
||||
"listring[current_player;main]",
|
||||
"listring[context;fuel]",
|
||||
"listring[current_player;main]",
|
||||
})
|
||||
|
||||
|
||||
local receive_fields = function(pos, formname, fields, sender)
|
||||
if fields.craftguide then
|
||||
@ -71,7 +94,7 @@ end
|
||||
|
||||
local function give_xp(pos, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local dir = vector.divide(minetest.facedir_to_dir(minetest.get_node(pos).param2),-1.95)
|
||||
local dir = vector.divide(minetest.facedir_to_dir(minetest.get_node(pos).param2), -1.95)
|
||||
local xp = meta:get_int("xp")
|
||||
if xp > 0 then
|
||||
if player then
|
||||
@ -98,7 +121,7 @@ local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
-- Test stack with size 1 because we burn one fuel at a time
|
||||
local teststack = ItemStack(stack)
|
||||
teststack:set_count(1)
|
||||
local output, decremented_input = minetest.get_craft_result({method="fuel", width=1, items={teststack}})
|
||||
local output, decremented_input = minetest.get_craft_result({ method = "fuel", width = 1, items = { teststack } })
|
||||
if output.time ~= 0 then
|
||||
-- Only allow to place 1 item if fuel get replaced by recipe.
|
||||
-- This is the case for lava buckets.
|
||||
@ -292,7 +315,7 @@ local function smoker_node_timer(pos, elapsed)
|
||||
|
||||
-- Check if we have cookable content: cookable
|
||||
local aftercooked
|
||||
cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
|
||||
cooked, aftercooked = minetest.get_craft_result({ method = "cooking", width = 1, items = srclist })
|
||||
cookable = minetest.get_item_group(inv:get_stack("src", 1):get_name(), "smoker_cookable") == 1
|
||||
if cookable then
|
||||
-- Successful cooking requires space in dst slot and time
|
||||
@ -310,7 +333,7 @@ local function smoker_node_timer(pos, elapsed)
|
||||
if cookable and not active then
|
||||
-- We need to get new fuel
|
||||
local afterfuel
|
||||
fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
|
||||
fuel, afterfuel = minetest.get_craft_result({ method = "fuel", width = 1, items = fuellist })
|
||||
|
||||
if fuel.time == 0 then
|
||||
-- No valid fuel in fuel list -- stop
|
||||
@ -415,12 +438,13 @@ end
|
||||
minetest.register_node("mcl_smoker:smoker", {
|
||||
description = S("Smoker"),
|
||||
_tt_help = S("Cooks food faster than furnace"),
|
||||
_doc_items_longdesc = S("Smokers cook several items, mainly raw foods, into cooked foods, but twice as fast as a normal furnace."),
|
||||
_doc_items_longdesc = S(
|
||||
"Smokers cook several items, mainly raw foods, into cooked foods, but twice as fast as a normal furnace."),
|
||||
_doc_items_usagehelp =
|
||||
S("Use the smoker to open the furnace menu.").."\n"..
|
||||
S("Place a furnace fuel in the lower slot and the source material in the upper slot.").."\n"..
|
||||
S("The smoker will slowly use its fuel to smelt the item.").."\n"..
|
||||
S("The result will be placed into the output slot at the right side.").."\n"..
|
||||
S("Use the smoker to open the furnace menu.") .. "\n" ..
|
||||
S("Place a furnace fuel in the lower slot and the source material in the upper slot.") .. "\n" ..
|
||||
S("The smoker will slowly use its fuel to smelt the item.") .. "\n" ..
|
||||
S("The result will be placed into the output slot at the right side.") .. "\n" ..
|
||||
S("Use the recipe book to see what foods you can smelt, what you can use as fuel and how long it will burn."),
|
||||
_doc_items_hidden = false,
|
||||
tiles = {
|
||||
@ -429,7 +453,7 @@ minetest.register_node("mcl_smoker:smoker", {
|
||||
"smoker_side.png", "smoker_front.png"
|
||||
},
|
||||
paramtype2 = "facedir",
|
||||
groups = {pickaxey=1, container=4, deco_block=1, material_stone=1},
|
||||
groups = { pickaxey = 1, container = 4, deco_block = 1, material_stone = 1 },
|
||||
is_ground_content = false,
|
||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
|
||||
@ -439,10 +463,14 @@ minetest.register_node("mcl_smoker:smoker", {
|
||||
local meta2 = meta:to_table()
|
||||
meta:from_table(oldmetadata)
|
||||
local inv = meta:get_inventory()
|
||||
for _, listname in ipairs({"src", "dst", "fuel"}) do
|
||||
for _, listname in ipairs({ "src", "dst", "fuel" }) do
|
||||
local stack = inv:get_stack(listname, 1)
|
||||
if not stack:is_empty() then
|
||||
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5}
|
||||
local p = {
|
||||
x = pos.x + math.random(0, 10) / 10 - 0.5,
|
||||
y = pos.y,
|
||||
z = pos.z + math.random(0, 10) / 10 - 0.5
|
||||
}
|
||||
minetest.add_item(p, stack)
|
||||
end
|
||||
end
|
||||
@ -499,14 +527,16 @@ minetest.register_node("mcl_smoker:smoker_active", {
|
||||
tiles = {
|
||||
"smoker_top.png", "smoker_bottom.png",
|
||||
"smoker_side.png", "smoker_side.png",
|
||||
"smoker_side.png", {name = "smoker_front_on.png",
|
||||
animation = {type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 48}},
|
||||
"smoker_side.png", {
|
||||
name = "smoker_front_on.png",
|
||||
animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 48 }
|
||||
},
|
||||
},
|
||||
paramtype2 = "facedir",
|
||||
paramtype = "light",
|
||||
light_source = LIGHT_ACTIVE_FURNACE,
|
||||
drop = "mcl_smoker:smoker",
|
||||
groups = {pickaxey=1, container=4, deco_block=1, not_in_creative_inventory=1, material_stone=1},
|
||||
groups = { pickaxey = 1, container = 4, deco_block = 1, not_in_creative_inventory = 1, material_stone = 1 },
|
||||
is_ground_content = false,
|
||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
on_timer = smoker_node_timer,
|
||||
@ -516,10 +546,14 @@ minetest.register_node("mcl_smoker:smoker_active", {
|
||||
local meta2 = meta
|
||||
meta:from_table(oldmetadata)
|
||||
local inv = meta:get_inventory()
|
||||
for _, listname in ipairs({"src", "dst", "fuel"}) do
|
||||
for _, listname in ipairs({ "src", "dst", "fuel" }) do
|
||||
local stack = inv:get_stack(listname, 1)
|
||||
if not stack:is_empty() then
|
||||
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5}
|
||||
local p = {
|
||||
x = pos.x + math.random(0, 10) / 10 - 0.5,
|
||||
y = pos.y,
|
||||
z = pos.z + math.random(0, 10) / 10 - 0.5
|
||||
}
|
||||
minetest.add_item(p, stack)
|
||||
end
|
||||
end
|
||||
@ -564,7 +598,7 @@ end
|
||||
minetest.register_lbm({
|
||||
label = "Active smoker flame particles",
|
||||
name = "mcl_smoker:flames",
|
||||
nodenames = {"mcl_smoker:smoker_active"},
|
||||
nodenames = { "mcl_smoker:smoker_active" },
|
||||
run_at_every_load = true,
|
||||
action = function(pos, node)
|
||||
spawn_flames(pos, node.param2)
|
||||
|
27
mods/PLAYER/mcl_gamemode/API.md
Normal file
@ -0,0 +1,27 @@
|
||||
# `mcl_gamemode`
|
||||
|
||||
## `mcl_gamemode.gamemodes`
|
||||
|
||||
List of availlable gamemodes.
|
||||
|
||||
Currently `{"survival", "creative"}`
|
||||
|
||||
## `mcl_gamemode.get_gamemode(player)`
|
||||
|
||||
Get the player's gamemode.
|
||||
|
||||
Returns "survival" or "creative".
|
||||
|
||||
## `mcl_gamemode.set_gamemode(player, gamemode)`
|
||||
|
||||
Set the player's gamemode.
|
||||
|
||||
gamemode: "survival" or "creative"
|
||||
|
||||
## `mcl_gamemode.register_on_gamemode_change(function(player, old_gamemode, new_gamemode))`
|
||||
|
||||
Register a function that will be called when `mcl_gamemode.set_gamemode` is called.
|
||||
|
||||
## `mcl_gamemode.registered_on_gamemode_change`
|
||||
|
||||
Map of registered on_gamemode_change.
|
84
mods/PLAYER/mcl_gamemode/init.lua
Normal file
@ -0,0 +1,84 @@
|
||||
local S = minetest.get_translator("mcl_gamemode")
|
||||
|
||||
mcl_gamemode = {}
|
||||
|
||||
mcl_gamemode.gamemodes = {
|
||||
"survival",
|
||||
"creative",
|
||||
}
|
||||
|
||||
---@param n any
|
||||
---@param h table
|
||||
---@return boolean
|
||||
local function in_table(n, h)
|
||||
for k, v in pairs(h) do
|
||||
if v == n then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
---@type fun(player: mt.PlayerObjectRef, old_gamemode: '"survival"'|'"creative"', new_gamemode: '"survival"'|'"creative"')[]
|
||||
mcl_gamemode.registered_on_gamemode_change = {}
|
||||
|
||||
---@param func fun(player: mt.PlayerObjectRef, old_gamemode: '"survival"'|'"creative"', new_gamemode: '"survival"'|'"creative"')
|
||||
function mcl_gamemode.register_on_gamemode_change(func)
|
||||
table.insert(mcl_gamemode.registered_on_gamemode_change, func)
|
||||
end
|
||||
|
||||
---@param player mt.PlayerObjectRef
|
||||
---@param gamemode '"survival"'|'"creative"'
|
||||
function mcl_gamemode.set_gamemode(player, gamemode)
|
||||
local meta = player:get_meta()
|
||||
local old_gamemode = meta:get_string("gamemode")
|
||||
meta:set_string("gamemode", gamemode)
|
||||
for _, f in ipairs(mcl_gamemode.registered_on_gamemode_change) do
|
||||
f(player, old_gamemode, gamemode)
|
||||
end
|
||||
end
|
||||
|
||||
local mt_is_creative_enabled = minetest.is_creative_enabled
|
||||
|
||||
---@param player mt.PlayerObjectRef
|
||||
---@return '"survival"'|'"creative"'
|
||||
function mcl_gamemode.get_gamemode(player)
|
||||
if mt_is_creative_enabled(player:get_player_name()) then
|
||||
return "creative"
|
||||
end
|
||||
return player:get_meta():get_string("gamemode")
|
||||
end
|
||||
|
||||
function minetest.is_creative_enabled(name)
|
||||
if mt_is_creative_enabled(name) then return true end
|
||||
if not name then return false end
|
||||
local p = minetest.get_player_by_name(name)
|
||||
if p then
|
||||
return p:get_meta():get_string("gamemode") == "creative"
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
minetest.register_chatcommand("gamemode", {
|
||||
params = S("[<gamemode>] [<player>]"),
|
||||
description = S("Change gamemode (survival/creative) for yourself or player"),
|
||||
privs = { server = true },
|
||||
func = function(n, param)
|
||||
-- Full input validation ( just for @erlehmann <3 )
|
||||
local p = minetest.get_player_by_name(n)
|
||||
local args = param:split(" ")
|
||||
if args[2] ~= nil then
|
||||
p = minetest.get_player_by_name(args[2])
|
||||
end
|
||||
if not p then
|
||||
return false, S("Player not online")
|
||||
end
|
||||
if args[1] ~= nil and not in_table(args[1], mcl_gamemode.gamemodes) then
|
||||
return false, S("Gamemode " .. args[1] .. " does not exist.")
|
||||
elseif args[1] ~= nil then
|
||||
mcl_gamemode.set_gamemode(p, args[1])
|
||||
end
|
||||
--Result message - show effective game mode
|
||||
local gm = p:get_meta():get_string("gamemode")
|
||||
if gm == "" then gm = mcl_gamemode.gamemodes[1] end
|
||||
return true, S("Gamemode for player ") .. n .. S(": " .. gm)
|
||||
end
|
||||
})
|
1
mods/PLAYER/mcl_gamemode/mod.conf
Normal file
@ -0,0 +1 @@
|
||||
name = mcl_gamemode
|
@ -89,6 +89,10 @@ minetest.register_on_joinplayer(function(player)
|
||||
player:get_inventory():set_size("hand", 1)
|
||||
end)
|
||||
|
||||
mcl_gamemode.register_on_gamemode_change(function(player)
|
||||
mcl_meshhand.update_player(player)
|
||||
end)
|
||||
|
||||
if mcl_skins_enabled then
|
||||
mcl_player.register_on_visual_change(mcl_meshhand.update_player)
|
||||
else
|
||||
|
@ -1,5 +1,5 @@
|
||||
name = mcl_meshhand
|
||||
author = jordan4ibanez
|
||||
description = Applies the player skin texture to the hand.
|
||||
depends = mcl_tools, mcl_player
|
||||
depends = mcl_tools, mcl_player, mcl_gamemode
|
||||
optional_depends = mcl_skins, mcl_custom_skins
|
||||
|
@ -1,3 +1,4 @@
|
||||
local string = string
|
||||
local sf = string.format
|
||||
|
||||
-- Minetest 0.4 mod: player
|
||||
@ -11,7 +12,8 @@ local animation_blend = 0
|
||||
local function get_mouse_button(player)
|
||||
local controls = player:get_player_control()
|
||||
local get_wielded_item_name = player:get_wielded_item():get_name()
|
||||
if controls.RMB and not string.find(get_wielded_item_name, "mcl_bows:bow") and not string.find(get_wielded_item_name, "mcl_bows:crossbow") and
|
||||
if controls.RMB and not string.find(get_wielded_item_name, "mcl_bows:bow") and
|
||||
not string.find(get_wielded_item_name, "mcl_bows:crossbow") and
|
||||
not mcl_shields.wielding_shield(player, 1) and not mcl_shields.wielding_shield(player, 2) or controls.LMB then
|
||||
return true
|
||||
else
|
||||
@ -19,7 +21,7 @@ local function get_mouse_button(player)
|
||||
end
|
||||
end
|
||||
|
||||
mcl_player.registered_player_models = { }
|
||||
mcl_player.registered_player_models = {}
|
||||
|
||||
-- Local for speed.
|
||||
local models = mcl_player.registered_player_models
|
||||
@ -49,7 +51,7 @@ function mcl_player.player_get_animation(player)
|
||||
model = player_model[name],
|
||||
textures = textures,
|
||||
animation = player_anim[name],
|
||||
visibility = player_visibility[name]
|
||||
visibility = player_visible[name]
|
||||
}
|
||||
end
|
||||
|
||||
@ -94,7 +96,7 @@ function mcl_player.player_set_model(player, model_name)
|
||||
player:set_properties({
|
||||
mesh = model_name,
|
||||
visual = "mesh",
|
||||
visual_size = model.visual_size or {x=1, y=1},
|
||||
visual_size = model.visual_size or { x = 1, y = 1 },
|
||||
damage_texture_modifier = "^[colorize:red:130",
|
||||
})
|
||||
update_player_textures(player)
|
||||
@ -133,6 +135,13 @@ function mcl_player.player_set_armor(player, texture)
|
||||
update_player_textures(player)
|
||||
end
|
||||
|
||||
---@param player mt.PlayerObjectRef
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@param w number
|
||||
---@param h number
|
||||
---@param fsname string
|
||||
---@return string
|
||||
function mcl_player.get_player_formspec_model(player, x, y, w, h, fsname)
|
||||
local name = player:get_player_name()
|
||||
local model = player_model[name]
|
||||
@ -165,7 +174,8 @@ minetest.register_on_joinplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
mcl_player.player_attached[name] = false
|
||||
player_visible[name] = true
|
||||
player_textures[name] = {"character.png", "blank.png", "blank.png"}
|
||||
player_textures[name] = { "character.png", "blank.png", "blank.png" }
|
||||
|
||||
--player:set_local_animation({x=0, y=79}, {x=168, y=187}, {x=189, y=198}, {x=200, y=219}, 30)
|
||||
player:set_fov(86.1) -- see <https://minecraft.gamepedia.com/Options#Video_settings>>>>
|
||||
end)
|
||||
@ -225,7 +235,9 @@ minetest.register_globalstep(function(dtime)
|
||||
or walking and velocity.z > 0.35
|
||||
or walking and velocity.z < -0.35 then
|
||||
local wielded_itemname = player:get_wielded_item():get_name()
|
||||
local no_arm_moving = string.find(wielded_itemname, "mcl_bows:bow") or mcl_shields.wielding_shield(player, 1) or mcl_shields.wielding_shield(player, 2)
|
||||
local no_arm_moving = string.find(wielded_itemname, "mcl_bows:bow") or
|
||||
mcl_shields.wielding_shield(player, 1) or
|
||||
mcl_shields.wielding_shield(player, 2)
|
||||
if player_sneak[name] ~= controls.sneak then
|
||||
player_anim[name] = nil
|
||||
player_sneak[name] = controls.sneak
|
||||
@ -234,7 +246,8 @@ minetest.register_globalstep(function(dtime)
|
||||
player_set_animation(player, "swim_walk_mine", animation_speed_mod)
|
||||
elseif not controls.sneak and head_in_water and is_sprinting == true then
|
||||
player_set_animation(player, "swim_walk", animation_speed_mod)
|
||||
elseif no_arm_moving and controls.RMB and controls.sneak or string.find(wielded_itemname, "mcl_bows:crossbow_") and controls.sneak then
|
||||
elseif no_arm_moving and controls.RMB and controls.sneak or
|
||||
string.find(wielded_itemname, "mcl_bows:crossbow_") and controls.sneak then
|
||||
player_set_animation(player, "bow_sneak", animation_speed_mod)
|
||||
elseif no_arm_moving and controls.RMB or string.find(wielded_itemname, "mcl_bows:crossbow_") then
|
||||
player_set_animation(player, "bow_walk", animation_speed_mod)
|
||||
|
BIN
textures/crafting_formspec_arrow.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.2 KiB |
BIN
textures/grindstone_gui_9.png
Normal file
After Width: | Height: | Size: 100 B |
BIN
textures/mcl_anvils_inventory_arrow.png
Normal file
After Width: | Height: | Size: 238 B |
BIN
textures/mcl_anvils_inventory_cross.png
Normal file
After Width: | Height: | Size: 133 B |
BIN
textures/mcl_anvils_inventory_hammer.png
Normal file
After Width: | Height: | Size: 177 B |
BIN
textures/mcl_book_book_empty_slot.png
Normal file
After Width: | Height: | Size: 115 B |
BIN
textures/mcl_inventory_background9.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 240 B After Width: | Height: | Size: 284 B |
Before Width: | Height: | Size: 263 B After Width: | Height: | Size: 298 B |
BIN
textures/mcl_smithing_table_inventory_hammer.png
Normal file
After Width: | Height: | Size: 178 B |
Before Width: | Height: | Size: 241 B After Width: | Height: | Size: 283 B |
Before Width: | Height: | Size: 283 B After Width: | Height: | Size: 320 B |