forked from VoxeLibre/VoxeLibre
Banners: Respawn entity if it got lost
Entity is respawned on load (in an LBM) or when the banner node is punched. Also, the banner drop is now handled in the node instead of the entity.
This commit is contained in:
parent
eb7c8371ac
commit
267a697fab
|
@ -32,6 +32,11 @@ mcl_banners.colors = {
|
||||||
["unicolor_light_blue"] = {"light_blue", "Light Blue Banner", "mcl_wool:light_blue", "#4040CF", "mcl_dye:lightblue", "Light Blue" },
|
["unicolor_light_blue"] = {"light_blue", "Light Blue Banner", "mcl_wool:light_blue", "#4040CF", "mcl_dye:lightblue", "Light Blue" },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local colors_reverse = {}
|
||||||
|
for k,v in pairs(mcl_banners.colors) do
|
||||||
|
colors_reverse["mcl_banners:banner_item_"..v[1]] = k
|
||||||
|
end
|
||||||
|
|
||||||
-- Add pattern/emblazoning crafting recipes
|
-- Add pattern/emblazoning crafting recipes
|
||||||
dofile(minetest.get_modpath("mcl_banners").."/patterncraft.lua")
|
dofile(minetest.get_modpath("mcl_banners").."/patterncraft.lua")
|
||||||
|
|
||||||
|
@ -42,28 +47,40 @@ local layer_ratio = 255
|
||||||
local standing_banner_entity_offset = { x=0, y=-0.499, z=0 }
|
local standing_banner_entity_offset = { x=0, y=-0.499, z=0 }
|
||||||
local hanging_banner_entity_offset = { x=0, y=-1.7, z=0 }
|
local hanging_banner_entity_offset = { x=0, y=-1.7, z=0 }
|
||||||
|
|
||||||
local on_destruct_standing_banner = function(pos)
|
local on_destruct_banner = function(pos, hanging)
|
||||||
|
local offset, nodename
|
||||||
|
if hanging then
|
||||||
|
offset = hanging_banner_entity_offset
|
||||||
|
nodename = "mcl_banners:hanging_banner"
|
||||||
|
else
|
||||||
|
offset = standing_banner_entity_offset
|
||||||
|
nodename = "mcl_banners:standing_banner"
|
||||||
|
end
|
||||||
-- Find this node's banner entity and make it drop as an item
|
-- Find this node's banner entity and make it drop as an item
|
||||||
local checkpos = vector.add(pos, standing_banner_entity_offset)
|
local checkpos = vector.add(pos, offset)
|
||||||
local objects = minetest.get_objects_inside_radius(checkpos, 0.5)
|
local objects = minetest.get_objects_inside_radius(checkpos, 0.5)
|
||||||
for _, v in ipairs(objects) do
|
for _, v in ipairs(objects) do
|
||||||
local ent = v:get_luaentity()
|
local ent = v:get_luaentity()
|
||||||
if ent and ent.name == "mcl_banners:standing_banner" then
|
if ent and ent.name == nodename then
|
||||||
v:get_luaentity():_drop()
|
v:remove()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
-- Drop item
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local item = meta:get_inventory():get_stack("banner", 1)
|
||||||
|
if not item:is_empty() then
|
||||||
|
minetest.add_item(pos, item)
|
||||||
|
else
|
||||||
|
minetest.add_item(pos, "mcl_banners:banner_item_white")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local on_destruct_standing_banner = function(pos)
|
||||||
|
return on_destruct_banner(pos, false)
|
||||||
end
|
end
|
||||||
|
|
||||||
local on_destruct_hanging_banner = function(pos)
|
local on_destruct_hanging_banner = function(pos)
|
||||||
-- Find this node's banner entity and make it drop as an item
|
return on_destruct_banner(pos, true)
|
||||||
local checkpos = vector.add(pos, hanging_banner_entity_offset)
|
|
||||||
local objects = minetest.get_objects_inside_radius(checkpos, 0.5)
|
|
||||||
for _, v in ipairs(objects) do
|
|
||||||
local ent = v:get_luaentity()
|
|
||||||
if ent and ent.name == "mcl_banners:hanging_banner" then
|
|
||||||
v:get_luaentity():_drop()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local make_banner_texture = function(base_color, layers)
|
local make_banner_texture = function(base_color, layers)
|
||||||
|
@ -96,6 +113,59 @@ local make_banner_texture = function(base_color, layers)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local spawn_banner_entity = function(pos, hanging, itemstack)
|
||||||
|
local banner
|
||||||
|
if hanging then
|
||||||
|
banner = minetest.add_entity(pos, "mcl_banners:hanging_banner")
|
||||||
|
else
|
||||||
|
banner = minetest.add_entity(pos, "mcl_banners:standing_banner")
|
||||||
|
end
|
||||||
|
if banner == nil then
|
||||||
|
return banner
|
||||||
|
end
|
||||||
|
local imeta = itemstack:get_meta()
|
||||||
|
local layers_raw = imeta:get_string("layers")
|
||||||
|
local layers = minetest.deserialize(layers_raw)
|
||||||
|
local colorid = colors_reverse[itemstack:get_name()]
|
||||||
|
banner:get_luaentity():_set_textures(colorid, layers)
|
||||||
|
local mname = imeta:get_string("name")
|
||||||
|
if mname ~= nil and mname ~= "" then
|
||||||
|
banner:get_luaentity()._item_name = mname
|
||||||
|
banner:get_luaentity()._item_description = imeta:get_string("description")
|
||||||
|
end
|
||||||
|
|
||||||
|
return banner
|
||||||
|
end
|
||||||
|
|
||||||
|
local respawn_banner_entity = function(pos, node)
|
||||||
|
local hanging = node.name == "mcl_banners:hanging_banner"
|
||||||
|
local offset
|
||||||
|
if hanging then
|
||||||
|
offset = hanging_banner_entity_offset
|
||||||
|
else
|
||||||
|
offset = standing_banner_entity_offset
|
||||||
|
end
|
||||||
|
-- Check if a banner entity already exists
|
||||||
|
local bpos = vector.add(pos, offset)
|
||||||
|
local objects = minetest.get_objects_inside_radius(bpos, 0.5)
|
||||||
|
for _, v in ipairs(objects) do
|
||||||
|
local ent = v:get_luaentity()
|
||||||
|
if ent and (ent.name == "mcl_banners:standing_banner" or ent.name == "mcl_banners:hanging_banner") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Spawn new entity
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local banner_item = meta:get_inventory():get_stack("banner", 1)
|
||||||
|
local banner_entity = spawn_banner_entity(bpos, hanging, banner_item)
|
||||||
|
|
||||||
|
-- Set rotation
|
||||||
|
local final_yaw
|
||||||
|
local rotation_level = meta:get_int("rotation_level")
|
||||||
|
final_yaw = (rotation_level * (math.pi/8)) + math.pi
|
||||||
|
banner_entity:set_yaw(final_yaw)
|
||||||
|
end
|
||||||
|
|
||||||
local on_rotate
|
local on_rotate
|
||||||
if minetest.get_modpath("screwdriver") then
|
if minetest.get_modpath("screwdriver") then
|
||||||
on_rotate = screwdriver.disallow
|
on_rotate = screwdriver.disallow
|
||||||
|
@ -138,6 +208,9 @@ minetest.register_node("mcl_banners:standing_banner", {
|
||||||
drop = "", -- Item drops are handled in entity code
|
drop = "", -- Item drops are handled in entity code
|
||||||
|
|
||||||
on_destruct = on_destruct_standing_banner,
|
on_destruct = on_destruct_standing_banner,
|
||||||
|
on_punch = function(pos, node)
|
||||||
|
respawn_banner_entity(pos, node)
|
||||||
|
end,
|
||||||
_mcl_hardness = 1,
|
_mcl_hardness = 1,
|
||||||
_mcl_blast_resistance = 5,
|
_mcl_blast_resistance = 5,
|
||||||
})
|
})
|
||||||
|
@ -166,6 +239,9 @@ minetest.register_node("mcl_banners:hanging_banner", {
|
||||||
drop = "", -- Item drops are handled in entity code
|
drop = "", -- Item drops are handled in entity code
|
||||||
|
|
||||||
on_destruct = on_destruct_hanging_banner,
|
on_destruct = on_destruct_hanging_banner,
|
||||||
|
on_punch = function(pos, node)
|
||||||
|
respawn_banner_entity(pos, node)
|
||||||
|
end,
|
||||||
_mcl_hardness = 1,
|
_mcl_hardness = 1,
|
||||||
_mcl_blast_resistance = 5,
|
_mcl_blast_resistance = 5,
|
||||||
on_rotate = on_rotate,
|
on_rotate = on_rotate,
|
||||||
|
@ -269,48 +345,61 @@ for colorid, colortab in pairs(mcl_banners.colors) do
|
||||||
end
|
end
|
||||||
hanging = true
|
hanging = true
|
||||||
end
|
end
|
||||||
|
|
||||||
local place_pos
|
local place_pos
|
||||||
if minetest.registered_nodes[node_under.name].buildable_to then
|
if minetest.registered_nodes[node_under.name].buildable_to then
|
||||||
place_pos = under
|
place_pos = under
|
||||||
else
|
else
|
||||||
place_pos = above
|
place_pos = above
|
||||||
end
|
end
|
||||||
if hanging then
|
local bnode = minetest.get_node(place_pos)
|
||||||
place_pos = vector.add(place_pos, hanging_banner_entity_offset)
|
if bnode.name ~= "mcl_banners:standing_banner" and bnode.name ~= "mcl_banners:hanging_banner" then
|
||||||
else
|
minetest.log("error", "[mcl_banners] The placed banner node is not what the mod expected!")
|
||||||
place_pos = vector.add(place_pos, standing_banner_entity_offset)
|
return itemstack
|
||||||
end
|
end
|
||||||
|
local meta = minetest.get_meta(place_pos)
|
||||||
|
local inv = meta:get_inventory()
|
||||||
|
inv:set_size("banner", 1)
|
||||||
|
local store_stack = ItemStack(itemstack)
|
||||||
|
store_stack:set_count(1)
|
||||||
|
inv:set_stack("banner", 1, store_stack)
|
||||||
|
|
||||||
local banner
|
-- Spawn entity
|
||||||
|
local entity_place_pos
|
||||||
if hanging then
|
if hanging then
|
||||||
banner = minetest.add_entity(place_pos, "mcl_banners:hanging_banner")
|
entity_place_pos = vector.add(place_pos, hanging_banner_entity_offset)
|
||||||
else
|
else
|
||||||
banner = minetest.add_entity(place_pos, "mcl_banners:standing_banner")
|
entity_place_pos = vector.add(place_pos, standing_banner_entity_offset)
|
||||||
end
|
end
|
||||||
local imeta = itemstack:get_meta()
|
local banner_entity = spawn_banner_entity(entity_place_pos, hanging, itemstack)
|
||||||
local layers_raw = imeta:get_string("layers")
|
|
||||||
local layers = minetest.deserialize(layers_raw)
|
|
||||||
banner:get_luaentity():_set_textures(colorid, layers)
|
|
||||||
local mname = imeta:get_string("name")
|
|
||||||
if mname ~= nil and mname ~= "" then
|
|
||||||
banner:get_luaentity()._item_name = mname
|
|
||||||
banner:get_luaentity()._item_description = imeta:get_string("description")
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set rotation
|
-- Set rotation
|
||||||
local final_yaw
|
local final_yaw, rotation_level
|
||||||
if hanging then
|
if hanging then
|
||||||
local pdir = vector.direction(pointed_thing.under, pointed_thing.above)
|
local pdir = vector.direction(pointed_thing.under, pointed_thing.above)
|
||||||
final_yaw = minetest.dir_to_yaw(pdir)
|
final_yaw = minetest.dir_to_yaw(pdir)
|
||||||
|
if pdir.x > 0 then
|
||||||
|
rotation_level = 4
|
||||||
|
elseif pdir.z > 0 then
|
||||||
|
rotation_level = 8
|
||||||
|
elseif pdir.x < 0 then
|
||||||
|
rotation_level = 12
|
||||||
|
else
|
||||||
|
rotation_level = 0
|
||||||
|
end
|
||||||
else
|
else
|
||||||
-- Determine the rotation based on player's yaw
|
-- Determine the rotation based on player's yaw
|
||||||
local yaw = placer:get_look_horizontal()
|
local yaw = placer:get_look_horizontal()
|
||||||
-- Select one of 16 possible rotations (0-15)
|
-- Select one of 16 possible rotations (0-15)
|
||||||
local rotation_level = round((yaw / (math.pi*2)) * 16)
|
rotation_level = round((yaw / (math.pi*2)) * 16)
|
||||||
|
if rotation_level >= 16 then
|
||||||
|
rotation_level = 0
|
||||||
|
end
|
||||||
final_yaw = (rotation_level * (math.pi/8)) + math.pi
|
final_yaw = (rotation_level * (math.pi/8)) + math.pi
|
||||||
end
|
end
|
||||||
banner:set_yaw(final_yaw)
|
meta:set_int("rotation_level", rotation_level)
|
||||||
|
|
||||||
|
if banner_entity ~= nil then
|
||||||
|
banner_entity:set_yaw(final_yaw)
|
||||||
|
end
|
||||||
|
|
||||||
if not minetest.settings:get_bool("creative_mode") then
|
if not minetest.settings:get_bool("creative_mode") then
|
||||||
itemstack:take_item()
|
itemstack:take_item()
|
||||||
|
@ -392,30 +481,6 @@ local entity_standing = {
|
||||||
self.object:set_armor_groups({immortal=1})
|
self.object:set_armor_groups({immortal=1})
|
||||||
end,
|
end,
|
||||||
|
|
||||||
-- This is a custom function which causes the banner to be dropped as item and destroys the entity.
|
|
||||||
_drop = function(self)
|
|
||||||
local pos = self.object:get_pos()
|
|
||||||
pos.y = pos.y + 1
|
|
||||||
|
|
||||||
if not minetest.settings:get_bool("creative_mode") and self._base_color then
|
|
||||||
-- Spawn item
|
|
||||||
local banner = ItemStack("mcl_banners:banner_item_"..mcl_banners.colors[self._base_color][1])
|
|
||||||
local meta = banner:get_meta()
|
|
||||||
meta:set_string("layers", minetest.serialize(self._layers))
|
|
||||||
if self._item_name ~= nil and self._item_name ~= "" then
|
|
||||||
meta:set_string("description", self._item_description)
|
|
||||||
meta:set_string("name", self._item_name)
|
|
||||||
else
|
|
||||||
meta:set_string("description", mcl_banners.make_advanced_banner_description(banner:get_definition().description, self._layers))
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.add_item(pos, banner)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Destroy entity
|
|
||||||
self.object:remove()
|
|
||||||
end,
|
|
||||||
|
|
||||||
-- Set the banner textures. This function can be used by external mods.
|
-- Set the banner textures. This function can be used by external mods.
|
||||||
-- Meaning of parameters:
|
-- Meaning of parameters:
|
||||||
-- * self: Lua entity reference to entity.
|
-- * self: Lua entity reference to entity.
|
||||||
|
@ -436,6 +501,17 @@ local entity_hanging = table.copy(entity_standing)
|
||||||
entity_hanging.mesh = "amc_banner_hanging.b3d"
|
entity_hanging.mesh = "amc_banner_hanging.b3d"
|
||||||
minetest.register_entity("mcl_banners:hanging_banner", entity_hanging)
|
minetest.register_entity("mcl_banners:hanging_banner", entity_hanging)
|
||||||
|
|
||||||
|
-- FIXME: Prevent entity destruction by /clearobjects
|
||||||
|
minetest.register_lbm({
|
||||||
|
label = "Respawn banner entities",
|
||||||
|
name = "mcl_banners:respawn_entities",
|
||||||
|
run_at_every_load = true,
|
||||||
|
nodenames = {"mcl_banners:standing_banner", "mcl_banners:hanging_banner"},
|
||||||
|
action = function(pos, node)
|
||||||
|
respawn_banner_entity(pos, node)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
type = "fuel",
|
type = "fuel",
|
||||||
recipe = "group:banner",
|
recipe = "group:banner",
|
||||||
|
|
Loading…
Reference in New Issue