forked from Mirrorlandia_minetest/minetest
master #7
@ -33,6 +33,8 @@ core.features = {
|
|||||||
random_state_restore = true,
|
random_state_restore = true,
|
||||||
after_order_expiry_registration = true,
|
after_order_expiry_registration = true,
|
||||||
wallmounted_rotate = true,
|
wallmounted_rotate = true,
|
||||||
|
item_specific_pointabilities = true,
|
||||||
|
blocking_pointability_type = true,
|
||||||
}
|
}
|
||||||
|
|
||||||
function core.has_feature(arg)
|
function core.has_feature(arg)
|
||||||
|
@ -5298,6 +5298,10 @@ Utilities
|
|||||||
-- wallmounted nodes mounted at floor or ceiling may additionally
|
-- wallmounted nodes mounted at floor or ceiling may additionally
|
||||||
-- be rotated by 90° with special param2 values (5.9.0)
|
-- be rotated by 90° with special param2 values (5.9.0)
|
||||||
wallmounted_rotate = true,
|
wallmounted_rotate = true,
|
||||||
|
-- Availability of the `pointabilities` property in the item definition (5.9.0)
|
||||||
|
item_specific_pointabilities = true,
|
||||||
|
-- Nodes `pointable` property can be `"blocking"` (5.9.0)
|
||||||
|
blocking_pointability_type = true,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -8382,7 +8386,9 @@ Player properties need to be saved manually.
|
|||||||
|
|
||||||
|
|
||||||
pointable = true,
|
pointable = true,
|
||||||
-- Whether the object can be pointed at
|
-- Can be `true` if it is pointable, `false` if it can be pointed through,
|
||||||
|
-- or `"blocking"` if it is pointable but not selectable.
|
||||||
|
-- Can be overridden by the `pointabilities` of the held item.
|
||||||
|
|
||||||
visual = "cube" / "sprite" / "upright_sprite" / "mesh" / "wielditem" / "item",
|
visual = "cube" / "sprite" / "upright_sprite" / "mesh" / "wielditem" / "item",
|
||||||
-- "cube" is a node-sized cube.
|
-- "cube" is a node-sized cube.
|
||||||
@ -8746,6 +8752,27 @@ Used by `minetest.register_node`, `minetest.register_craftitem`, and
|
|||||||
-- If true, item can point to all liquid nodes (`liquidtype ~= "none"`),
|
-- If true, item can point to all liquid nodes (`liquidtype ~= "none"`),
|
||||||
-- even those for which `pointable = false`
|
-- even those for which `pointable = false`
|
||||||
|
|
||||||
|
pointabilities = {
|
||||||
|
nodes = {
|
||||||
|
["default:stone"] = "blocking",
|
||||||
|
["group:leaves"] = false,
|
||||||
|
},
|
||||||
|
objects = {
|
||||||
|
["modname:entityname"] = true,
|
||||||
|
["group:ghosty"] = true, -- (an armor group)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
-- Contains lists to override the `pointable` property of pointed nodes and objects.
|
||||||
|
-- The index can be a node/entity name or a group with the prefix `"group:"`.
|
||||||
|
-- (For objects `armor_groups` are used and for players the entity name is irrelevant.)
|
||||||
|
-- If multiple fields fit, the following priority order is applied:
|
||||||
|
-- value of matching node/entity name
|
||||||
|
-- `true` for any group
|
||||||
|
-- `false` for any group
|
||||||
|
-- `"blocking"` for any group
|
||||||
|
-- `liquids_pointable` if it is a liquid node
|
||||||
|
-- `pointable` property of the node or object
|
||||||
|
|
||||||
light_source = 0,
|
light_source = 0,
|
||||||
-- When used for nodes: Defines amount of light emitted by node.
|
-- When used for nodes: Defines amount of light emitted by node.
|
||||||
-- Otherwise: Defines texture glow when viewed as a dropped item
|
-- Otherwise: Defines texture glow when viewed as a dropped item
|
||||||
@ -8971,7 +8998,11 @@ Used by `minetest.register_node`.
|
|||||||
|
|
||||||
walkable = true, -- If true, objects collide with node
|
walkable = true, -- If true, objects collide with node
|
||||||
|
|
||||||
pointable = true, -- If true, can be pointed at
|
pointable = true,
|
||||||
|
-- Can be `true` if it is pointable, `false` if it can be pointed through,
|
||||||
|
-- or `"blocking"` if it is pointable but not selectable.
|
||||||
|
-- Can be overridden by the `pointabilities` of the held item.
|
||||||
|
-- A client may be able to point non-pointable nodes, since it isn't checked server-side.
|
||||||
|
|
||||||
diggable = true, -- If false, can never be dug
|
diggable = true, -- If false, can never be dug
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
dofile(minetest.get_modpath("testentities").."/visuals.lua")
|
dofile(minetest.get_modpath("testentities").."/visuals.lua")
|
||||||
dofile(minetest.get_modpath("testentities").."/selectionbox.lua")
|
dofile(minetest.get_modpath("testentities").."/selectionbox.lua")
|
||||||
dofile(minetest.get_modpath("testentities").."/armor.lua")
|
dofile(minetest.get_modpath("testentities").."/armor.lua")
|
||||||
|
dofile(minetest.get_modpath("testentities").."/pointable.lua")
|
||||||
|
23
games/devtest/mods/testentities/pointable.lua
Normal file
23
games/devtest/mods/testentities/pointable.lua
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
-- Pointability test Entities
|
||||||
|
|
||||||
|
-- Register wrapper for compactness
|
||||||
|
local function register_pointable_testentity(name, pointable)
|
||||||
|
local texture = "testnodes_"..name..".png"
|
||||||
|
minetest.register_entity("testentities:"..name, {
|
||||||
|
initial_properties = {
|
||||||
|
visual = "cube",
|
||||||
|
visual_size = {x = 0.6, y = 0.6, z = 0.6},
|
||||||
|
textures = {
|
||||||
|
texture, texture, texture, texture, texture, texture
|
||||||
|
},
|
||||||
|
pointable = pointable,
|
||||||
|
},
|
||||||
|
on_activate = function(self)
|
||||||
|
self.object:set_armor_groups({[name.."_test"] = 1})
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
register_pointable_testentity("pointable", true)
|
||||||
|
register_pointable_testentity("not_pointable", false)
|
||||||
|
register_pointable_testentity("blocking_pointable", "blocking")
|
@ -663,3 +663,23 @@ minetest.register_node("testnodes:post_effect_color_shaded_true", {
|
|||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
groups = {dig_immediate=3},
|
groups = {dig_immediate=3},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
-- Pointability
|
||||||
|
|
||||||
|
-- Register wrapper for compactness
|
||||||
|
local function register_pointable_test_node(name, description, pointable)
|
||||||
|
local texture = "testnodes_"..name..".png"
|
||||||
|
minetest.register_node("testnodes:"..name, {
|
||||||
|
description = S(description),
|
||||||
|
tiles = {texture},
|
||||||
|
drawtype = "glasslike_framed",
|
||||||
|
paramtype = "light",
|
||||||
|
walkable = false,
|
||||||
|
pointable = pointable,
|
||||||
|
groups = {dig_immediate=3, [name.."_test"]=1},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
register_pointable_test_node("pointable", "Pointable Node", true)
|
||||||
|
register_pointable_test_node("not_pointable", "Not Pointable Node", false)
|
||||||
|
register_pointable_test_node("blocking_pointable", "Blocking Pointable Node", "blocking")
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 150 B |
Binary file not shown.
After Width: | Height: | Size: 152 B |
BIN
games/devtest/mods/testnodes/textures/testnodes_pointable.png
Normal file
BIN
games/devtest/mods/testnodes/textures/testnodes_pointable.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 144 B |
@ -7,6 +7,20 @@ dofile(minetest.get_modpath("testtools") .. "/light.lua")
|
|||||||
dofile(minetest.get_modpath("testtools") .. "/privatizer.lua")
|
dofile(minetest.get_modpath("testtools") .. "/privatizer.lua")
|
||||||
dofile(minetest.get_modpath("testtools") .. "/particles.lua")
|
dofile(minetest.get_modpath("testtools") .. "/particles.lua")
|
||||||
|
|
||||||
|
local pointabilities_nodes = {
|
||||||
|
nodes = {
|
||||||
|
["group:blocking_pointable_test"] = true,
|
||||||
|
["group:not_pointable_test"] = true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
local pointabilities_objects = {
|
||||||
|
objects = {
|
||||||
|
["group:blocking_pointable_test"] = true,
|
||||||
|
["group:not_pointable_test"] = true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
minetest.register_tool("testtools:param2tool", {
|
minetest.register_tool("testtools:param2tool", {
|
||||||
description = S("Param2 Tool") .."\n"..
|
description = S("Param2 Tool") .."\n"..
|
||||||
S("Modify param2 value of nodes") .."\n"..
|
S("Modify param2 value of nodes") .."\n"..
|
||||||
@ -16,6 +30,7 @@ minetest.register_tool("testtools:param2tool", {
|
|||||||
S("Sneak+Place: -8"),
|
S("Sneak+Place: -8"),
|
||||||
inventory_image = "testtools_param2tool.png",
|
inventory_image = "testtools_param2tool.png",
|
||||||
groups = { testtool = 1, disable_repair = 1 },
|
groups = { testtool = 1, disable_repair = 1 },
|
||||||
|
pointabilities = pointabilities_nodes,
|
||||||
on_use = function(itemstack, user, pointed_thing)
|
on_use = function(itemstack, user, pointed_thing)
|
||||||
local pos = minetest.get_pointed_thing_position(pointed_thing)
|
local pos = minetest.get_pointed_thing_position(pointed_thing)
|
||||||
if pointed_thing.type ~= "node" or (not pos) then
|
if pointed_thing.type ~= "node" or (not pos) then
|
||||||
@ -58,6 +73,7 @@ minetest.register_tool("testtools:node_setter", {
|
|||||||
S("Place in air: Manually select a node"),
|
S("Place in air: Manually select a node"),
|
||||||
inventory_image = "testtools_node_setter.png",
|
inventory_image = "testtools_node_setter.png",
|
||||||
groups = { testtool = 1, disable_repair = 1 },
|
groups = { testtool = 1, disable_repair = 1 },
|
||||||
|
pointabilities = pointabilities_nodes,
|
||||||
on_use = function(itemstack, user, pointed_thing)
|
on_use = function(itemstack, user, pointed_thing)
|
||||||
local pos = minetest.get_pointed_thing_position(pointed_thing)
|
local pos = minetest.get_pointed_thing_position(pointed_thing)
|
||||||
if pointed_thing.type == "nothing" then
|
if pointed_thing.type == "nothing" then
|
||||||
@ -118,6 +134,10 @@ minetest.register_tool("testtools:remover", {
|
|||||||
S("Punch: Remove pointed node or object"),
|
S("Punch: Remove pointed node or object"),
|
||||||
inventory_image = "testtools_remover.png",
|
inventory_image = "testtools_remover.png",
|
||||||
groups = { testtool = 1, disable_repair = 1 },
|
groups = { testtool = 1, disable_repair = 1 },
|
||||||
|
pointabilities = {
|
||||||
|
nodes = pointabilities_nodes.nodes,
|
||||||
|
objects = pointabilities_objects.objects,
|
||||||
|
},
|
||||||
on_use = function(itemstack, user, pointed_thing)
|
on_use = function(itemstack, user, pointed_thing)
|
||||||
local pos = minetest.get_pointed_thing_position(pointed_thing)
|
local pos = minetest.get_pointed_thing_position(pointed_thing)
|
||||||
if pointed_thing.type == "node" and pos ~= nil then
|
if pointed_thing.type == "node" and pos ~= nil then
|
||||||
@ -139,6 +159,7 @@ minetest.register_tool("testtools:falling_node_tool", {
|
|||||||
S("Place: Move pointed node 2 units upwards, then make it fall"),
|
S("Place: Move pointed node 2 units upwards, then make it fall"),
|
||||||
inventory_image = "testtools_falling_node_tool.png",
|
inventory_image = "testtools_falling_node_tool.png",
|
||||||
groups = { testtool = 1, disable_repair = 1 },
|
groups = { testtool = 1, disable_repair = 1 },
|
||||||
|
pointabilities = pointabilities_nodes,
|
||||||
on_place = function(itemstack, user, pointed_thing)
|
on_place = function(itemstack, user, pointed_thing)
|
||||||
-- Teleport node 1-2 units upwards (if possible) and make it fall
|
-- Teleport node 1-2 units upwards (if possible) and make it fall
|
||||||
local pos = minetest.get_pointed_thing_position(pointed_thing)
|
local pos = minetest.get_pointed_thing_position(pointed_thing)
|
||||||
@ -192,6 +213,7 @@ minetest.register_tool("testtools:rotator", {
|
|||||||
S("Aux1+Punch: Roll"),
|
S("Aux1+Punch: Roll"),
|
||||||
inventory_image = "testtools_entity_rotator.png",
|
inventory_image = "testtools_entity_rotator.png",
|
||||||
groups = { testtool = 1, disable_repair = 1 },
|
groups = { testtool = 1, disable_repair = 1 },
|
||||||
|
pointabilities = pointabilities_objects,
|
||||||
on_use = function(itemstack, user, pointed_thing)
|
on_use = function(itemstack, user, pointed_thing)
|
||||||
if pointed_thing.type ~= "object" then
|
if pointed_thing.type ~= "object" then
|
||||||
return
|
return
|
||||||
@ -250,6 +272,7 @@ minetest.register_tool("testtools:object_mover", {
|
|||||||
S("Sneak+Place: Decrease distance"),
|
S("Sneak+Place: Decrease distance"),
|
||||||
inventory_image = "testtools_object_mover.png",
|
inventory_image = "testtools_object_mover.png",
|
||||||
groups = { testtool = 1, disable_repair = 1 },
|
groups = { testtool = 1, disable_repair = 1 },
|
||||||
|
pointabilities = pointabilities_objects,
|
||||||
on_place = mover_config,
|
on_place = mover_config,
|
||||||
on_secondary_use = mover_config,
|
on_secondary_use = mover_config,
|
||||||
on_use = function(itemstack, user, pointed_thing)
|
on_use = function(itemstack, user, pointed_thing)
|
||||||
@ -296,6 +319,7 @@ minetest.register_tool("testtools:entity_scaler", {
|
|||||||
S("Sneak+Punch: Decrease scale"),
|
S("Sneak+Punch: Decrease scale"),
|
||||||
inventory_image = "testtools_entity_scaler.png",
|
inventory_image = "testtools_entity_scaler.png",
|
||||||
groups = { testtool = 1, disable_repair = 1 },
|
groups = { testtool = 1, disable_repair = 1 },
|
||||||
|
pointabilities = pointabilities_objects,
|
||||||
on_use = function(itemstack, user, pointed_thing)
|
on_use = function(itemstack, user, pointed_thing)
|
||||||
if pointed_thing.type ~= "object" then
|
if pointed_thing.type ~= "object" then
|
||||||
return
|
return
|
||||||
@ -355,6 +379,7 @@ minetest.register_tool("testtools:branding_iron", {
|
|||||||
S("Devices that accept the returned name also accept \"player:<playername>\" for players."),
|
S("Devices that accept the returned name also accept \"player:<playername>\" for players."),
|
||||||
inventory_image = "testtools_branding_iron.png",
|
inventory_image = "testtools_branding_iron.png",
|
||||||
groups = { testtool = 1, disable_repair = 1 },
|
groups = { testtool = 1, disable_repair = 1 },
|
||||||
|
pointabilities = pointabilities_objects,
|
||||||
on_use = function(_itemstack, user, pointed_thing)
|
on_use = function(_itemstack, user, pointed_thing)
|
||||||
local obj
|
local obj
|
||||||
local msg
|
local msg
|
||||||
@ -499,6 +524,7 @@ minetest.register_tool("testtools:object_editor", {
|
|||||||
S("Punch air: Edit yourself"),
|
S("Punch air: Edit yourself"),
|
||||||
inventory_image = "testtools_object_editor.png",
|
inventory_image = "testtools_object_editor.png",
|
||||||
groups = { testtool = 1, disable_repair = 1 },
|
groups = { testtool = 1, disable_repair = 1 },
|
||||||
|
pointabilities = pointabilities_objects,
|
||||||
on_use = function(itemstack, user, pointed_thing)
|
on_use = function(itemstack, user, pointed_thing)
|
||||||
if user and user:is_player() then
|
if user and user:is_player() then
|
||||||
local name = user:get_player_name()
|
local name = user:get_player_name()
|
||||||
@ -586,6 +612,7 @@ minetest.register_tool("testtools:object_attacher", {
|
|||||||
S("Aux1+Sneak+Place: Decrease attachment rotation"),
|
S("Aux1+Sneak+Place: Decrease attachment rotation"),
|
||||||
inventory_image = "testtools_object_attacher.png",
|
inventory_image = "testtools_object_attacher.png",
|
||||||
groups = { testtool = 1, disable_repair = 1 },
|
groups = { testtool = 1, disable_repair = 1 },
|
||||||
|
pointabilities = pointabilities_objects,
|
||||||
on_place = attacher_config,
|
on_place = attacher_config,
|
||||||
on_secondary_use = attacher_config,
|
on_secondary_use = attacher_config,
|
||||||
on_use = function(itemstack, user, pointed_thing)
|
on_use = function(itemstack, user, pointed_thing)
|
||||||
@ -679,6 +706,7 @@ minetest.register_tool("testtools:children_getter", {
|
|||||||
S("Punch air to show your own 'children'"),
|
S("Punch air to show your own 'children'"),
|
||||||
inventory_image = "testtools_children_getter.png",
|
inventory_image = "testtools_children_getter.png",
|
||||||
groups = { testtool = 1, disable_repair = 1 },
|
groups = { testtool = 1, disable_repair = 1 },
|
||||||
|
pointabilities = pointabilities_objects,
|
||||||
on_use = function(itemstack, user, pointed_thing)
|
on_use = function(itemstack, user, pointed_thing)
|
||||||
if user and user:is_player() then
|
if user and user:is_player() then
|
||||||
local name = user:get_player_name()
|
local name = user:get_player_name()
|
||||||
@ -998,3 +1026,41 @@ minetest.register_on_leaveplayer(function(player)
|
|||||||
meta_latest_keylist[name] = nil
|
meta_latest_keylist[name] = nil
|
||||||
node_meta_posses[name] = nil
|
node_meta_posses[name] = nil
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
-- Pointing Staffs
|
||||||
|
|
||||||
|
minetest.register_tool("testtools:blocked_pointing_staff", {
|
||||||
|
description = S("Blocked Pointing Staff").."\n"..
|
||||||
|
S("Can point the Blocking Pointable Node/Object and "..
|
||||||
|
"the Pointable Node/Object is point blocking."),
|
||||||
|
inventory_image = "testtools_blocked_pointing_staff.png",
|
||||||
|
pointabilities = {
|
||||||
|
nodes = {
|
||||||
|
["testnodes:blocking_pointable"] = true,
|
||||||
|
["group:pointable_test"] = "blocking"
|
||||||
|
},
|
||||||
|
objects = {
|
||||||
|
["testentities:blocking_pointable"] = true,
|
||||||
|
["group:pointable_test"] = "blocking"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_tool("testtools:ultimate_pointing_staff", {
|
||||||
|
description = S("Ultimate Pointing Staff").."\n"..
|
||||||
|
S("Can point all pointable test nodes, objects and liquids."),
|
||||||
|
inventory_image = "testtools_ultimate_pointing_staff.png",
|
||||||
|
liquids_pointable = true,
|
||||||
|
pointabilities = {
|
||||||
|
nodes = {
|
||||||
|
["group:blocking_pointable_test"] = true,
|
||||||
|
["group:pointable_test"] = true,
|
||||||
|
["testnodes:not_pointable"] = true
|
||||||
|
},
|
||||||
|
objects = {
|
||||||
|
["group:blocking_pointable_test"] = true,
|
||||||
|
["group:pointable_test"] = true,
|
||||||
|
["testentities:not_pointable"] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 136 B |
Binary file not shown.
After Width: | Height: | Size: 136 B |
@ -489,7 +489,8 @@ ClientEnvEvent ClientEnvironment::getClientEnvEvent()
|
|||||||
|
|
||||||
void ClientEnvironment::getSelectedActiveObjects(
|
void ClientEnvironment::getSelectedActiveObjects(
|
||||||
const core::line3d<f32> &shootline_on_map,
|
const core::line3d<f32> &shootline_on_map,
|
||||||
std::vector<PointedThing> &objects)
|
std::vector<PointedThing> &objects,
|
||||||
|
const std::optional<Pointabilities> &pointabilities)
|
||||||
{
|
{
|
||||||
auto allObjects = m_ao_manager.getActiveSelectableObjects(shootline_on_map);
|
auto allObjects = m_ao_manager.getActiveSelectableObjects(shootline_on_map);
|
||||||
const v3f line_vector = shootline_on_map.getVector();
|
const v3f line_vector = shootline_on_map.getVector();
|
||||||
@ -516,9 +517,23 @@ void ClientEnvironment::getSelectedActiveObjects(
|
|||||||
current_raw_normal = current_normal;
|
current_raw_normal = current_normal;
|
||||||
}
|
}
|
||||||
if (collision) {
|
if (collision) {
|
||||||
|
PointabilityType pointable;
|
||||||
|
if (pointabilities) {
|
||||||
|
if (gcao->isPlayer()) {
|
||||||
|
pointable = pointabilities->matchPlayer(gcao->getGroups()).value_or(
|
||||||
|
gcao->getProperties().pointable);
|
||||||
|
} else {
|
||||||
|
pointable = pointabilities->matchObject(gcao->getName(),
|
||||||
|
gcao->getGroups()).value_or(gcao->getProperties().pointable);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pointable = gcao->getProperties().pointable;
|
||||||
|
}
|
||||||
|
if (pointable != PointabilityType::POINTABLE_NOT) {
|
||||||
current_intersection += obj->getPosition();
|
current_intersection += obj->getPosition();
|
||||||
objects.emplace_back(obj->getId(), current_intersection, current_normal, current_raw_normal,
|
objects.emplace_back(obj->getId(), current_intersection, current_normal, current_raw_normal,
|
||||||
(current_intersection - shootline_on_map.start).getLengthSQ());
|
(current_intersection - shootline_on_map.start).getLengthSQ(), pointable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,8 @@ public:
|
|||||||
|
|
||||||
virtual void getSelectedActiveObjects(
|
virtual void getSelectedActiveObjects(
|
||||||
const core::line3d<f32> &shootline_on_map,
|
const core::line3d<f32> &shootline_on_map,
|
||||||
std::vector<PointedThing> &objects
|
std::vector<PointedThing> &objects,
|
||||||
|
const std::optional<Pointabilities> &pointabilities
|
||||||
);
|
);
|
||||||
|
|
||||||
const std::set<std::string> &getPlayerNames() { return m_player_names; }
|
const std::set<std::string> &getPlayerNames() { return m_player_names; }
|
||||||
|
@ -411,8 +411,7 @@ GenericCAO::~GenericCAO()
|
|||||||
|
|
||||||
bool GenericCAO::getSelectionBox(aabb3f *toset) const
|
bool GenericCAO::getSelectionBox(aabb3f *toset) const
|
||||||
{
|
{
|
||||||
if (!m_prop.is_visible || !m_is_visible || m_is_local_player
|
if (!m_prop.is_visible || !m_is_visible || m_is_local_player) {
|
||||||
|| !m_prop.pointable) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*toset = m_selection_box;
|
*toset = m_selection_box;
|
||||||
|
@ -174,6 +174,8 @@ public:
|
|||||||
|
|
||||||
inline const ObjectProperties &getProperties() const { return m_prop; }
|
inline const ObjectProperties &getProperties() const { return m_prop; }
|
||||||
|
|
||||||
|
inline const std::string &getName() const { return m_name; }
|
||||||
|
|
||||||
scene::ISceneNode *getSceneNode() const override;
|
scene::ISceneNode *getSceneNode() const override;
|
||||||
|
|
||||||
scene::IAnimatedMeshSceneNode *getAnimatedMeshSceneNode() const override;
|
scene::IAnimatedMeshSceneNode *getAnimatedMeshSceneNode() const override;
|
||||||
@ -208,6 +210,11 @@ public:
|
|||||||
return m_is_local_player;
|
return m_is_local_player;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool isPlayer() const
|
||||||
|
{
|
||||||
|
return m_is_player;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool isVisible() const
|
inline bool isVisible() const
|
||||||
{
|
{
|
||||||
return m_is_visible;
|
return m_is_visible;
|
||||||
|
@ -841,6 +841,7 @@ protected:
|
|||||||
* the camera position. This also gives the maximal distance
|
* the camera position. This also gives the maximal distance
|
||||||
* of the search.
|
* of the search.
|
||||||
* @param[in] liquids_pointable if false, liquids are ignored
|
* @param[in] liquids_pointable if false, liquids are ignored
|
||||||
|
* @param[in] pointabilities item specific pointable overriding
|
||||||
* @param[in] look_for_object if false, objects are ignored
|
* @param[in] look_for_object if false, objects are ignored
|
||||||
* @param[in] camera_offset offset of the camera
|
* @param[in] camera_offset offset of the camera
|
||||||
* @param[out] selected_object the selected object or
|
* @param[out] selected_object the selected object or
|
||||||
@ -848,6 +849,7 @@ protected:
|
|||||||
*/
|
*/
|
||||||
PointedThing updatePointedThing(
|
PointedThing updatePointedThing(
|
||||||
const core::line3d<f32> &shootline, bool liquids_pointable,
|
const core::line3d<f32> &shootline, bool liquids_pointable,
|
||||||
|
const std::optional<Pointabilities> &pointabilities,
|
||||||
bool look_for_object, const v3s16 &camera_offset);
|
bool look_for_object, const v3s16 &camera_offset);
|
||||||
void handlePointingAtNothing(const ItemStack &playerItem);
|
void handlePointingAtNothing(const ItemStack &playerItem);
|
||||||
void handlePointingAtNode(const PointedThing &pointed,
|
void handlePointingAtNode(const PointedThing &pointed,
|
||||||
@ -3343,6 +3345,7 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud)
|
|||||||
|
|
||||||
PointedThing pointed = updatePointedThing(shootline,
|
PointedThing pointed = updatePointedThing(shootline,
|
||||||
selected_def.liquids_pointable,
|
selected_def.liquids_pointable,
|
||||||
|
selected_def.pointabilities,
|
||||||
!runData.btn_down_for_dig,
|
!runData.btn_down_for_dig,
|
||||||
camera_offset);
|
camera_offset);
|
||||||
|
|
||||||
@ -3454,6 +3457,7 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud)
|
|||||||
PointedThing Game::updatePointedThing(
|
PointedThing Game::updatePointedThing(
|
||||||
const core::line3d<f32> &shootline,
|
const core::line3d<f32> &shootline,
|
||||||
bool liquids_pointable,
|
bool liquids_pointable,
|
||||||
|
const std::optional<Pointabilities> &pointabilities,
|
||||||
bool look_for_object,
|
bool look_for_object,
|
||||||
const v3s16 &camera_offset)
|
const v3s16 &camera_offset)
|
||||||
{
|
{
|
||||||
@ -3470,7 +3474,7 @@ PointedThing Game::updatePointedThing(
|
|||||||
runData.selected_object = NULL;
|
runData.selected_object = NULL;
|
||||||
hud->pointing_at_object = false;
|
hud->pointing_at_object = false;
|
||||||
|
|
||||||
RaycastState s(shootline, look_for_object, liquids_pointable);
|
RaycastState s(shootline, look_for_object, liquids_pointable, pointabilities);
|
||||||
PointedThing result;
|
PointedThing result;
|
||||||
env.continueRaycast(&s, &result);
|
env.continueRaycast(&s, &result);
|
||||||
if (result.type == POINTEDTHING_OBJECT) {
|
if (result.type == POINTEDTHING_OBJECT) {
|
||||||
|
@ -102,24 +102,33 @@ bool Environment::line_of_sight(v3f pos1, v3f pos2, v3s16 *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check if a node is pointable
|
Check how a node can be pointed at
|
||||||
*/
|
*/
|
||||||
inline static bool isPointableNode(const MapNode &n,
|
inline static PointabilityType isPointableNode(const MapNode &n,
|
||||||
const NodeDefManager *nodedef , bool liquids_pointable)
|
const NodeDefManager *nodedef, bool liquids_pointable,
|
||||||
|
const std::optional<Pointabilities> &pointabilities)
|
||||||
{
|
{
|
||||||
const ContentFeatures &features = nodedef->get(n);
|
const ContentFeatures &features = nodedef->get(n);
|
||||||
return features.pointable ||
|
if (pointabilities) {
|
||||||
(liquids_pointable && features.isLiquid());
|
std::optional<PointabilityType> match =
|
||||||
|
pointabilities->matchNode(features.name, features.groups);
|
||||||
|
if (match)
|
||||||
|
return match.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (features.isLiquid() && liquids_pointable)
|
||||||
|
return PointabilityType::POINTABLE;
|
||||||
|
return features.pointable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Environment::continueRaycast(RaycastState *state, PointedThing *result)
|
void Environment::continueRaycast(RaycastState *state, PointedThing *result_p)
|
||||||
{
|
{
|
||||||
const NodeDefManager *nodedef = getMap().getNodeDefManager();
|
const NodeDefManager *nodedef = getMap().getNodeDefManager();
|
||||||
if (state->m_initialization_needed) {
|
if (state->m_initialization_needed) {
|
||||||
// Add objects
|
// Add objects
|
||||||
if (state->m_objects_pointable) {
|
if (state->m_objects_pointable) {
|
||||||
std::vector<PointedThing> found;
|
std::vector<PointedThing> found;
|
||||||
getSelectedActiveObjects(state->m_shootline, found);
|
getSelectedActiveObjects(state->m_shootline, found, state->m_pointabilities);
|
||||||
for (const PointedThing &pointed : found) {
|
for (const PointedThing &pointed : found) {
|
||||||
state->m_found.push(pointed);
|
state->m_found.push(pointed);
|
||||||
}
|
}
|
||||||
@ -184,10 +193,15 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result)
|
|||||||
bool is_valid_position;
|
bool is_valid_position;
|
||||||
|
|
||||||
n = map.getNode(np, &is_valid_position);
|
n = map.getNode(np, &is_valid_position);
|
||||||
if (!(is_valid_position && isPointableNode(n, nodedef,
|
if (!is_valid_position)
|
||||||
state->m_liquids_pointable))) {
|
continue;
|
||||||
|
|
||||||
|
PointabilityType pointable = isPointableNode(n, nodedef,
|
||||||
|
state->m_liquids_pointable,
|
||||||
|
state->m_pointabilities);
|
||||||
|
// If it can be pointed through skip
|
||||||
|
if (pointable == PointabilityType::POINTABLE_NOT)
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
PointedThing result;
|
PointedThing result;
|
||||||
|
|
||||||
@ -234,6 +248,7 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result)
|
|||||||
if (!is_colliding) {
|
if (!is_colliding) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
result.pointability = pointable;
|
||||||
result.type = POINTEDTHING_NODE;
|
result.type = POINTEDTHING_NODE;
|
||||||
result.node_undersurface = np;
|
result.node_undersurface = np;
|
||||||
result.distanceSq = min_distance_sq;
|
result.distanceSq = min_distance_sq;
|
||||||
@ -275,12 +290,16 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result)
|
|||||||
state->m_previous_node = state->m_iterator.m_current_node_pos;
|
state->m_previous_node = state->m_iterator.m_current_node_pos;
|
||||||
state->m_iterator.next();
|
state->m_iterator.next();
|
||||||
}
|
}
|
||||||
// Return empty PointedThing if nothing left on the ray
|
|
||||||
|
// Return empty PointedThing if nothing left on the ray or it is blocking pointable
|
||||||
if (state->m_found.empty()) {
|
if (state->m_found.empty()) {
|
||||||
result->type = POINTEDTHING_NOTHING;
|
result_p->type = POINTEDTHING_NOTHING;
|
||||||
} else {
|
} else {
|
||||||
*result = state->m_found.top();
|
*result_p = state->m_found.top();
|
||||||
state->m_found.pop();
|
state->m_found.pop();
|
||||||
|
if (result_p->pointability == PointabilityType::POINTABLE_BLOCKING) {
|
||||||
|
result_p->type = POINTEDTHING_NOTHING;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <optional>
|
||||||
#include "irr_v3d.h"
|
#include "irr_v3d.h"
|
||||||
#include "util/basic_macros.h"
|
#include "util/basic_macros.h"
|
||||||
#include "line3d.h"
|
#include "line3d.h"
|
||||||
@ -42,6 +43,7 @@ class IGameDef;
|
|||||||
class Map;
|
class Map;
|
||||||
struct PointedThing;
|
struct PointedThing;
|
||||||
class RaycastState;
|
class RaycastState;
|
||||||
|
struct Pointabilities;
|
||||||
|
|
||||||
class Environment
|
class Environment
|
||||||
{
|
{
|
||||||
@ -97,7 +99,8 @@ public:
|
|||||||
* @param[out] objects found objects
|
* @param[out] objects found objects
|
||||||
*/
|
*/
|
||||||
virtual void getSelectedActiveObjects(const core::line3d<f32> &shootline_on_map,
|
virtual void getSelectedActiveObjects(const core::line3d<f32> &shootline_on_map,
|
||||||
std::vector<PointedThing> &objects) = 0;
|
std::vector<PointedThing> &objects,
|
||||||
|
const std::optional<Pointabilities> &pointabilities) = 0;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the next node or object the shootline meets.
|
* Returns the next node or object the shootline meets.
|
||||||
|
@ -122,6 +122,7 @@ ItemDefinition& ItemDefinition::operator=(const ItemDefinition &def)
|
|||||||
stack_max = def.stack_max;
|
stack_max = def.stack_max;
|
||||||
usable = def.usable;
|
usable = def.usable;
|
||||||
liquids_pointable = def.liquids_pointable;
|
liquids_pointable = def.liquids_pointable;
|
||||||
|
pointabilities = def.pointabilities;
|
||||||
if (def.tool_capabilities)
|
if (def.tool_capabilities)
|
||||||
tool_capabilities = new ToolCapabilities(*def.tool_capabilities);
|
tool_capabilities = new ToolCapabilities(*def.tool_capabilities);
|
||||||
groups = def.groups;
|
groups = def.groups;
|
||||||
@ -167,6 +168,7 @@ void ItemDefinition::reset()
|
|||||||
stack_max = 99;
|
stack_max = 99;
|
||||||
usable = false;
|
usable = false;
|
||||||
liquids_pointable = false;
|
liquids_pointable = false;
|
||||||
|
pointabilities = std::nullopt;
|
||||||
delete tool_capabilities;
|
delete tool_capabilities;
|
||||||
tool_capabilities = NULL;
|
tool_capabilities = NULL;
|
||||||
groups.clear();
|
groups.clear();
|
||||||
@ -241,6 +243,14 @@ void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const
|
|||||||
|
|
||||||
writeU8(os, wallmounted_rotate_vertical);
|
writeU8(os, wallmounted_rotate_vertical);
|
||||||
touch_interaction.serialize(os);
|
touch_interaction.serialize(os);
|
||||||
|
|
||||||
|
std::string pointabilities_s;
|
||||||
|
if (pointabilities) {
|
||||||
|
std::ostringstream tmp_os(std::ios::binary);
|
||||||
|
pointabilities->serialize(tmp_os);
|
||||||
|
pointabilities_s = tmp_os.str();
|
||||||
|
}
|
||||||
|
os << serializeString16(pointabilities_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemDefinition::deSerialize(std::istream &is, u16 protocol_version)
|
void ItemDefinition::deSerialize(std::istream &is, u16 protocol_version)
|
||||||
@ -316,6 +326,13 @@ void ItemDefinition::deSerialize(std::istream &is, u16 protocol_version)
|
|||||||
|
|
||||||
wallmounted_rotate_vertical = readU8(is); // 0 if missing
|
wallmounted_rotate_vertical = readU8(is); // 0 if missing
|
||||||
touch_interaction.deSerialize(is);
|
touch_interaction.deSerialize(is);
|
||||||
|
|
||||||
|
std::string pointabilities_s = deSerializeString16(is);
|
||||||
|
if (!pointabilities_s.empty()) {
|
||||||
|
std::istringstream tmp_is(pointabilities_s, std::ios::binary);
|
||||||
|
pointabilities = std::make_optional<Pointabilities>();
|
||||||
|
pointabilities->deSerialize(tmp_is);
|
||||||
|
}
|
||||||
} catch(SerializationError &e) {};
|
} catch(SerializationError &e) {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "itemgroup.h"
|
#include "itemgroup.h"
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
#include "texture_override.h" // TextureOverride
|
#include "texture_override.h" // TextureOverride
|
||||||
|
#include "util/pointabilities.h"
|
||||||
class IGameDef;
|
class IGameDef;
|
||||||
class Client;
|
class Client;
|
||||||
struct ToolCapabilities;
|
struct ToolCapabilities;
|
||||||
@ -97,8 +98,11 @@ struct ItemDefinition
|
|||||||
u16 stack_max;
|
u16 stack_max;
|
||||||
bool usable;
|
bool usable;
|
||||||
bool liquids_pointable;
|
bool liquids_pointable;
|
||||||
// May be NULL. If non-NULL, deleted by destructor
|
std::optional<Pointabilities> pointabilities;
|
||||||
|
|
||||||
|
// They may be NULL. If non-NULL, deleted by destructor
|
||||||
ToolCapabilities *tool_capabilities;
|
ToolCapabilities *tool_capabilities;
|
||||||
|
|
||||||
ItemGroupList groups;
|
ItemGroupList groups;
|
||||||
SoundSpec sound_place;
|
SoundSpec sound_place;
|
||||||
SoundSpec sound_place_failed;
|
SoundSpec sound_place_failed;
|
||||||
|
@ -386,7 +386,7 @@ void ContentFeatures::reset()
|
|||||||
light_propagates = false;
|
light_propagates = false;
|
||||||
sunlight_propagates = false;
|
sunlight_propagates = false;
|
||||||
walkable = true;
|
walkable = true;
|
||||||
pointable = true;
|
pointable = PointabilityType::POINTABLE;
|
||||||
diggable = true;
|
diggable = true;
|
||||||
climbable = false;
|
climbable = false;
|
||||||
buildable_to = false;
|
buildable_to = false;
|
||||||
@ -504,7 +504,7 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
|
|||||||
|
|
||||||
// interaction
|
// interaction
|
||||||
writeU8(os, walkable);
|
writeU8(os, walkable);
|
||||||
writeU8(os, pointable);
|
Pointabilities::serializePointabilityType(os, pointable);
|
||||||
writeU8(os, diggable);
|
writeU8(os, diggable);
|
||||||
writeU8(os, climbable);
|
writeU8(os, climbable);
|
||||||
writeU8(os, buildable_to);
|
writeU8(os, buildable_to);
|
||||||
@ -617,7 +617,7 @@ void ContentFeatures::deSerialize(std::istream &is, u16 protocol_version)
|
|||||||
|
|
||||||
// interaction
|
// interaction
|
||||||
walkable = readU8(is);
|
walkable = readU8(is);
|
||||||
pointable = readU8(is);
|
pointable = Pointabilities::deSerializePointabilityType(is);
|
||||||
diggable = readU8(is);
|
diggable = readU8(is);
|
||||||
climbable = readU8(is);
|
climbable = readU8(is);
|
||||||
buildable_to = readU8(is);
|
buildable_to = readU8(is);
|
||||||
@ -1083,7 +1083,7 @@ void NodeDefManager::clear()
|
|||||||
f.light_propagates = true;
|
f.light_propagates = true;
|
||||||
f.sunlight_propagates = true;
|
f.sunlight_propagates = true;
|
||||||
f.walkable = false;
|
f.walkable = false;
|
||||||
f.pointable = false;
|
f.pointable = PointabilityType::POINTABLE_NOT;
|
||||||
f.diggable = false;
|
f.diggable = false;
|
||||||
f.buildable_to = true;
|
f.buildable_to = true;
|
||||||
f.floodable = true;
|
f.floodable = true;
|
||||||
@ -1104,7 +1104,7 @@ void NodeDefManager::clear()
|
|||||||
f.light_propagates = false;
|
f.light_propagates = false;
|
||||||
f.sunlight_propagates = false;
|
f.sunlight_propagates = false;
|
||||||
f.walkable = false;
|
f.walkable = false;
|
||||||
f.pointable = false;
|
f.pointable = PointabilityType::POINTABLE_NOT;
|
||||||
f.diggable = false;
|
f.diggable = false;
|
||||||
f.buildable_to = true; // A way to remove accidental CONTENT_IGNOREs
|
f.buildable_to = true; // A way to remove accidental CONTENT_IGNOREs
|
||||||
f.is_ground_content = true;
|
f.is_ground_content = true;
|
||||||
|
@ -35,6 +35,7 @@ class Client;
|
|||||||
#include "constants.h" // BS
|
#include "constants.h" // BS
|
||||||
#include "texture_override.h" // TextureOverride
|
#include "texture_override.h" // TextureOverride
|
||||||
#include "tileanimation.h"
|
#include "tileanimation.h"
|
||||||
|
#include "util/pointabilities.h"
|
||||||
|
|
||||||
class IItemDefManager;
|
class IItemDefManager;
|
||||||
class ITextureSource;
|
class ITextureSource;
|
||||||
@ -395,8 +396,8 @@ struct ContentFeatures
|
|||||||
// This is used for collision detection.
|
// This is used for collision detection.
|
||||||
// Also for general solidness queries.
|
// Also for general solidness queries.
|
||||||
bool walkable;
|
bool walkable;
|
||||||
// Player can point to these
|
// Player can point to these, point through or it is blocking
|
||||||
bool pointable;
|
PointabilityType pointable;
|
||||||
// Player can dig these
|
// Player can dig these
|
||||||
bool diggable;
|
bool diggable;
|
||||||
// Player can climb these
|
// Player can climb these
|
||||||
|
@ -73,7 +73,7 @@ std::string ObjectProperties::dump()
|
|||||||
|
|
||||||
os << ", selectionbox=" << selectionbox.MinEdge << "," << selectionbox.MaxEdge;
|
os << ", selectionbox=" << selectionbox.MinEdge << "," << selectionbox.MaxEdge;
|
||||||
os << ", rotate_selectionbox=" << rotate_selectionbox;
|
os << ", rotate_selectionbox=" << rotate_selectionbox;
|
||||||
os << ", pointable=" << pointable;
|
os << ", pointable=" << Pointabilities::toStringPointabilityType(pointable);
|
||||||
os << ", static_save=" << static_save;
|
os << ", static_save=" << static_save;
|
||||||
os << ", eye_height=" << eye_height;
|
os << ", eye_height=" << eye_height;
|
||||||
os << ", zoom_fov=" << zoom_fov;
|
os << ", zoom_fov=" << zoom_fov;
|
||||||
@ -127,7 +127,7 @@ void ObjectProperties::serialize(std::ostream &os) const
|
|||||||
writeV3F32(os, collisionbox.MaxEdge);
|
writeV3F32(os, collisionbox.MaxEdge);
|
||||||
writeV3F32(os, selectionbox.MinEdge);
|
writeV3F32(os, selectionbox.MinEdge);
|
||||||
writeV3F32(os, selectionbox.MaxEdge);
|
writeV3F32(os, selectionbox.MaxEdge);
|
||||||
writeU8(os, pointable);
|
Pointabilities::serializePointabilityType(os, pointable);
|
||||||
os << serializeString16(visual);
|
os << serializeString16(visual);
|
||||||
writeV3F32(os, visual_size);
|
writeV3F32(os, visual_size);
|
||||||
writeU16(os, textures.size());
|
writeU16(os, textures.size());
|
||||||
@ -188,7 +188,7 @@ void ObjectProperties::deSerialize(std::istream &is)
|
|||||||
collisionbox.MaxEdge = readV3F32(is);
|
collisionbox.MaxEdge = readV3F32(is);
|
||||||
selectionbox.MinEdge = readV3F32(is);
|
selectionbox.MinEdge = readV3F32(is);
|
||||||
selectionbox.MaxEdge = readV3F32(is);
|
selectionbox.MaxEdge = readV3F32(is);
|
||||||
pointable = readU8(is);
|
pointable = Pointabilities::deSerializePointabilityType(is);
|
||||||
visual = deSerializeString16(is);
|
visual = deSerializeString16(is);
|
||||||
visual_size = readV3F32(is);
|
visual_size = readV3F32(is);
|
||||||
textures.clear();
|
textures.clear();
|
||||||
|
@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "util/pointabilities.h"
|
||||||
|
|
||||||
struct ObjectProperties
|
struct ObjectProperties
|
||||||
{
|
{
|
||||||
@ -36,7 +37,7 @@ struct ObjectProperties
|
|||||||
aabb3f collisionbox = aabb3f(-0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f);
|
aabb3f collisionbox = aabb3f(-0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f);
|
||||||
aabb3f selectionbox = aabb3f(-0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f);
|
aabb3f selectionbox = aabb3f(-0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f);
|
||||||
bool rotate_selectionbox = false;
|
bool rotate_selectionbox = false;
|
||||||
bool pointable = true;
|
PointabilityType pointable = PointabilityType::POINTABLE;
|
||||||
std::string visual = "sprite";
|
std::string visual = "sprite";
|
||||||
std::string mesh = "";
|
std::string mesh = "";
|
||||||
v3f visual_size = v3f(1, 1, 1);
|
v3f visual_size = v3f(1, 1, 1);
|
||||||
|
@ -58,12 +58,14 @@ bool RaycastSort::operator() (const PointedThing &pt1,
|
|||||||
|
|
||||||
|
|
||||||
RaycastState::RaycastState(const core::line3d<f32> &shootline,
|
RaycastState::RaycastState(const core::line3d<f32> &shootline,
|
||||||
bool objects_pointable, bool liquids_pointable) :
|
bool objects_pointable, bool liquids_pointable,
|
||||||
|
const std::optional<Pointabilities> &pointabilities) :
|
||||||
m_shootline(shootline),
|
m_shootline(shootline),
|
||||||
m_iterator(shootline.start / BS, shootline.getVector() / BS),
|
m_iterator(shootline.start / BS, shootline.getVector() / BS),
|
||||||
m_previous_node(m_iterator.m_current_node_pos),
|
m_previous_node(m_iterator.m_current_node_pos),
|
||||||
m_objects_pointable(objects_pointable),
|
m_objects_pointable(objects_pointable),
|
||||||
m_liquids_pointable(liquids_pointable)
|
m_liquids_pointable(liquids_pointable),
|
||||||
|
m_pointabilities(pointabilities)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ public:
|
|||||||
* @param liquids pointable if false, liquid nodes won't be found
|
* @param liquids pointable if false, liquid nodes won't be found
|
||||||
*/
|
*/
|
||||||
RaycastState(const core::line3d<f32> &shootline, bool objects_pointable,
|
RaycastState(const core::line3d<f32> &shootline, bool objects_pointable,
|
||||||
bool liquids_pointable);
|
bool liquids_pointable, const std::optional<Pointabilities> &pointabilities);
|
||||||
|
|
||||||
//! Shootline of the raycast.
|
//! Shootline of the raycast.
|
||||||
core::line3d<f32> m_shootline;
|
core::line3d<f32> m_shootline;
|
||||||
@ -55,6 +55,7 @@ public:
|
|||||||
|
|
||||||
bool m_objects_pointable;
|
bool m_objects_pointable;
|
||||||
bool m_liquids_pointable;
|
bool m_liquids_pointable;
|
||||||
|
const std::optional<Pointabilities> &m_pointabilities;
|
||||||
|
|
||||||
//! The code needs to search these nodes around the center node.
|
//! The code needs to search these nodes around the center node.
|
||||||
core::aabbox3d<s16> m_search_range { 0, 0, 0, 0, 0, 0 };
|
core::aabbox3d<s16> m_search_range { 0, 0, 0, 0, 0, 0 };
|
||||||
|
@ -83,6 +83,12 @@ void read_item_definition(lua_State* L, int index,
|
|||||||
|
|
||||||
getboolfield(L, index, "liquids_pointable", def.liquids_pointable);
|
getboolfield(L, index, "liquids_pointable", def.liquids_pointable);
|
||||||
|
|
||||||
|
lua_getfield(L, index, "pointabilities");
|
||||||
|
if(lua_istable(L, -1)){
|
||||||
|
def.pointabilities = std::make_optional<Pointabilities>(
|
||||||
|
read_pointabilities(L, -1));
|
||||||
|
}
|
||||||
|
|
||||||
lua_getfield(L, index, "tool_capabilities");
|
lua_getfield(L, index, "tool_capabilities");
|
||||||
if(lua_istable(L, -1)){
|
if(lua_istable(L, -1)){
|
||||||
def.tool_capabilities = new ToolCapabilities(
|
def.tool_capabilities = new ToolCapabilities(
|
||||||
@ -199,6 +205,10 @@ void push_item_definition_full(lua_State *L, const ItemDefinition &i)
|
|||||||
lua_setfield(L, -2, "usable");
|
lua_setfield(L, -2, "usable");
|
||||||
lua_pushboolean(L, i.liquids_pointable);
|
lua_pushboolean(L, i.liquids_pointable);
|
||||||
lua_setfield(L, -2, "liquids_pointable");
|
lua_setfield(L, -2, "liquids_pointable");
|
||||||
|
if (i.pointabilities) {
|
||||||
|
push_pointabilities(L, *i.pointabilities);
|
||||||
|
lua_setfield(L, -2, "pointabilities");
|
||||||
|
}
|
||||||
if (i.tool_capabilities) {
|
if (i.tool_capabilities) {
|
||||||
push_tool_capabilities(L, *i.tool_capabilities);
|
push_tool_capabilities(L, *i.tool_capabilities);
|
||||||
lua_setfield(L, -2, "tool_capabilities");
|
lua_setfield(L, -2, "tool_capabilities");
|
||||||
@ -311,7 +321,12 @@ void read_object_properties(lua_State *L, int index,
|
|||||||
}
|
}
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
getboolfield(L, -1, "pointable", prop->pointable);
|
lua_getfield(L, -1, "pointable");
|
||||||
|
if(!lua_isnil(L, -1)){
|
||||||
|
prop->pointable = read_pointability_type(L, -1);
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
getstringfield(L, -1, "visual", prop->visual);
|
getstringfield(L, -1, "visual", prop->visual);
|
||||||
|
|
||||||
getstringfield(L, -1, "mesh", prop->mesh);
|
getstringfield(L, -1, "mesh", prop->mesh);
|
||||||
@ -452,7 +467,7 @@ void push_object_properties(lua_State *L, ObjectProperties *prop)
|
|||||||
lua_pushboolean(L, prop->rotate_selectionbox);
|
lua_pushboolean(L, prop->rotate_selectionbox);
|
||||||
lua_setfield(L, -2, "rotate");
|
lua_setfield(L, -2, "rotate");
|
||||||
lua_setfield(L, -2, "selectionbox");
|
lua_setfield(L, -2, "selectionbox");
|
||||||
lua_pushboolean(L, prop->pointable);
|
push_pointability_type(L, prop->pointable);
|
||||||
lua_setfield(L, -2, "pointable");
|
lua_setfield(L, -2, "pointable");
|
||||||
lua_pushlstring(L, prop->visual.c_str(), prop->visual.size());
|
lua_pushlstring(L, prop->visual.c_str(), prop->visual.size());
|
||||||
lua_setfield(L, -2, "visual");
|
lua_setfield(L, -2, "visual");
|
||||||
@ -781,8 +796,14 @@ void read_content_features(lua_State *L, ContentFeatures &f, int index)
|
|||||||
// This is used for collision detection.
|
// This is used for collision detection.
|
||||||
// Also for general solidness queries.
|
// Also for general solidness queries.
|
||||||
getboolfield(L, index, "walkable", f.walkable);
|
getboolfield(L, index, "walkable", f.walkable);
|
||||||
// Player can point to these
|
|
||||||
getboolfield(L, index, "pointable", f.pointable);
|
// Player can point to these, point through or it is blocking
|
||||||
|
lua_getfield(L, index, "pointable");
|
||||||
|
if(!lua_isnil(L, -1)){
|
||||||
|
f.pointable = read_pointability_type(L, -1);
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
// Player can dig these
|
// Player can dig these
|
||||||
getboolfield(L, index, "diggable", f.diggable);
|
getboolfield(L, index, "diggable", f.diggable);
|
||||||
// Player can climb these
|
// Player can climb these
|
||||||
@ -1005,7 +1026,7 @@ void push_content_features(lua_State *L, const ContentFeatures &c)
|
|||||||
lua_setfield(L, -2, "is_ground_content");
|
lua_setfield(L, -2, "is_ground_content");
|
||||||
lua_pushboolean(L, c.walkable);
|
lua_pushboolean(L, c.walkable);
|
||||||
lua_setfield(L, -2, "walkable");
|
lua_setfield(L, -2, "walkable");
|
||||||
lua_pushboolean(L, c.pointable);
|
push_pointability_type(L, c.pointable);
|
||||||
lua_setfield(L, -2, "pointable");
|
lua_setfield(L, -2, "pointable");
|
||||||
lua_pushboolean(L, c.diggable);
|
lua_pushboolean(L, c.diggable);
|
||||||
lua_setfield(L, -2, "diggable");
|
lua_setfield(L, -2, "diggable");
|
||||||
@ -1592,6 +1613,125 @@ ToolCapabilities read_tool_capabilities(
|
|||||||
return toolcap;
|
return toolcap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
PointabilityType read_pointability_type(lua_State *L, int index)
|
||||||
|
{
|
||||||
|
if (lua_isboolean(L, index)) {
|
||||||
|
if (lua_toboolean(L, index))
|
||||||
|
return PointabilityType::POINTABLE;
|
||||||
|
else
|
||||||
|
return PointabilityType::POINTABLE_NOT;
|
||||||
|
} else {
|
||||||
|
const char* s = luaL_checkstring(L, index);
|
||||||
|
if (s && !strcmp(s, "blocking")) {
|
||||||
|
return PointabilityType::POINTABLE_BLOCKING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw LuaError("Invalid pointable type.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
Pointabilities read_pointabilities(lua_State *L, int index)
|
||||||
|
{
|
||||||
|
Pointabilities pointabilities;
|
||||||
|
|
||||||
|
lua_getfield(L, index, "nodes");
|
||||||
|
if(lua_istable(L, -1)){
|
||||||
|
int ti = lua_gettop(L);
|
||||||
|
lua_pushnil(L);
|
||||||
|
while(lua_next(L, ti) != 0) {
|
||||||
|
// key at index -2 and value at index -1
|
||||||
|
std::string name = luaL_checkstring(L, -2);
|
||||||
|
|
||||||
|
// handle groups
|
||||||
|
if(std::string_view(name).substr(0,6)=="group:") {
|
||||||
|
pointabilities.node_groups[name.substr(6)] = read_pointability_type(L, -1);
|
||||||
|
} else {
|
||||||
|
pointabilities.nodes[name] = read_pointability_type(L, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// removes value, keeps key for next iteration
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
lua_getfield(L, index, "objects");
|
||||||
|
if(lua_istable(L, -1)){
|
||||||
|
int ti = lua_gettop(L);
|
||||||
|
lua_pushnil(L);
|
||||||
|
while(lua_next(L, ti) != 0) {
|
||||||
|
// key at index -2 and value at index -1
|
||||||
|
std::string name = luaL_checkstring(L, -2);
|
||||||
|
|
||||||
|
// handle groups
|
||||||
|
if(std::string_view(name).substr(0,6)=="group:") {
|
||||||
|
pointabilities.object_groups[name.substr(6)] = read_pointability_type(L, -1);
|
||||||
|
} else {
|
||||||
|
pointabilities.objects[name] = read_pointability_type(L, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// removes value, keeps key for next iteration
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
return pointabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
void push_pointability_type(lua_State *L, PointabilityType pointable)
|
||||||
|
{
|
||||||
|
switch(pointable)
|
||||||
|
{
|
||||||
|
case PointabilityType::POINTABLE:
|
||||||
|
lua_pushboolean(L, true);
|
||||||
|
break;
|
||||||
|
case PointabilityType::POINTABLE_NOT:
|
||||||
|
lua_pushboolean(L, false);
|
||||||
|
break;
|
||||||
|
case PointabilityType::POINTABLE_BLOCKING:
|
||||||
|
lua_pushliteral(L, "blocking");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
void push_pointabilities(lua_State *L, const Pointabilities &pointabilities)
|
||||||
|
{
|
||||||
|
// pointabilities table
|
||||||
|
lua_newtable(L);
|
||||||
|
|
||||||
|
if (!pointabilities.nodes.empty() || !pointabilities.node_groups.empty()) {
|
||||||
|
// Create and fill table
|
||||||
|
lua_newtable(L);
|
||||||
|
for (const auto &entry : pointabilities.nodes) {
|
||||||
|
push_pointability_type(L, entry.second);
|
||||||
|
lua_setfield(L, -2, entry.first.c_str());
|
||||||
|
}
|
||||||
|
for (const auto &entry : pointabilities.node_groups) {
|
||||||
|
push_pointability_type(L, entry.second);
|
||||||
|
lua_setfield(L, -2, ("group:" + entry.first).c_str());
|
||||||
|
}
|
||||||
|
lua_setfield(L, -2, "nodes");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pointabilities.objects.empty() || !pointabilities.object_groups.empty()) {
|
||||||
|
// Create and fill table
|
||||||
|
lua_newtable(L);
|
||||||
|
for (const auto &entry : pointabilities.objects) {
|
||||||
|
push_pointability_type(L, entry.second);
|
||||||
|
lua_setfield(L, -2, entry.first.c_str());
|
||||||
|
}
|
||||||
|
for (const auto &entry : pointabilities.object_groups) {
|
||||||
|
push_pointability_type(L, entry.second);
|
||||||
|
lua_setfield(L, -2, ("group:" + entry.first).c_str());
|
||||||
|
}
|
||||||
|
lua_setfield(L, -2, "objects");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
void push_dig_params(lua_State *L,const DigParams ¶ms)
|
void push_dig_params(lua_State *L,const DigParams ¶ms)
|
||||||
{
|
{
|
||||||
|
@ -39,6 +39,7 @@ extern "C" {
|
|||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
#include "itemgroup.h"
|
#include "itemgroup.h"
|
||||||
#include "itemdef.h"
|
#include "itemdef.h"
|
||||||
|
#include "util/pointabilities.h"
|
||||||
#include "c_types.h"
|
#include "c_types.h"
|
||||||
// We do an explicit path include because by default c_content.h include src/client/hud.h
|
// We do an explicit path include because by default c_content.h include src/client/hud.h
|
||||||
// prior to the src/hud.h, which is not good on server only build
|
// prior to the src/hud.h, which is not good on server only build
|
||||||
@ -107,6 +108,11 @@ ItemStack read_item (lua_State *L, int index, IItemDefM
|
|||||||
|
|
||||||
struct TileAnimationParams read_animation_definition(lua_State *L, int index);
|
struct TileAnimationParams read_animation_definition(lua_State *L, int index);
|
||||||
|
|
||||||
|
PointabilityType read_pointability_type (lua_State *L, int index);
|
||||||
|
Pointabilities read_pointabilities (lua_State *L, int index);
|
||||||
|
void push_pointability_type (lua_State *L, PointabilityType pointable);
|
||||||
|
void push_pointabilities (lua_State *L, const Pointabilities &pointabilities);
|
||||||
|
|
||||||
ToolCapabilities read_tool_capabilities (lua_State *L, int table);
|
ToolCapabilities read_tool_capabilities (lua_State *L, int table);
|
||||||
void push_tool_capabilities (lua_State *L,
|
void push_tool_capabilities (lua_State *L,
|
||||||
const ToolCapabilities &prop);
|
const ToolCapabilities &prop);
|
||||||
|
@ -188,7 +188,7 @@ int LuaRaycast::create_object(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
LuaRaycast *o = new LuaRaycast(core::line3d<f32>(pos1, pos2),
|
LuaRaycast *o = new LuaRaycast(core::line3d<f32>(pos1, pos2),
|
||||||
objects, liquids);
|
objects, liquids, std::nullopt);
|
||||||
|
|
||||||
*(void **) (lua_newuserdata(L, sizeof(void *))) = o;
|
*(void **) (lua_newuserdata(L, sizeof(void *))) = o;
|
||||||
luaL_getmetatable(L, className);
|
luaL_getmetatable(L, className);
|
||||||
|
@ -336,8 +336,9 @@ public:
|
|||||||
LuaRaycast(
|
LuaRaycast(
|
||||||
const core::line3d<f32> &shootline,
|
const core::line3d<f32> &shootline,
|
||||||
bool objects_pointable,
|
bool objects_pointable,
|
||||||
bool liquids_pointable) :
|
bool liquids_pointable,
|
||||||
state(shootline, objects_pointable, liquids_pointable)
|
const std::optional<Pointabilities> &pointabilities) :
|
||||||
|
state(shootline, objects_pointable, liquids_pointable, pointabilities)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
//! Creates a LuaRaycast and leaves it on top of the stack.
|
//! Creates a LuaRaycast and leaves it on top of the stack.
|
||||||
|
@ -245,7 +245,7 @@ std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version)
|
|||||||
|
|
||||||
// PROTOCOL_VERSION >= 37
|
// PROTOCOL_VERSION >= 37
|
||||||
writeU8(os, 1); // version
|
writeU8(os, 1); // version
|
||||||
os << serializeString16(""); // name
|
os << serializeString16(m_init_name); // name
|
||||||
writeU8(os, 0); // is_player
|
writeU8(os, 0); // is_player
|
||||||
writeU16(os, getId()); //id
|
writeU16(os, getId()); //id
|
||||||
writeV3F32(os, m_base_position);
|
writeV3F32(os, m_base_position);
|
||||||
@ -553,7 +553,7 @@ bool LuaEntitySAO::getCollisionBox(aabb3f *toset) const
|
|||||||
|
|
||||||
bool LuaEntitySAO::getSelectionBox(aabb3f *toset) const
|
bool LuaEntitySAO::getSelectionBox(aabb3f *toset) const
|
||||||
{
|
{
|
||||||
if (!m_prop.is_visible || !m_prop.pointable) {
|
if (!m_prop.is_visible) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, session_t p
|
|||||||
m_prop.physical = false;
|
m_prop.physical = false;
|
||||||
m_prop.collisionbox = aabb3f(-0.3f, 0.0f, -0.3f, 0.3f, 1.77f, 0.3f);
|
m_prop.collisionbox = aabb3f(-0.3f, 0.0f, -0.3f, 0.3f, 1.77f, 0.3f);
|
||||||
m_prop.selectionbox = aabb3f(-0.3f, 0.0f, -0.3f, 0.3f, 1.77f, 0.3f);
|
m_prop.selectionbox = aabb3f(-0.3f, 0.0f, -0.3f, 0.3f, 1.77f, 0.3f);
|
||||||
m_prop.pointable = true;
|
m_prop.pointable = PointabilityType::POINTABLE;
|
||||||
// Start of default appearance, this should be overwritten by Lua
|
// Start of default appearance, this should be overwritten by Lua
|
||||||
m_prop.visual = "upright_sprite";
|
m_prop.visual = "upright_sprite";
|
||||||
m_prop.visual_size = v3f(1, 2, 1);
|
m_prop.visual_size = v3f(1, 2, 1);
|
||||||
@ -724,7 +724,7 @@ bool PlayerSAO::getCollisionBox(aabb3f *toset) const
|
|||||||
|
|
||||||
bool PlayerSAO::getSelectionBox(aabb3f *toset) const
|
bool PlayerSAO::getSelectionBox(aabb3f *toset) const
|
||||||
{
|
{
|
||||||
if (!m_prop.is_visible || !m_prop.pointable) {
|
if (!m_prop.is_visible) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1830,7 +1830,8 @@ bool ServerEnvironment::getActiveObjectMessage(ActiveObjectMessage *dest)
|
|||||||
|
|
||||||
void ServerEnvironment::getSelectedActiveObjects(
|
void ServerEnvironment::getSelectedActiveObjects(
|
||||||
const core::line3d<f32> &shootline_on_map,
|
const core::line3d<f32> &shootline_on_map,
|
||||||
std::vector<PointedThing> &objects)
|
std::vector<PointedThing> &objects,
|
||||||
|
const std::optional<Pointabilities> &pointabilities)
|
||||||
{
|
{
|
||||||
std::vector<ServerActiveObject *> objs;
|
std::vector<ServerActiveObject *> objs;
|
||||||
getObjectsInsideRadius(objs, shootline_on_map.start,
|
getObjectsInsideRadius(objs, shootline_on_map.start,
|
||||||
@ -1863,10 +1864,26 @@ void ServerEnvironment::getSelectedActiveObjects(
|
|||||||
current_raw_normal = current_normal;
|
current_raw_normal = current_normal;
|
||||||
}
|
}
|
||||||
if (collision) {
|
if (collision) {
|
||||||
|
PointabilityType pointable;
|
||||||
|
if (pointabilities) {
|
||||||
|
if (LuaEntitySAO* lsao = dynamic_cast<LuaEntitySAO*>(obj)) {
|
||||||
|
pointable = pointabilities->matchObject(lsao->getName(),
|
||||||
|
usao->getArmorGroups()).value_or(props->pointable);
|
||||||
|
} else if (PlayerSAO* psao = dynamic_cast<PlayerSAO*>(obj)) {
|
||||||
|
pointable = pointabilities->matchPlayer(psao->getArmorGroups()).value_or(
|
||||||
|
props->pointable);
|
||||||
|
} else {
|
||||||
|
pointable = props->pointable;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pointable = props->pointable;
|
||||||
|
}
|
||||||
|
if (pointable != PointabilityType::POINTABLE_NOT) {
|
||||||
current_intersection += pos;
|
current_intersection += pos;
|
||||||
objects.emplace_back(
|
objects.emplace_back(
|
||||||
(s16) obj->getId(), current_intersection, current_normal, current_raw_normal,
|
(s16) obj->getId(), current_intersection, current_normal, current_raw_normal,
|
||||||
(current_intersection - shootline_on_map.start).getLengthSQ());
|
(current_intersection - shootline_on_map.start).getLengthSQ(), pointable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -315,7 +315,8 @@ public:
|
|||||||
|
|
||||||
virtual void getSelectedActiveObjects(
|
virtual void getSelectedActiveObjects(
|
||||||
const core::line3d<f32> &shootline_on_map,
|
const core::line3d<f32> &shootline_on_map,
|
||||||
std::vector<PointedThing> &objects
|
std::vector<PointedThing> &objects,
|
||||||
|
const std::optional<Pointabilities> &pointabilities
|
||||||
);
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -8,6 +8,7 @@ set(UTIL_SRCS
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/metricsbackend.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/metricsbackend.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/numeric.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/numeric.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/pointedthing.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/pointedthing.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/pointabilities.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/quicktune.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/quicktune.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/serialize.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/serialize.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/sha1.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/sha1.cpp
|
||||||
|
147
src/util/pointabilities.cpp
Normal file
147
src/util/pointabilities.cpp
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
Minetest
|
||||||
|
Copyright (C) 2023 cx384
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "pointabilities.h"
|
||||||
|
|
||||||
|
#include "serialize.h"
|
||||||
|
#include "exceptions.h"
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
PointabilityType Pointabilities::deSerializePointabilityType(std::istream &is)
|
||||||
|
{
|
||||||
|
PointabilityType pointable_type = static_cast<PointabilityType>(readU8(is));
|
||||||
|
switch(pointable_type) {
|
||||||
|
case PointabilityType::POINTABLE:
|
||||||
|
case PointabilityType::POINTABLE_NOT:
|
||||||
|
case PointabilityType::POINTABLE_BLOCKING:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Default to POINTABLE in case of unknown PointabilityType type.
|
||||||
|
pointable_type = PointabilityType::POINTABLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return pointable_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pointabilities::serializePointabilityType(std::ostream &os, PointabilityType pointable_type)
|
||||||
|
{
|
||||||
|
writeU8(os, static_cast<u8>(pointable_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Pointabilities::toStringPointabilityType(PointabilityType pointable_type)
|
||||||
|
{
|
||||||
|
switch(pointable_type) {
|
||||||
|
case PointabilityType::POINTABLE:
|
||||||
|
return "true";
|
||||||
|
case PointabilityType::POINTABLE_NOT:
|
||||||
|
return "false";
|
||||||
|
case PointabilityType::POINTABLE_BLOCKING:
|
||||||
|
return "\"blocking\"";
|
||||||
|
}
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<PointabilityType> Pointabilities::matchNode(const std::string &name,
|
||||||
|
const ItemGroupList &groups) const
|
||||||
|
{
|
||||||
|
auto i = nodes.find(name);
|
||||||
|
return i == nodes.end() ? matchGroups(groups, node_groups) : i->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<PointabilityType> Pointabilities::matchObject(const std::string &name,
|
||||||
|
const ItemGroupList &groups) const
|
||||||
|
{
|
||||||
|
auto i = objects.find(name);
|
||||||
|
return i == objects.end() ? matchGroups(groups, object_groups) : i->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<PointabilityType> Pointabilities::matchPlayer(const ItemGroupList &groups) const
|
||||||
|
{
|
||||||
|
return matchGroups(groups, object_groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<PointabilityType> Pointabilities::matchGroups(const ItemGroupList &groups,
|
||||||
|
const std::unordered_map<std::string, PointabilityType> &pointable_groups)
|
||||||
|
{
|
||||||
|
// prefers POINTABLE over POINTABLE_NOT over POINTABLE_BLOCKING
|
||||||
|
bool blocking = false;
|
||||||
|
bool not_pointable = false;
|
||||||
|
for (auto const &ability : pointable_groups) {
|
||||||
|
if (itemgroup_get(groups, ability.first) > 0) {
|
||||||
|
switch(ability.second) {
|
||||||
|
case PointabilityType::POINTABLE:
|
||||||
|
return PointabilityType::POINTABLE;
|
||||||
|
case PointabilityType::POINTABLE_NOT:
|
||||||
|
not_pointable = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
blocking = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (not_pointable)
|
||||||
|
return PointabilityType::POINTABLE_NOT;
|
||||||
|
if (blocking)
|
||||||
|
return PointabilityType::POINTABLE_BLOCKING;
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pointabilities::serializeTypeMap(std::ostream &os,
|
||||||
|
const std::unordered_map<std::string, PointabilityType> &map)
|
||||||
|
{
|
||||||
|
writeU32(os, map.size());
|
||||||
|
for (const auto &entry : map) {
|
||||||
|
os << serializeString16(entry.first);
|
||||||
|
writeU8(os, (u8)entry.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pointabilities::deSerializeTypeMap(std::istream &is,
|
||||||
|
std::unordered_map<std::string, PointabilityType> &map)
|
||||||
|
{
|
||||||
|
map.clear();
|
||||||
|
u32 size = readU32(is);
|
||||||
|
for (u32 i = 0; i < size; i++) {
|
||||||
|
std::string name = deSerializeString16(is);
|
||||||
|
PointabilityType type = Pointabilities::deSerializePointabilityType(is);
|
||||||
|
map[name] = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pointabilities::serialize(std::ostream &os) const
|
||||||
|
{
|
||||||
|
writeU8(os, 0); // version
|
||||||
|
serializeTypeMap(os, nodes);
|
||||||
|
serializeTypeMap(os, node_groups);
|
||||||
|
serializeTypeMap(os, objects);
|
||||||
|
serializeTypeMap(os, object_groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pointabilities::deSerialize(std::istream &is)
|
||||||
|
{
|
||||||
|
int version = readU8(is);
|
||||||
|
if (version != 0)
|
||||||
|
throw SerializationError("unsupported Pointabilities version");
|
||||||
|
|
||||||
|
deSerializeTypeMap(is, nodes);
|
||||||
|
deSerializeTypeMap(is, node_groups);
|
||||||
|
deSerializeTypeMap(is, objects);
|
||||||
|
deSerializeTypeMap(is, object_groups);
|
||||||
|
}
|
70
src/util/pointabilities.h
Normal file
70
src/util/pointabilities.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
Minetest
|
||||||
|
Copyright (C) 2023 cx384
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include "itemgroup.h"
|
||||||
|
#include <optional>
|
||||||
|
#include "irrlichttypes.h"
|
||||||
|
|
||||||
|
enum class PointabilityType : u8
|
||||||
|
{
|
||||||
|
POINTABLE,
|
||||||
|
POINTABLE_NOT, // Can be pointed through.
|
||||||
|
POINTABLE_BLOCKING,
|
||||||
|
};
|
||||||
|
|
||||||
|
// An object to store overridden pointable properties
|
||||||
|
struct Pointabilities
|
||||||
|
{
|
||||||
|
// Nodes
|
||||||
|
std::unordered_map<std::string, PointabilityType> nodes;
|
||||||
|
std::unordered_map<std::string, PointabilityType> node_groups;
|
||||||
|
|
||||||
|
// Objects
|
||||||
|
std::unordered_map<std::string, PointabilityType> objects;
|
||||||
|
std::unordered_map<std::string, PointabilityType> object_groups; // armor_groups
|
||||||
|
|
||||||
|
// Match functions return fitting pointability,
|
||||||
|
// otherwise the default pointability should be used.
|
||||||
|
|
||||||
|
std::optional<PointabilityType> matchNode(const std::string &name,
|
||||||
|
const ItemGroupList &groups) const;
|
||||||
|
std::optional<PointabilityType> matchObject(const std::string &name,
|
||||||
|
const ItemGroupList &groups) const;
|
||||||
|
// For players only armor groups will work
|
||||||
|
std::optional<PointabilityType> matchPlayer(const ItemGroupList &groups) const;
|
||||||
|
|
||||||
|
void serialize(std::ostream &os) const;
|
||||||
|
void deSerialize(std::istream &is);
|
||||||
|
|
||||||
|
// For a save enum conversion.
|
||||||
|
static PointabilityType deSerializePointabilityType(std::istream &is);
|
||||||
|
static void serializePointabilityType(std::ostream &os, PointabilityType pointable_type);
|
||||||
|
static std::string toStringPointabilityType(PointabilityType pointable_type);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::optional<PointabilityType> matchGroups(const ItemGroupList &groups,
|
||||||
|
const std::unordered_map<std::string, PointabilityType> &pointable_groups);
|
||||||
|
static void serializeTypeMap(std::ostream &os,
|
||||||
|
const std::unordered_map<std::string, PointabilityType> &map);
|
||||||
|
static void deSerializeTypeMap(std::istream &is,
|
||||||
|
std::unordered_map<std::string, PointabilityType> &map);
|
||||||
|
};
|
@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
PointedThing::PointedThing(const v3s16 &under, const v3s16 &above,
|
PointedThing::PointedThing(const v3s16 &under, const v3s16 &above,
|
||||||
const v3s16 &real_under, const v3f &point, const v3f &normal,
|
const v3s16 &real_under, const v3f &point, const v3f &normal,
|
||||||
u16 box_id, f32 distSq):
|
u16 box_id, f32 distSq, PointabilityType pointab):
|
||||||
type(POINTEDTHING_NODE),
|
type(POINTEDTHING_NODE),
|
||||||
node_undersurface(under),
|
node_undersurface(under),
|
||||||
node_abovesurface(above),
|
node_abovesurface(above),
|
||||||
@ -33,17 +33,19 @@ PointedThing::PointedThing(const v3s16 &under, const v3s16 &above,
|
|||||||
intersection_point(point),
|
intersection_point(point),
|
||||||
intersection_normal(normal),
|
intersection_normal(normal),
|
||||||
box_id(box_id),
|
box_id(box_id),
|
||||||
distanceSq(distSq)
|
distanceSq(distSq),
|
||||||
|
pointability(pointab)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
PointedThing::PointedThing(u16 id, const v3f &point,
|
PointedThing::PointedThing(u16 id, const v3f &point, const v3f &normal,
|
||||||
const v3f &normal, const v3f &raw_normal, f32 distSq) :
|
const v3f &raw_normal, f32 distSq, PointabilityType pointab) :
|
||||||
type(POINTEDTHING_OBJECT),
|
type(POINTEDTHING_OBJECT),
|
||||||
object_id(id),
|
object_id(id),
|
||||||
intersection_point(point),
|
intersection_point(point),
|
||||||
intersection_normal(normal),
|
intersection_normal(normal),
|
||||||
raw_intersection_normal(raw_normal),
|
raw_intersection_normal(raw_normal),
|
||||||
distanceSq(distSq)
|
distanceSq(distSq),
|
||||||
|
pointability(pointab)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
std::string PointedThing::dump() const
|
std::string PointedThing::dump() const
|
||||||
@ -118,12 +120,13 @@ bool PointedThing::operator==(const PointedThing &pt2) const
|
|||||||
{
|
{
|
||||||
if ((node_undersurface != pt2.node_undersurface)
|
if ((node_undersurface != pt2.node_undersurface)
|
||||||
|| (node_abovesurface != pt2.node_abovesurface)
|
|| (node_abovesurface != pt2.node_abovesurface)
|
||||||
|| (node_real_undersurface != pt2.node_real_undersurface))
|
|| (node_real_undersurface != pt2.node_real_undersurface)
|
||||||
|
|| (pointability != pt2.pointability))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (type == POINTEDTHING_OBJECT)
|
else if (type == POINTEDTHING_OBJECT)
|
||||||
{
|
{
|
||||||
if (object_id != pt2.object_id)
|
if (object_id != pt2.object_id || pointability != pt2.pointability)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -23,8 +23,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "irr_v3d.h"
|
#include "irr_v3d.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include "pointabilities.h"
|
||||||
|
|
||||||
enum PointedThingType : u8
|
enum PointedThingType :u8
|
||||||
{
|
{
|
||||||
POINTEDTHING_NOTHING,
|
POINTEDTHING_NOTHING,
|
||||||
POINTEDTHING_NODE,
|
POINTEDTHING_NODE,
|
||||||
@ -90,15 +91,20 @@ struct PointedThing
|
|||||||
* ray's start point and the intersection point in irrlicht coordinates.
|
* ray's start point and the intersection point in irrlicht coordinates.
|
||||||
*/
|
*/
|
||||||
f32 distanceSq = 0;
|
f32 distanceSq = 0;
|
||||||
|
/*!
|
||||||
|
* How the object or node has been pointed at.
|
||||||
|
*/
|
||||||
|
PointabilityType pointability = PointabilityType::POINTABLE_NOT;
|
||||||
|
|
||||||
//! Constructor for POINTEDTHING_NOTHING
|
//! Constructor for POINTEDTHING_NOTHING
|
||||||
PointedThing() = default;
|
PointedThing() = default;
|
||||||
//! Constructor for POINTEDTHING_NODE
|
//! Constructor for POINTEDTHING_NODE
|
||||||
PointedThing(const v3s16 &under, const v3s16 &above,
|
PointedThing(const v3s16 &under, const v3s16 &above,
|
||||||
const v3s16 &real_under, const v3f &point, const v3f &normal,
|
const v3s16 &real_under, const v3f &point, const v3f &normal,
|
||||||
u16 box_id, f32 distSq);
|
u16 box_id, f32 distSq, PointabilityType pointability);
|
||||||
//! Constructor for POINTEDTHING_OBJECT
|
//! Constructor for POINTEDTHING_OBJECT
|
||||||
PointedThing(u16 id, const v3f &point, const v3f &normal, const v3f &raw_normal, f32 distSq);
|
PointedThing(u16 id, const v3f &point, const v3f &normal, const v3f &raw_normal, f32 distSq,
|
||||||
|
PointabilityType pointability);
|
||||||
std::string dump() const;
|
std::string dump() const;
|
||||||
void serialize(std::ostream &os) const;
|
void serialize(std::ostream &os) const;
|
||||||
void deSerialize(std::istream &is);
|
void deSerialize(std::istream &is);
|
||||||
|
Loading…
Reference in New Issue
Block a user