Merge pull request 'mcl_itemframes_rewrite' (#2897) from mcl_itemframes_rewrite into master

Reviewed-on: https://git.minetest.land/MineClone2/MineClone2/pulls/2897
Reviewed-by: cora <cora@noreply.git.minetest.land>
This commit is contained in:
cora 2022-11-05 00:28:45 +00:00
commit faf75a3ce5
16 changed files with 1141 additions and 367 deletions

@ -1,4 +1,13 @@
This mod is originally by Zeg9, but heavily modified for MineClone 2.
This mod has been rewritten and revamped by Michieal / Faerraven. Based on the code originally done by Zeg9, and then
heavily modified by the Mineclone 2 dev team.
This mod now supports all the base item frame functions, like rotating the displayed item, which it didn't do before it
was rewritten. Additionally, Glow Frames have been added in, and item frames now has an API to allow new item frames to
be created in other modules.
Now requires the Screwdriver to have full functionality.
The code is licenced under the standard MineClone 2 license for usage, with the requirement that this readme is
included in the code / module.
Model created by 22i, licensed under the
GNU GPLv3 <https://www.gnu.org/licenses/gpl-3.0.html>.

@ -1,348 +1,62 @@
mcl_itemframes = {}
local modname = minetest.get_current_modname()
local modpath = minetest.get_modpath(modname)
local S = minetest.get_translator(minetest.get_current_modname())
local VISUAL_SIZE = 0.3
-- mcl_itemframes API
dofile(modpath .. "/item_frames_API.lua")
minetest.register_entity("mcl_itemframes:item",{
hp_max = 1,
visual = "wielditem",
visual_size = {x=VISUAL_SIZE, y=VISUAL_SIZE},
physical = false,
pointable = false,
textures = { "blank.png" },
_texture = "blank.png",
_scale = 1,
-- actual api initialization.
mcl_itemframes.create_base_definitions()
on_activate = function(self, staticdata)
if staticdata and staticdata ~= "" then
local data = staticdata:split(";")
if data and data[1] and data[2] then
self._nodename = data[1]
self._texture = data[2]
if data[3] then
self._scale = data[3]
else
self._scale = 1
end
end
end
if self._texture then
self.object:set_properties({
textures={self._texture},
visual_size={x=VISUAL_SIZE/self._scale, y=VISUAL_SIZE/self._scale},
})
end
end,
get_staticdata = function(self)
if self._nodename and self._texture then
local ret = self._nodename .. ";" .. self._texture
if self._scale then
ret = ret .. ";" .. self._scale
end
return ret
end
return ""
end,
-- necessary to maintain compatibility amongst older versions.
mcl_itemframes.backwards_compatibility()
_update_texture = function(self)
if self._texture then
self.object:set_properties({
textures={self._texture},
visual_size={x=VISUAL_SIZE/self._scale, y=VISUAL_SIZE/self._scale},
})
end
end,
})
minetest.register_entity("mcl_itemframes:map", {
initial_properties = {
visual = "upright_sprite",
visual_size = {x = 1, y = 1},
pointable = false,
physical = false,
collide_with_objects = false,
textures = {"blank.png"},
},
on_activate = function(self, staticdata)
self.id = staticdata
mcl_maps.load_map(self.id, function(texture)
-- will not crash even if self.object is invalid by now
self.object:set_properties({textures = {texture}})
end)
end,
get_staticdata = function(self)
return self.id
end,
})
local facedir = {}
facedir[0] = {x=0,y=0,z=1}
facedir[1] = {x=1,y=0,z=0}
facedir[2] = {x=0,y=0,z=-1}
facedir[3] = {x=-1,y=0,z=0}
local remove_item_entity = function(pos, node)
if node.name == "mcl_itemframes:item_frame" then
for _, obj in pairs(minetest.get_objects_inside_radius(pos, 0.5)) do
local entity = obj:get_luaentity()
if entity and (entity.name == "mcl_itemframes:item" or entity.name == "mcl_itemframes:map") then
obj:remove()
end
end
end
end
local update_item_entity = function(pos, node, param2)
remove_item_entity(pos, node)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local item = inv:get_stack("main", 1)
if not item:is_empty() then
if not param2 then
param2 = node.param2
end
if node.name == "mcl_itemframes:item_frame" then
local posad = facedir[param2]
pos.x = pos.x + posad.x*6.5/16
pos.y = pos.y + posad.y*6.5/16
pos.z = pos.z + posad.z*6.5/16
end
local yaw = math.pi*2 - param2 * math.pi/2
local map_id = item:get_meta():get_string("mcl_maps:id")
if map_id == "" then
local e = minetest.add_entity(pos, "mcl_itemframes:item")
local lua = e:get_luaentity()
lua._nodename = node.name
local itemname = item:get_name()
if itemname == "" or itemname == nil then
lua._texture = "blank.png"
lua._scale = 1
else
lua._texture = itemname
local def = minetest.registered_items[itemname]
lua._scale = def and def.wield_scale and def.wield_scale.x or 1
end
lua:_update_texture()
if node.name == "mcl_itemframes:item_frame" then
e:set_yaw(yaw)
end
else
local e = minetest.add_entity(pos, "mcl_itemframes:map", map_id)
e:set_yaw(yaw)
end
end
end
mcl_itemframes.update_item_entity = update_item_entity
local drop_item = function(pos, node, meta, clicker)
local cname = ""
if clicker and clicker:is_player() then
cname = clicker:get_player_name()
end
if node.name == "mcl_itemframes:item_frame" and not minetest.is_creative_enabled(cname) then
local inv = meta:get_inventory()
local item = inv:get_stack("main", 1)
if not item:is_empty() then
minetest.add_item(pos, item)
end
end
meta:set_string("infotext", "")
remove_item_entity(pos, node)
end
minetest.register_node("mcl_itemframes:item_frame",{
description = S("Item Frame"),
_tt_help = S("Can hold an item"),
_doc_items_longdesc = S("Item frames are decorative blocks in which items can be placed."),
_doc_items_usagehelp = S("Just place any item on the item frame. Use the item frame again to retrieve the item."),
drawtype = "mesh",
is_ground_content = false,
mesh = "mcl_itemframes_itemframe1facedir.obj",
selection_box = { type = "fixed", fixed = {-6/16, -6/16, 7/16, 6/16, 6/16, 0.5} },
collision_box = { type = "fixed", fixed = {-6/16, -6/16, 7/16, 6/16, 6/16, 0.5} },
tiles = {"mcl_itemframes_itemframe_background.png", "mcl_itemframes_itemframe_background.png", "mcl_itemframes_itemframe_background.png", "mcl_itemframes_itemframe_background.png", "default_wood.png", "mcl_itemframes_itemframe_background.png"},
inventory_image = "mcl_itemframes_item_frame.png",
wield_image = "mcl_itemframes_item_frame.png",
paramtype = "light",
paramtype2 = "facedir",
sunlight_propagates = true,
groups = { dig_immediate=3,deco_block=1,dig_by_piston=1,container=7,attached_node_facedir=1 },
sounds = mcl_sounds.node_sound_defaults(),
node_placement_prediction = "",
on_timer = function(pos)
local inv = minetest.get_meta(pos):get_inventory()
local stack = inv:get_stack("main", 1)
local itemname = stack:get_name()
if minetest.get_item_group(itemname, "clock") > 0 then
local new_name = "mcl_clock:clock_" .. (mcl_worlds.clock_works(pos) and mcl_clock.old_time or mcl_clock.random_frame)
if itemname ~= new_name then
stack:set_name(new_name)
inv:set_stack("main", 1, stack)
local node = minetest.get_node(pos)
update_item_entity(pos, node, node.param2)
end
minetest.get_node_timer(pos):start(1.0)
end
end,
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then
return itemstack
end
-- Use pointed node's on_rightclick function first, if present
local node = minetest.get_node(pointed_thing.under)
if placer and not placer: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, placer, itemstack) or itemstack
end
end
return minetest.item_place(itemstack, placer, pointed_thing, minetest.dir_to_facedir(vector.direction(pointed_thing.above, pointed_thing.under)))
end,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
inv:set_size("main", 1)
end,
on_rightclick = function(pos, node, clicker, itemstack)
if not itemstack then
return
end
local pname = clicker:get_player_name()
if minetest.is_protected(pos, pname) then
minetest.record_protection_violation(pos, pname)
return
end
local meta = minetest.get_meta(pos)
drop_item(pos, node, meta, clicker)
local inv = meta:get_inventory()
if itemstack:is_empty() then
remove_item_entity(pos, node)
meta:set_string("infotext", "")
inv:set_stack("main", 1, "")
return itemstack
end
local put_itemstack = ItemStack(itemstack)
put_itemstack:set_count(1)
local itemname = put_itemstack:get_name()
if minetest.get_item_group(itemname, "compass") > 0 then
put_itemstack:set_name(mcl_compass.get_compass_itemname(pos, minetest.dir_to_yaw(minetest.facedir_to_dir(node.param2)), put_itemstack))
end
if minetest.get_item_group(itemname, "clock") > 0 then
minetest.get_node_timer(pos):start(1.0)
end
inv:set_stack("main", 1, put_itemstack)
update_item_entity(pos, node)
-- Add node infotext when item has been named
local imeta = itemstack:get_meta()
local iname = imeta:get_string("name")
if iname then
meta:set_string("infotext", iname)
end
if not minetest.is_creative_enabled(clicker:get_player_name()) then
itemstack:take_item()
end
return itemstack
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return 0
else
return count
end
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return 0
else
return stack:get_count()
end
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return 0
else
return stack:get_count()
end
end,
on_destruct = function(pos)
local meta = minetest.get_meta(pos)
local node = minetest.get_node(pos)
drop_item(pos, node, meta)
end,
on_rotate = function(pos, node, user, mode, param2)
if mode == screwdriver.ROTATE_FACE then
-- Rotate face
--local meta = minetest.get_meta(pos)
local node = minetest.get_node(pos)
local objs = nil
if node.name == "mcl_itemframes:item_frame" then
objs = minetest.get_objects_inside_radius(pos, 0.5)
end
if objs then
for _, obj in ipairs(objs) do
if obj and obj:get_luaentity() and obj:get_luaentity().name == "mcl_itemframes:item" then
update_item_entity(pos, node, (node.param2+1) % 4)
break
end
end
end
return
elseif mode == screwdriver.ROTATE_AXIS then
return false
end
end,
})
-- Define the standard frames.
mcl_itemframes.create_custom_frame("false", "item_frame", false,
"mcl_itemframes_item_frame.png", mcl_colors.WHITE, "Item Frame",
"Can hold an item.","")
mcl_itemframes.create_custom_frame("false", "glow_item_frame", true,
"mcl_itemframes_glow_item_frame.png", mcl_colors.WHITE, "Glowing Item Frame",
"Can hold an item and glows.","")
-- Register the base frame's recipes.
-- was going to make it a specialized function, but minetest refuses to play nice.
minetest.register_craft({
output = "mcl_itemframes:item_frame",
recipe = {
{"mcl_core:stick", "mcl_core:stick", "mcl_core:stick"},
{"mcl_core:stick", "mcl_mobitems:leather", "mcl_core:stick"},
{"mcl_core:stick", "mcl_core:stick", "mcl_core:stick"},
{ "mcl_core:stick", "mcl_core:stick", "mcl_core:stick" },
{ "mcl_core:stick", "mcl_mobitems:leather", "mcl_core:stick" },
{ "mcl_core:stick", "mcl_core:stick", "mcl_core:stick" },
}
})
minetest.register_lbm({
label = "Update legacy item frames",
name = "mcl_itemframes:update_legacy_item_frames",
nodenames = {"itemframes:frame"},
action = function(pos, node)
-- Swap legacy node, then respawn entity
node.name = "mcl_itemframes:item_frame"
local meta = minetest.get_meta(pos)
local item = meta:get_string("item")
minetest.swap_node(pos, node)
if item ~= "" then
local itemstack = ItemStack(minetest.deserialize(meta:get_string("itemdata")))
local inv = meta:get_inventory()
inv:set_size("main", 1)
if not itemstack:is_empty() then
inv:set_stack("main", 1, itemstack)
end
end
update_item_entity(pos, node)
end,
minetest.register_craft({
type = "shapeless",
output = 'mcl_itemframes:glow_item_frame',
recipe = { 'mcl_mobitems:glow_ink_sac', 'mcl_itemframes:item_frame' },
})
-- FIXME: Item entities can get destroyed by /clearobjects
minetest.register_lbm({
label = "Respawn item frame item entities",
name = "mcl_itemframes:respawn_entities",
nodenames = {"mcl_itemframes:item_frame"},
run_at_every_load = true,
action = function(pos, node)
update_item_entity(pos, node)
end,
--[[ green frames just for testing
mcl_itemframes.create_custom_frame("false", "my_regular_frame", false,
"mcl_itemframes_item_frame.png", mcl_colors.DARK_GREEN, "A Green frame",
"My Green Frame")
mcl_itemframes.create_custom_frame("false", "my_glowing_frame", true,
"mcl_itemframes_glow_item_frame.png", mcl_colors.DARK_GREEN, "A Green glowing frame",
"My Green glowing Frame")
minetest.register_craft({
output = "mcl_itemframes:my_regular_frame",
recipe = {
{ "", "mcl_core:stick", "" },
{ "mcl_core:stick", "", "mcl_core:stick" },
{ "", "mcl_core:stick", "" },
}
})
minetest.register_alias("itemframes:frame", "mcl_itemframes:item_frame")
minetest.register_craft({
type = "shapeless",
output = "mcl_itemframes:my_glowing_frame",
recipe = { "mcl_mobitems:glow_ink_sac", "mcl_itemframes:my_regular_frame" },
})
--]]

@ -0,0 +1,821 @@
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by michieal.
--- DateTime: 10/26/22 1:16 AM
---
mcl_itemframes = {}
mcl_itemframes.item_frame_base = {}
mcl_itemframes.glow_frame_base = {}
mcl_itemframes.frames_registered = {}
mcl_itemframes.frames_registered.glowing = {}
mcl_itemframes.frames_registered.standard = {}
-- Set to true to get all of the DEBUG messages.
mcl_itemframes.DEBUG = false
if mcl_itemframes.DEBUG then
minetest.log("action", "[mcl_itemframes] initialized.")
end
local S = minetest.get_translator(minetest.get_current_modname())
local table = table
local pairs = pairs
if mcl_itemframes.DEBUG then
minetest.log("action", "[mcl_itemframes] API initialized.")
end
local VISUAL_SIZE = 0.3
local facedir = {}
local pi = math.pi
local glow_amount = 6 -- LIGHT_MAX is 15, but the items aren't supposed to be a light source.
local frame_item_base = {}
local map_item_base = {}
-- Time to Fleckenstein! (it just sounds cool lol)
--- self: the object to roll.
local function update_roll(self, pos)
-- get the entity's metadata.
local meta = minetest.get_meta(pos)
-- using an integer, as it's the number of 45 degree turns. ie, 0 to 7
local current_roll = meta:get_int("roll", 0)
local new_roll = current_roll + 1
if new_roll == 8 then
new_roll = 0
end
meta:set_int("roll", new_roll)
local new_roll_deg = new_roll * 45
-- * `get_rotation()`: returns the rotation, a vector (radians)
local rot = self:get_rotation()
local Radians = 0
-- Radians = Degrees * (pi / 180) degrees to radian formula
-- Radian quick chart
-- One full revolution is equal to 2π rad (or) 360°.
-- 1° = 0.017453 radians and 1 rad = 57.2958°.
-- To convert an angle from degrees to radians, we multiply it by π/180°.
-- To convert an angle from radians to degrees, we multiply it by 180°/π.
Radians = new_roll_deg * (pi / 180)
rot.z = Radians
self:set_rotation(rot)
end
--- self: the object to roll.
--- faceDeg: 0-7, inclusive.
local function set_roll(self, faceDeg)
-- get the entity's metadata.
local meta = minetest.get_meta(self:get_pos())
-- using an integer, as it's the number of 45 degree turns. ie, 0 to 7
local new_roll = faceDeg
if new_roll >= 8 then
new_roll = 7
end
if new_roll <= 0 then
new_roll = 0
end
meta:set_int("roll", new_roll)
local new_roll_deg = new_roll * 45
-- * `get_rotation()`: returns the rotation, a vector (radians)
local rot = self:get_rotation()
local Radians = 0
-- Radians = Degrees * (pi / 180) degrees to radian formula
-- Radian quick chart
-- One full revolution is equal to 2π rad (or) 360°.
-- 1° = 0.017453 radians and 1 rad = 57.2958°.
-- To convert an angle from degrees to radians, we multiply it by π/180°.
-- To convert an angle from radians to degrees, we multiply it by 180°/π.
Radians = new_roll_deg * (pi / 180)
rot.z = Radians
self:set_rotation(rot)
end
local function update_map_texture (self, staticdata)
self.id = staticdata
local result = true
result = mcl_maps.load_map(self.id, function(texture)
-- will not crash even if self.object is invalid by now
-- update... quite possibly will screw up with each version of Minetest. >.<
if not texture then
minetest.log("error", "Failed to load the map texture using mcl_maps.")
end
self.object:set_properties({ textures = { texture } })
end)
if result ~= nil and result == false then
mintest.log("error", "[mcl_itemframes] Error setting up Map Item.")
end
end
local remove_item_entity = function(pos, node)
local name_found = false
local found_name_to_use = ""
for k, v in pairs(mcl_itemframes.frames_registered.glowing) do
if node.name == v then
name_found = true
found_name_to_use = v
break
end
end
-- try to cut down on excess looping, if possible.
if name_found == false then
for k, v in pairs(mcl_itemframes.frames_registered.standard) do
if node.name == v then
name_found = true
found_name_to_use = v
break
end
end
end
if mcl_itemframes.DEBUG then
minetest.log("action", "mcl_itemframes] remove_item_entity: " .. found_name_to_use .. "'s displayed item.")
end
-- node.name == "mcl_itemframes:item_frame" or node.name == "mcl_itemframes:glow_item_frame" or
if node.name == found_name_to_use then
for _, obj in pairs(minetest.get_objects_inside_radius(pos, 0.5)) do
local entity = obj:get_luaentity()
if entity then
-- remove old entities
if entity.name == "mcl_itemframes:item" or entity.name == "mcl_itemframes:glow_item" or entity.name == "mcl_itemframes:map" or entity.name == "mcl_itemframes:glow_map" then
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local item = inv:get_stack("main", 1)
if not item:is_empty() then
if (node.name == found_name_to_use) then
minetest.add_item(pos, item)
end
meta:set_string("infotext", "")
end
obj:remove()
end
if entity.name == found_name_to_use .. "_item" or entity.name == found_name_to_use .. "_map" then
if mcl_itemframes.DEBUG then
minetest.log("action", "mcl_itemframes] remove_item_entity: " .. entity.name .. "-- the item.")
end
obj:remove()
end
end
end
end
end
mcl_itemframes.update_item_entity = function(pos, node, param2)
if mcl_itemframes.DEBUG then
minetest.log("action", "[mcl_itemframes] Update_Generic_Item:\nPosition: " .. dump(pos) .. "\nNode: " .. dump(node))
end
remove_item_entity(pos, node)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local item = inv:get_stack("main", 1)
local name_found = false
local found_name_to_use = ""
local has_glow = false
for k, v in pairs(mcl_itemframes.frames_registered.glowing) do
if node.name == v then
name_found = true
has_glow = true
found_name_to_use = v
break
end
end
-- try to cut down on excess looping, if possible.
if name_found == false then
for k, v in pairs(mcl_itemframes.frames_registered.standard) do
if node.name == v then
name_found = true
has_glow = false
found_name_to_use = v
break
end
end
end
if name_found == false then
minetest.log("error", "[mcl_itemframes] Update_Generic_Item:\nFailed to find registered node:\nNode name - " .. node.name)
minetest.log("error", "[mcl_itemframes] Update_Generic_Item:\nRegistry definition:" .. dump(mcl_itemframes.frames_registered))
return
end
if not item:is_empty() then
-- update existing items placed.
if not param2 then
param2 = node.param2
end
local pos_adj = facedir[param2]
if node.name == found_name_to_use then
pos.x = pos.x + pos_adj.x * 6.5 / 16
pos.y = pos.y + pos_adj.y * 6.5 / 16
pos.z = pos.z + pos_adj.z * 6.5 / 16
if mcl_itemframes.DEBUG then
minetest.log("[mcl_itemframes] Update_Generic_Item:\nFound Name in Registry: " .. found_name_to_use)
end
end
local yaw = pi * 2 - param2 * pi / 2
local map_id = item:get_meta():get_string("mcl_maps:id")
local map_id_entity = {}
local map_id_lua = {}
if map_id == "" then
-- handle regular items placed into custom frame.
if mcl_itemframes.DEBUG then
minetest.log("action", "[mcl_itemframes] Update_Generic_Item:\nAdding entity: " .. node.name .. "_item")
end
if node.name == found_name_to_use then
map_id_entity = minetest.add_entity(pos, node.name .. "_item")
else
local debug_string = "[mcl_itemframes] Update_Generic_Item:\nCouldn't find node name in registry: "
minetest.log("error", debug_string .. found_name_to_use "\nregistry: " .. dump(mcl_itemframes.frames_registered))
return
end
map_id_lua = map_id_entity:get_luaentity()
map_id_lua._nodename = node.name
local itemname = item:get_name()
if itemname == "" or itemname == nil then
map_id_lua._texture = "blank.png"
map_id_lua._scale = 1
if has_glow then
map_id_lua.glow = glow_amount
end
else
map_id_lua._texture = itemname
local def = minetest.registered_items[itemname]
map_id_lua._scale = def and def.wield_scale and def.wield_scale.x or 1
end
if mcl_itemframes.DEBUG then
minetest.log("action", "[mcl_itemframes] Update_Generic_Item: item's name: " .. itemname)
end
map_id_lua:_update_texture()
if node.name == found_name_to_use then
map_id_entity:set_yaw(yaw)
else
minetest.log("error", "[mcl_itemframes] Update_Generic_Item: Failed to set Display Item's yaw. " .. node.name)
end
else
-- handle map items placed into custom frame.
if mcl_itemframes.DEBUG then
minetest.log("action", "[mcl_itemframes] Update_Generic_Item: Placing map in a " .. found_name_to_use .. " frame.")
end
if node.name == found_name_to_use then
map_id_entity = minetest.add_entity(pos, found_name_to_use .. "_map", map_id)
map_id_entity:set_yaw(yaw)
else
minetest.log("error", "[mcl_itemframes] Update_Generic_Item: Failed to set Map Item in " .. found_name_to_use .. "'s frame.")
end
end
-- finally, set the rotation (roll) of the displayed object.
local roll = meta:get_int("roll", 0)
set_roll(map_id_entity, roll)
end
end
function mcl_itemframes.drop_generic_item(pos, node, meta, clicker)
local name_found = false
local found_name_to_use = ""
for k, v in pairs(mcl_itemframes.frames_registered.glowing) do
if node.name == v then
name_found = true
found_name_to_use = v
break
end
end
-- try to cut down on excess looping, if possible.
if name_found == false then
for k, v in pairs(mcl_itemframes.frames_registered.standard) do
if node.name == v then
name_found = true
found_name_to_use = v
break
end
end
end
local cname = ""
if clicker and clicker:is_player() then
cname = clicker:get_player_name()
end
if not minetest.is_creative_enabled(cname) then
if (node.name == found_name_to_use) then
local inv = meta:get_inventory()
local item = inv:get_stack("main", 1)
if not item:is_empty() then
minetest.add_item(pos, item)
end
end
end
meta:set_string("infotext", "")
remove_item_entity(pos, node)
end
--- reworked to set up the base item definitions.
function mcl_itemframes.create_base_item_entity()
if mcl_itemframes.DEBUG then
minetest.log("action", "[mcl_itemframes] create_item_entity.")
end
--"mcl_itemframes:item",
frame_item_base = {
hp_max = 1,
visual = "wielditem",
visual_size = { x = VISUAL_SIZE, y = VISUAL_SIZE },
physical = false,
pointable = false,
textures = { "blank.png" },
_texture = "blank.png",
_scale = 1,
on_activate = function(self, staticdata)
if staticdata and staticdata ~= "" then
local data = staticdata:split(";")
if data and data[1] and data[2] then
self._nodename = data[1]
self._texture = data[2]
if data[3] then
self._scale = data[3]
else
self._scale = 1
end
end
end
if self._texture then
self.object:set_properties({
textures = { self._texture },
visual_size = { x = VISUAL_SIZE / self._scale, y = VISUAL_SIZE / self._scale },
})
end
end,
get_staticdata = function(self)
if self._nodename and self._texture then
local ret = self._nodename .. ";" .. self._texture
if self._scale then
ret = ret .. ";" .. self._scale
end
return ret
end
return ""
end,
_update_texture = function(self)
if self._texture then
self.object:set_properties({
textures = { self._texture },
visual_size = { x = VISUAL_SIZE / self._scale, y = VISUAL_SIZE / self._scale },
})
end
end,
}
-- "mcl_itemframes:map",
map_item_base = {
initial_properties = {
visual = "upright_sprite",
visual_size = { x = 1, y = 1 },
pointable = false,
physical = false,
collide_with_objects = false,
textures = { "blank.png" },
},
on_activate = function(self, staticdata)
if mcl_itemframes.DEBUG then
minetest.log("action", "[mcl_itemframes] map_item:on_activate.")
end
update_map_texture(self, staticdata)
end,
get_staticdata = function(self)
return self.id
end,
}
end
function mcl_itemframes.create_custom_items(name, has_glow)
local custom_frame_item = table.copy(frame_item_base)
local custom_frame_map_item = table.copy(map_item_base)
if has_glow then
custom_frame_map_item.glow = glow_amount
custom_frame_item.glow = glow_amount
if mcl_itemframes.DEBUG then
minetest.log("action", "\n[mcl_itemframes] create_custom_item_entity: glow name: " .. name .. "_item")
minetest.log("action", "[mcl_itemframes] create_custom_item_entity: glow name: " .. name .. "_map\n")
end
else
if mcl_itemframes.DEBUG then
minetest.log("action", "\n[mcl_itemframes] create_custom_item_entity: name: " .. name .. "_item")
minetest.log("action", "[mcl_itemframes] create_custom_item_entity: name: " .. name .. "_map\n")
end
end
minetest.register_entity(":" .. name .. "_item", custom_frame_item)
minetest.register_entity(":" .. name .. "_map", custom_frame_map_item)
end
function mcl_itemframes.update_frame_registry(modname, name, has_glow)
local mod_name_pass = false
if modname ~= "" and modname ~= "false" then
if minetest.get_modpath(modname) then
mod_name_pass = true
end
if mod_name_pass == false then
return
end
end
local frame = name -- should only be called within the create_frames functions.
if has_glow == true then
table.insert(mcl_itemframes.frames_registered.glowing, frame)
else
table.insert(mcl_itemframes.frames_registered.standard, frame)
end
end
--- name: The name used to distinguish the item frame. Prepends "mcl_itemframes:" to the name. Example usage:
--- "glow_item_frame" creates a node named ":mcl_itemframes:glow_item_frame".
function mcl_itemframes.create_custom_frame(modname, name, has_glow, tiles, color, ttframe, description, inv_wield_image)
local mod_name_pass = false
if modname ~= "" and modname ~= "false" then
if minetest.get_modpath(modname) then
mod_name_pass = true
end
if mod_name_pass == false then
return
end
end
if name == nil then
name = ""
end
if name == "" then
minetest.log("error", "attempted to create an item frame WITHOUT a name!")
return
end
if has_glow == nil or has_glow == "" then
has_glow = false
end
if tiles == nil or tiles == "" then
minetest.log("error", "No textures passed to Create_Custom_Frame!! Exiting frame creation.")
return
end
local working_name = "mcl_itemframes:" .. name
if mcl_itemframes.DEBUG then
minetest.log("action", "[mcl_itemframes] create_custom_frame: " .. working_name)
minetest.log("action", "[mcl_itemframes] create_custom_frame - calling create_custom_items " .. working_name)
end
-- make any special frame items.
mcl_itemframes.create_custom_items(working_name, has_glow)
local custom_itemframe_definition = {}
if has_glow == false then
custom_itemframe_definition = table.copy(mcl_itemframes.item_frame_base)
else
custom_itemframe_definition = table.copy(mcl_itemframes.glow_frame_base)
end
if inv_wield_image ~= nil and inv_wield_image ~= "" then
custom_itemframe_definition.glow_frame_base.inventory_image = { "(" .. inv_wield_image .. "^[multiply:" .. color .. ")" }
custom_itemframe_definition.glow_frame_base.wield_image = { "(" .. inv_wield_image .. "^[multiply:" .. color .. ")" }
end
custom_itemframe_definition.tiles = { "(" .. tiles .. "^[multiply:" .. color .. ")" }
custom_itemframe_definition._tt_help = ttframe
custom_itemframe_definition.description = description
minetest.register_node(":" .. working_name, custom_itemframe_definition)
mcl_itemframes.update_frame_registry(modname, working_name, has_glow)
mcl_itemframes.custom_register_lbm(working_name)
end
function mcl_itemframes.custom_register_lbm(name)
-- FIXME: Item entities can get destroyed by /clearobjects
-- glow frame
minetest.register_lbm({
label = "Respawn item frame item entities",
name = "mcl_itemframes:respawn_entities",
nodenames = { name },
run_at_every_load = true,
action = function(pos, node)
mcl_itemframes.update_item_entity(pos, node)
end,
})
end
function mcl_itemframes.create_base_definitions()
if mcl_itemframes.DEBUG then
minetest.log("action", "[mcl_itemframes] create_base_definitions.")
end
-- set up the facedir information.
facedir[0] = { x = 0, y = 0, z = 1 }
facedir[1] = { x = 1, y = 0, z = 0 }
facedir[2] = { x = 0, y = 0, z = -1 }
facedir[3] = { x = -1, y = 0, z = 0 }
mcl_itemframes.item_frame_base = {
description = S("Item Frame"),
_tt_help = S("Can hold an item"),
_doc_items_longdesc = S("Item frames are decorative blocks in which items can be placed."),
_doc_items_usagehelp = S("Just place any item on the item frame. Use the item frame again to retrieve the item."),
drawtype = "mesh",
is_ground_content = false,
mesh = "mcl_itemframes_itemframe1facedir.obj",
selection_box = { type = "fixed", fixed = { -6 / 16, -6 / 16, 7 / 16, 6 / 16, 6 / 16, 0.5 } },
collision_box = { type = "fixed", fixed = { -6 / 16, -6 / 16, 7 / 16, 6 / 16, 6 / 16, 0.5 } },
tiles = { "mcl_itemframes_item_frame_back.png", "mcl_itemframes_item_frame_back.png", "mcl_itemframes_item_frame_back.png", "mcl_itemframes_item_frame_back.png", "default_wood.png", "mcl_itemframes_item_frame_back.png" },
inventory_image = "mcl_itemframes_item_frame.png",
wield_image = "mcl_itemframes_item_frame.png",
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
paramtype = "light",
paramtype2 = "facedir",
sunlight_propagates = true,
groups = { dig_immediate = 3, deco_block = 1, dig_by_piston = 1, container = 7, attached_node_facedir = 1 },
sounds = mcl_sounds.node_sound_defaults(),
node_placement_prediction = "",
on_timer = function(pos)
local inv = minetest.get_meta(pos):get_inventory()
local stack = inv:get_stack("main", 1)
local itemname = stack:get_name()
if minetest.get_item_group(itemname, "clock") > 0 then
local new_name = "mcl_clock:clock_" .. (mcl_worlds.clock_works(pos) and mcl_clock.old_time or mcl_clock.random_frame)
if itemname ~= new_name then
stack:set_name(new_name)
inv:set_stack("main", 1, stack)
local node = minetest.get_node(pos)
mcl_itemframes.update_item_entity(pos, node, node.param2)
end
minetest.get_node_timer(pos):start(1.0)
end
end,
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then
return itemstack
end
-- Use pointed node's on_rightclick function first, if present
local node = minetest.get_node(pointed_thing.under)
if placer and not placer: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, placer, itemstack) or itemstack
end
end
return minetest.item_place(itemstack, placer, pointed_thing, minetest.dir_to_facedir(vector.direction(pointed_thing.above, pointed_thing.under)))
end,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
inv:set_size("main", 1)
end,
on_rightclick = function(pos, node, clicker, itemstack)
if not itemstack then
return
end
local pname = clicker:get_player_name()
if minetest.is_protected(pos, pname) then
minetest.record_protection_violation(pos, pname)
return
end
local meta = minetest.get_meta(pos)
mcl_itemframes.drop_generic_item(pos, node, meta, clicker)
local inv = meta:get_inventory()
if itemstack:is_empty() then
remove_item_entity(pos, node)
meta:set_string("infotext", "")
inv:set_stack("main", 1, "")
return itemstack
end
local put_itemstack = ItemStack(itemstack)
put_itemstack:set_count(1)
local itemname = put_itemstack:get_name()
if minetest.get_item_group(itemname, "compass") > 0 then
put_itemstack:set_name(mcl_compass.get_compass_itemname(pos, minetest.dir_to_yaw(minetest.facedir_to_dir(node.param2)), put_itemstack))
end
if minetest.get_item_group(itemname, "clock") > 0 then
minetest.get_node_timer(pos):start(1.0)
end
inv:set_stack("main", 1, put_itemstack)
mcl_itemframes.update_item_entity(pos, node)
-- Add node infotext when item has been named
local imeta = itemstack:get_meta()
local iname = imeta:get_string("name")
if iname then
meta:set_string("infotext", iname)
end
if not minetest.is_creative_enabled(clicker:get_player_name()) then
itemstack:take_item()
end
return itemstack
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return 0
else
return count
end
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return 0
else
return stack:get_count()
end
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return 0
else
return stack:get_count()
end
end,
on_destruct = function(pos)
local meta = minetest.get_meta(pos)
local node = minetest.get_node(pos)
mcl_itemframes.drop_generic_item(pos, node, meta)
end,
on_rotate = function(pos, node, user, mode, param2)
--local meta = minetest.get_meta(pos)
local node = minetest.get_node(pos)
local objs = nil
local name_found = false
local found_name_to_use = ""
name_found = false
found_name_to_use = ""
for k, v in pairs(mcl_itemframes.frames_registered.glowing) do
if node.name == v then
name_found = true
found_name_to_use = v
break
end
end
-- try to cut down on excess looping, if possible.
if name_found == false then
for k, v in pairs(mcl_itemframes.frames_registered.standard) do
if node.name == v then
name_found = true
found_name_to_use = v
break
end
end
end
if node.name == found_name_to_use then
objs = minetest.get_objects_inside_radius(pos, 0.5)
else
return -- short circuit if it's somehow not the right thing.
end
if objs then
if mode == screwdriver.ROTATE_FACE or mode == screwdriver.ROTATE_AXIS then
for _, obj in ipairs(objs) do
if obj and obj:get_luaentity() then
local obj_name = obj:get_luaentity().name
if obj_name == found_name_to_use .. "_item" then
if mode == screwdriver.ROTATE_AXIS then
update_roll(obj, pos)
end
break
end
end
end
return false
end
end
end,
}
-- make the base items for the base frames.
mcl_itemframes.create_base_item_entity()
-- minetest.register_node("mcl_itemframes:item_frame", mcl_itemframes.item_frame_base)
-- make glow frame from the base item_frame.
mcl_itemframes.glow_frame_base = table.copy(mcl_itemframes.item_frame_base)
mcl_itemframes.glow_frame_base.description = S("Glowing Item Frame")
mcl_itemframes.glow_frame_base._tt_help = S("Can hold an item and glows.")
mcl_itemframes.glow_frame_base.longdesc = S("Glowing item frames are decorative blocks in which items can be placed and made to glow.")
mcl_itemframes.glow_frame_base.tiles = { "mcl_itemframes_glow_item_frame.png" }
mcl_itemframes.glow_frame_base.inventory_image = "mcl_itemframes_glow_item_frame_item.png"
mcl_itemframes.glow_frame_base.wield_image = "mcl_itemframes_glow_item_frame.png"
mcl_itemframes.glow_frame_base.mesh = "mcl_itemframes_glow_item_frame.obj"
--[[
minetest.register_node("mcl_itemframes:glow_item_frame", mcl_itemframes.glow_frame_base)
mcl_itemframes.update_frame_registry("false", "mcl_itemframes:item_frame", false)
mcl_itemframes.update_frame_registry("false", "mcl_itemframes:glow_item_frame", true)
create_register_lbm("mcl_itemframes:item_frame")
create_register_lbm("mcl_itemframes:glow_item_frame")
--]]
end
-- for compatibility:
function mcl_itemframes.backwards_compatibility ()
minetest.register_lbm({
label = "Update legacy item frames",
name = "mcl_itemframes:update_legacy_item_frames",
nodenames = { "itemframes:frame" },
action = function(pos, node)
-- Swap legacy node, then respawn entity
node.name = "mcl_itemframes:item_frame"
local meta = minetest.get_meta(pos)
local item = meta:get_string("item")
minetest.swap_node(pos, node)
if item ~= "" then
local itemstack = ItemStack(minetest.deserialize(meta:get_string("itemdata")))
local inv = meta:get_inventory()
inv:set_size("main", 1)
if not itemstack:is_empty() then
inv:set_stack("main", 1, itemstack)
end
end
mcl_itemframes.update_item_entity(pos, node)
end,
})
minetest.register_alias("itemframes:frame", "mcl_itemframes:item_frame")
-- adds backwards compatibility
minetest.register_alias("mcl_itemframes:item", "mcl_itemframes:item_frame_item")
minetest.register_alias("mcl_itemframes:map", "mcl_itemframes:item_frame_map")
minetest.register_alias("mcl_itemframes:glow_item", "mcl_itemframes:glow_item_frame_item")
minetest.register_alias("mcl_itemframes:glow_map", "mcl_itemframes:glow_item_frame_map")
minetest.register_entity("mcl_itemframes:item", frame_item_base)
minetest.register_entity("mcl_itemframes:map", map_item_base)
minetest.register_entity("mcl_itemframes:glow_item", frame_item_base)
minetest.register_entity("mcl_itemframes:glow_map", map_item_base)
end

@ -0,0 +1,36 @@
The item frames use case is a very specific one, but... in the event that there is need for a new item frame then that
is where this api will shine.
As long as the api has been initialized (which it does in its own init.lua) then you really only need to call one
function. That function being mcl_itemframes.create_custom_frame(modname, name, has_glow, tiles, color, ttframe,
description, inv_wield_image). Note: unlike the Signs API, this API does not automatically create the recipe for you.
Here's an explanation of create_custom_frame and an example of using it.
This function is responsible for creating each frame, and handling the creation of its underlying entities.
Parameters:
* modname: Used to make sure that a specific module is installed before running the code contained within. Set to "" or
false, if there's not a mod to check for.
* name: The name used to distinguish the item frame. Prepends "mcl_itemframes:" to the name. Example usage:
"glow_item_frame" creates a node named "mcl_itemframes:glow_item_frame".
* has_glow: Does the frame cause the item within to glow? true / false.
* tiles: The image files used for the item frame's object texturing.
* color: Colorizes the frame / wield / inventory image to a specific color. Use White (#FFFFFF) to ignore.
* ttframe: The tooltip to show for the frame.
* description: The frame's description.
* inv_wield_image: Optionally the image to use as the inventory and the wield image. Colorized. set to "" or nil to use
the default frame / glow frame images. Note: must be set if you want the inventory / wield image to be colored.
example:
-- Register the Glow Frame
mcl_itemframes.create_custom_frame("false", "glow_item_frame", true,
"mcl_itemframes_glow_item_frame.png", mcl_colors.WHITE, "Glowing Item Frame",
"Can hold an item and glows.","")
-- Register the Glow Frame's recipe
minetest.register_craft({
type = "shapeless",
output = 'mcl_itemframes:glow_item_frame',
recipe = { 'mcl_mobitems:glow_ink_sac', 'mcl_itemframes:item_frame' },
})

@ -1,5 +1,8 @@
# textdomain: mcl_itemframes
Item Frame=Rahmen
Item frames are decorative blocks in which items can be placed.=Rahmen sind dekorative Blöcke, in denen man Gegenstände platzieren kann.
Just place any item on the item frame. Use the item frame again to retrieve the item.=Platzieren Sie einfach einen beliebigen Gegenstand in den Rahmen. Benutzen Sie den Rahmen erneut, um den Gegenstand zurück zu erhalten.
Can hold an item=Kann einen Gegenstand halten
Item Frame=Artikel Rahmen
Item frames are decorative blocks in which items can be placed.=Artikelrahmen sind dekorative Blöcke, in denen Artikel platziert werden können.
Just place any item on the item frame. Use the item frame again to retrieve the item.=Platzieren Sie einfach einen beliebigen Gegenstand auf dem Gegenstandsrahmen. Verwenden Sie den Artikelrahmen erneut, um den Artikel abzurufen.
Can hold an item.=Kann einen Gegenstand halten.
Glowing Item Frame=Leuchtender Gegenstandsrahmen
Glowing item frames are decorative blocks in which items can be placed and made to glow.=Leuchtende Gegenstandsrahmen sind dekorative Blöcke, in denen Gegenstände platziert und zum Leuchten gebracht werden können.
Can hold an item and glows.=Kann einen Gegenstand halten und leuchtet.

@ -1,5 +1,8 @@
# textdomain: mcl_itemframes
Item Frame=Marco
Item Frame=Cuadro de artículo
Item frames are decorative blocks in which items can be placed.=Los marcos de elementos son bloques decorativos en los que se pueden colocar elementos.
Just place any item on the item frame. Use the item frame again to retrieve the item.=Simplemente coloque cualquier artículo en el marco del artículo. Use el marco del artículo nuevamente para recuperar el artículo.
Just place any item on the item frame. Use the item frame again to retrieve the item.=Simplemente coloque cualquier elemento en el marco del elemento. Use el marco del elemento nuevamente para recuperar el elemento.
Can hold an item.=Puede contener un artículo.
Glowing Item Frame=Marco de artículo brillante
Glowing item frames are decorative blocks in which items can be placed and made to glow.=Los marcos de elementos brillantes son bloques decorativos en los que se pueden colocar elementos y hacer que brillen.
Can hold an item and glows.=Puede sostener un artículo y brilla.

@ -1,5 +1,8 @@
# textdomain: mcl_itemframes
Item Frame=Cadre
Item frames are decorative blocks in which items can be placed.=Les cadres sont des blocs décoratifs dans lesquels les objets peuvent être placés.
Just place any item on the item frame. Use the item frame again to retrieve the item.=Placez simplement n'importe quel objet sur le cadre. Utilisez à nouveau le cadre décoré pour récupérer l'élément.
Can hold an item=Peut contenir un objet
Item Frame=Cadre de l'article
Item frames are decorative blocks in which items can be placed.=Les cadres d'objets sont des blocs décoratifs dans lesquels des objets peuvent être placés.
Just place any item on the item frame. Use the item frame again to retrieve the item.=Placez simplement n'importe quel élément sur le cadre de l'élément. Utilisez à nouveau le cadre de l'objet pour récupérer l'objet.
Can hold an item.=Peut contenir un objet.
Glowing Item Frame=Cadre d'objet lumineux
Glowing item frames are decorative blocks in which items can be placed and made to glow.=Les cadres d'objets lumineux sont des blocs décoratifs dans lesquels des objets peuvent être placés et rendus brillants.
Can hold an item and glows.=Peut contenir un objet et brille.

@ -3,3 +3,10 @@ Item Frame=Ramka na przedmiot
Item frames are decorative blocks in which items can be placed.=Ramki na przedmiot to dekoracyjne bloki w których można umieszczać przedmioty.
Just place any item on the item frame. Use the item frame again to retrieve the item.=Umieść dowolny przedmiot w ramce. Użyj ramki ponownie aby odzyskać przedmiot.
Can hold an item=Może przetrzymywać przedmiot
Item Frame=Rama przedmiotu
Item frames are decorative blocks in which items can be placed.=Ramki na przedmioty to klocki ozdobne, w których można umieszczać przedmioty.
Just place any item on the item frame. Use the item frame again to retrieve the item.=Wystarczy umieścić dowolny przedmiot na ramie przedmiotu. Użyj ponownie ramki elementu, aby pobrać element.
Can hold an item.=Może pomieścić przedmiot.
Glowing Item Frame=Świecąca ramka na przedmiot
Glowing item frames are decorative blocks in which items can be placed and made to glow.=Świecące ramki na przedmioty to ozdobne bloki, w których można umieścić przedmioty i sprawić, by świeciły.
Can hold an item and glows.=Może trzymać przedmiot i świeci.

@ -3,3 +3,10 @@ Item Frame=Рамка
Item frames are decorative blocks in which items can be placed.=Рамки это декоративные блоки, в которые можно помещать предметы.
Just place any item on the item frame. Use the item frame again to retrieve the item.=Просто поместите в рамку любой предмет. Используйте рамку вновь, чтобы заполучить из неё предмет обратно.
Can hold an item=Может хранить предмет
Item Frame=Рамка предмета
Item frames are decorative blocks in which items can be placed.=Рамки предметов — это декоративные блоки, в которые можно помещать предметы.
Just place any item on the item frame. Use the item frame again to retrieve the item.=Просто поместите любой предмет на рамку предмета. Используйте рамку предмета снова, чтобы получить предмет.
Can hold an item.=Может держать предмет.
Glowing Item Frame=Светящаяся рамка предмета
Glowing item frames are decorative blocks in which items can be placed and made to glow.=Светящиеся рамки предметов — это декоративные блоки, в которые можно помещать предметы и заставлять их светиться.
Can hold an item and glows.=Может держать предмет и светится.

@ -3,3 +3,6 @@ Item Frame=
Item frames are decorative blocks in which items can be placed.=
Just place any item on the item frame. Use the item frame again to retrieve the item.=
Can hold an item=
Glow Item Frame=
Glow item frames are decorative blocks in which items can be placed.=
Can hold an item and glows=

@ -1,3 +1,2 @@
name = mcl_itemframes
depends = mcl_core, mcl_sounds, mcl_compass, mcl_maps
optional_depends = screwdriver
depends = mcl_core, mcl_sounds, mcl_compass, mcl_maps, screwdriver

@ -0,0 +1,156 @@
# Blender v2.76 (sub 0) OBJ File: 'itemframe1facedir.blend'
# www.blender.org
mtllib itemframe1facedir.mtl
o right.frame_Cube.005
v -0.313413 -0.313413 0.435326
v -0.313413 0.313413 0.435326
v -0.313413 -0.313413 0.498008
v -0.313413 0.313413 0.498008
v -0.376095 -0.313413 0.435326
v -0.376095 0.313413 0.435326
v -0.376095 -0.313413 0.498008
v -0.376095 0.313413 0.498008
vt 0.875000 0.812500
vt 0.812500 0.812500
vt 0.812500 0.187500
vt 0.875000 0.187500
vt 1.000000 0.812500
vt 0.937500 0.812500
vt 0.937500 0.187500
vt 1.000000 0.187500
vt -0.000000 0.937500
vt 0.062500 0.937500
vt 0.062500 1.000000
vt -0.000000 1.000000
vn 1.000000 0.000000 -0.000000
vn 0.000000 0.000000 1.000000
vn -1.000000 0.000000 0.000000
vn -0.000000 0.000000 -1.000000
vn 0.000000 -1.000000 -0.000000
vn 0.000000 1.000000 0.000000
usemtl None
s off
f 2/1/1 4/2/1 3/3/1 1/4/1
f 4/1/2 8/2/2 7/3/2 3/4/2
f 8/5/3 6/6/3 5/7/3 7/8/3
f 6/1/4 2/2/4 1/3/4 5/4/4
f 1/9/5 3/10/5 7/11/5 5/12/5
f 6/9/6 8/10/6 4/11/6 2/12/6
o left.frame_Cube.004
v 0.376095 -0.313413 0.435326
v 0.376095 0.313413 0.435326
v 0.376095 -0.313413 0.498008
v 0.376095 0.313413 0.498008
v 0.313413 -0.313413 0.435326
v 0.313413 0.313413 0.435326
v 0.313413 -0.313413 0.498008
v 0.313413 0.313413 0.498008
vt 0.875000 0.812500
vt 0.812500 0.812500
vt 0.812500 0.187500
vt 0.875000 0.187500
vt 1.000000 0.812500
vt 0.937500 0.812500
vt 0.937500 0.187500
vt 1.000000 0.187500
vt -0.000000 0.937500
vt 0.062500 0.937500
vt 0.062500 1.000000
vt -0.000000 1.000000
vn 1.000000 0.000000 -0.000000
vn 0.000000 0.000000 1.000000
vn -1.000000 0.000000 0.000000
vn 0.000000 0.000000 -1.000000
vn 0.000000 -1.000000 -0.000000
vn 0.000000 1.000000 0.000000
usemtl None
s off
f 10/13/7 12/14/7 11/15/7 9/16/7
f 12/13/8 16/14/8 15/15/8 11/16/8
f 16/17/9 14/18/9 13/19/9 15/20/9
f 14/13/10 10/14/10 9/15/10 13/16/10
f 9/21/11 11/22/11 15/23/11 13/24/11
f 14/21/12 16/22/12 12/23/12 10/24/12
o lower.frame_Cube.003
v 0.376095 -0.376095 0.435326
v 0.376095 -0.313413 0.435326
v 0.376095 -0.376095 0.498008
v 0.376095 -0.313413 0.498008
v -0.376095 -0.376095 0.435326
v -0.376095 -0.313413 0.435326
v -0.376095 -0.376095 0.498008
v -0.376095 -0.313413 0.498008
vt 0.187500 0.187500
vt 0.125000 0.187500
vt 0.125000 0.125000
vt 0.187500 0.125000
vt 0.875000 0.187500
vt 0.875000 0.125000
vt 0.812500 0.187500
vt 0.812500 0.125000
vt 0.875000 0.937500
vt 0.875000 1.000000
vt 0.125000 1.000000
vt 0.125000 0.937500
vn 1.000000 0.000000 0.000000
vn 0.000000 0.000000 1.000000
vn -1.000000 0.000000 0.000000
vn -0.000000 0.000000 -1.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 1.000000 0.000000
usemtl None
s off
f 18/25/13 20/26/13 19/27/13 17/28/13
f 20/29/14 24/26/14 23/27/14 19/30/14
f 24/29/15 22/31/15 21/32/15 23/30/15
f 22/29/16 18/26/16 17/27/16 21/30/16
f 17/33/17 19/34/17 23/35/17 21/36/17
f 22/30/18 24/29/18 20/26/18 18/27/18
o upper.frame_Cube.002
v 0.376095 0.313413 0.435326
v 0.376095 0.376095 0.435326
v 0.376095 0.313413 0.498008
v 0.376095 0.376095 0.498008
v -0.376095 0.313413 0.435326
v -0.376095 0.376095 0.435326
v -0.376095 0.313413 0.498008
v -0.376095 0.376095 0.498008
vt 0.187500 0.875000
vt 0.125000 0.875000
vt 0.125000 0.812500
vt 0.187500 0.812500
vt 0.875000 0.875000
vt 0.875000 0.812500
vt 0.812500 0.875000
vt 0.812500 0.812500
vt 0.875000 0.937500
vt 0.875000 1.000000
vt 0.125000 1.000000
vt 0.125000 0.937500
vn 1.000000 0.000000 0.000000
vn 0.000000 0.000000 1.000000
vn -1.000000 0.000000 0.000000
vn -0.000000 0.000000 -1.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 1.000000 0.000000
usemtl None
s off
f 26/37/19 28/38/19 27/39/19 25/40/19
f 28/41/20 32/38/20 31/39/20 27/42/20
f 32/41/21 30/43/21 29/44/21 31/42/21
f 30/41/22 26/38/22 25/39/22 29/42/22
f 25/45/23 27/46/23 31/47/23 29/48/23
f 30/48/24 32/38/24 28/41/24 26/45/24
o background_Plane
v 0.313413 -0.313413 0.466667
v -0.313413 -0.313413 0.466667
v 0.313413 0.313413 0.466667
v -0.313413 0.313413 0.466667
vt 0.187500 0.187500
vt 0.812500 0.187500
vt 0.812500 0.812500
vt 0.187500 0.812500
vn -0.000000 0.000000 -1.000000
usemtl None
s off
f 33/49/25 34/50/25 36/51/25 35/52/25

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

@ -62,7 +62,7 @@ function mcl_maps.create_map(pos)
local emin, emax = vm:read_from_map(minp, maxp)
local data = vm:get_data()
local param2data = vm:get_param2_data()
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local area = VoxelArea:new({ MinEdge = emin, MaxEdge = emax })
local pixels = {}
local last_heightmap
for x = 1, 128 do
@ -94,7 +94,7 @@ function mcl_maps.create_map(pos)
end
if def.palette then
local palette = palettes[texture]
color = palette and {palette = palette}
color = palette and { palette = palette }
else
color = texture_colors[texture]
end
@ -129,7 +129,7 @@ function mcl_maps.create_map(pos)
end
heightmap[z] = height or minp.y
pixels[z] = pixels[z] or {}
pixels[z][x] = color or {0, 0, 0}
pixels[z][x] = color or { 0, 0, 0 }
end
last_heightmap = heightmap
end
@ -141,30 +141,43 @@ end
function mcl_maps.load_map(id, callback)
if id == "" or creating_maps[id] then
return
return false
end
local texture = "mcl_maps_map_texture_" .. id .. ".tga"
local result = true
if not loaded_maps[id] then
if not minetest.features.dynamic_add_media_table then
-- minetest.dynamic_add_media() blocks in
-- Minetest 5.3 and 5.4 until media loads
loaded_maps[id] = true
dynamic_add_media(map_textures_path .. texture, function() end)
if callback then callback(texture) end
result = dynamic_add_media(map_textures_path .. texture, function()
end)
if callback then
callback(texture)
end
else
-- minetest.dynamic_add_media() never blocks
-- in Minetest 5.5, callback runs after load
dynamic_add_media(map_textures_path .. texture, function()
result = dynamic_add_media(map_textures_path .. texture, function()
loaded_maps[id] = true
if callback then callback(texture) end
if callback then
callback(texture)
end
end)
end
end
if result == false then
return false
end
if loaded_maps[id] then
if callback then callback(texture) end
if callback then
callback(texture)
end
return texture
end
end
@ -213,7 +226,7 @@ local filled_def = {
_doc_items_usagehelp = S("Hold the map in your hand. This will display a map on your screen."),
inventory_image = "mcl_maps_map_filled.png^(mcl_maps_map_filled_markings.png^[colorize:#000000)",
stack_max = 64,
groups = {not_in_creative_inventory = 1, filled_map = 1, tool = 1},
groups = { not_in_creative_inventory = 1, filled_map = 1, tool = 1 },
}
minetest.register_craftitem("mcl_maps:filled_map", filled_def)
@ -221,7 +234,7 @@ minetest.register_craftitem("mcl_maps:filled_map", filled_def)
local filled_wield_def = table.copy(filled_def)
filled_wield_def.use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false
filled_wield_def.visual_scale = 1
filled_wield_def.wield_scale = {x = 1, y = 1, z = 1}
filled_wield_def.wield_scale = { x = 1, y = 1, z = 1 }
filled_wield_def.paramtype = "light"
filled_wield_def.drawtype = "mesh"
filled_wield_def.node_placement_prediction = ""
@ -239,20 +252,20 @@ if mcl_skins_enabled then
local female = table.copy(filled_wield_def)
female._mcl_hand_id = skin.id
female.mesh = "mcl_meshhand_female.b3d"
female.tiles = {skin.texture}
female.tiles = { skin.texture }
minetest.register_node("mcl_maps:filled_map_" .. skin.id, female)
else
local male = table.copy(filled_wield_def)
male._mcl_hand_id = skin.id
male.mesh = "mcl_meshhand.b3d"
male.tiles = {skin.texture}
male.tiles = { skin.texture }
minetest.register_node("mcl_maps:filled_map_" .. skin.id, male)
end
end
else
filled_wield_def._mcl_hand_id = "hand"
filled_wield_def.mesh = "mcl_meshhand.b3d"
filled_wield_def.tiles = {"character.png"}
filled_wield_def.tiles = { "character.png" }
minetest.register_node("mcl_maps:filled_map_hand", filled_wield_def)
end
@ -286,7 +299,7 @@ minetest.register_craft({
minetest.register_craft({
type = "shapeless",
output = "mcl_maps:filled_map 2",
recipe = {"group:filled_map", "mcl_maps:empty_map"},
recipe = { "group:filled_map", "mcl_maps:empty_map" },
})
local function on_craft(itemstack, player, old_craft_grid, craft_inv)
@ -310,13 +323,13 @@ minetest.register_on_joinplayer(function(player)
local map_def = {
hud_elem_type = "image",
text = "blank.png",
position = {x = 0.75, y = 0.8},
alignment = {x = 0, y = -1},
offset = {x = 0, y = 0},
scale = {x = 2, y = 2},
position = { x = 0.75, y = 0.8 },
alignment = { x = 0, y = -1 },
offset = { x = 0, y = 0 },
scale = { x = 2, y = 2 },
}
local marker_def = table.copy(map_def)
marker_def.alignment = {x = 0, y = 0}
marker_def.alignment = { x = 0, y = 0 }
huds[player] = {
map = player:hud_add(map_def),
marker = player:hud_add(marker_def),
@ -376,7 +389,7 @@ minetest.register_globalstep(function(dtime)
end
player:hud_change(hud.marker, "text", marker)
player:hud_change(hud.marker, "offset", {x = (6 - 140 / 2 + pos.x - minp.x) * 2, y = (6 - 140 + maxp.z - pos.z) * 2})
player:hud_change(hud.marker, "offset", { x = (6 - 140 / 2 + pos.x - minp.x) * 2, y = (6 - 140 + maxp.z - pos.z) * 2 })
elseif maps[player] then
player:hud_change(hud.map, "text", "blank.png")
player:hud_change(hud.marker, "text", "blank.png")