mirror of
https://github.com/minetest/minetest_game.git
synced 2024-12-22 14:12:26 +01:00
Deduplicate player action logging, silence fake player actions (#2941)
This commit is contained in:
parent
edd033b708
commit
0c2ee1e41d
30
game_api.txt
30
game_api.txt
@ -1115,3 +1115,33 @@ This function registers a shapeless recipe that takes `ingredient`
|
|||||||
and `result` as input and outputs `result`.
|
and `result` as input and outputs `result`.
|
||||||
|
|
||||||
The metadata of the input `result` is copied to the output `result`.
|
The metadata of the input `result` is copied to the output `result`.
|
||||||
|
|
||||||
|
|
||||||
|
Log API
|
||||||
|
-------
|
||||||
|
|
||||||
|
Logs action of the player with a node at a certain position.
|
||||||
|
By default only actions of real players are logged.
|
||||||
|
Actions of non-players (usually machines) are logged only when
|
||||||
|
setting `log_non_player_actions` is enabled.
|
||||||
|
A player is considered non-player if `player:is_player()` returns
|
||||||
|
`false` or `player.is_fake_player` is truthy. The use of
|
||||||
|
`is_fake_player` is an unofficial standard between mods.
|
||||||
|
These non-players are marked by the content of `is_fake_player`
|
||||||
|
(if it is a string) or a "*" in brackets after the player name in
|
||||||
|
the log.
|
||||||
|
|
||||||
|
`default.log_player_action(player, ...)`
|
||||||
|
|
||||||
|
* `player` The player who performed the action
|
||||||
|
* `message_parts` Any mumber of message parts describing the action
|
||||||
|
in 3rd person singular present tense. It can also
|
||||||
|
contain a `pos` which is logged as "(X,Y,Z)"
|
||||||
|
|
||||||
|
`default.set_inventory_action_loggers(def, name)`
|
||||||
|
|
||||||
|
* sets the callbacks `on_metadata_inventory_move`,
|
||||||
|
`on_metadata_inventory_put` and `on_metadata_inventory_take`
|
||||||
|
that log corresponding actions
|
||||||
|
* `def` See [Node definition]
|
||||||
|
* `name` Description of the node in the log message
|
||||||
|
@ -75,3 +75,6 @@ default:torch 99,default:cobble 99
|
|||||||
# Enable cloud and shadow intensity variation by the 'weather' mod.
|
# Enable cloud and shadow intensity variation by the 'weather' mod.
|
||||||
# Non-functional in V6 or Singlenode mapgens.
|
# Non-functional in V6 or Singlenode mapgens.
|
||||||
#enable_weather = true
|
#enable_weather = true
|
||||||
|
|
||||||
|
# If enabled, non-player actions are logged
|
||||||
|
#log_non_player_actions = false
|
||||||
|
@ -222,21 +222,7 @@ function default.chest.register_chest(prefixed_name, d)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def.on_metadata_inventory_move = function(pos, from_list, from_index,
|
default.set_inventory_action_loggers(def, "chest")
|
||||||
to_list, to_index, count, player)
|
|
||||||
minetest.log("action", player:get_player_name() ..
|
|
||||||
" moves stuff in chest at " .. minetest.pos_to_string(pos))
|
|
||||||
end
|
|
||||||
def.on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
|
||||||
minetest.log("action", player:get_player_name() ..
|
|
||||||
" moves " .. stack:get_name() ..
|
|
||||||
" to chest at " .. minetest.pos_to_string(pos))
|
|
||||||
end
|
|
||||||
def.on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
|
||||||
minetest.log("action", player:get_player_name() ..
|
|
||||||
" takes " .. stack:get_name() ..
|
|
||||||
" from chest at " .. minetest.pos_to_string(pos))
|
|
||||||
end
|
|
||||||
|
|
||||||
local def_opened = table.copy(def)
|
local def_opened = table.copy(def)
|
||||||
local def_closed = table.copy(def)
|
local def_closed = table.copy(def)
|
||||||
|
@ -715,6 +715,47 @@ function default.register_craft_metadata_copy(ingredient, result)
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Log API / helpers
|
||||||
|
--
|
||||||
|
|
||||||
|
local log_non_player_actions = minetest.settings:get_bool("log_non_player_actions", false)
|
||||||
|
|
||||||
|
local is_pos = function(v)
|
||||||
|
return type(v) == "table" and
|
||||||
|
type(v.x) == "number" and type(v.y) == "number" and type(v.z) == "number"
|
||||||
|
end
|
||||||
|
|
||||||
|
function default.log_player_action(player, ...)
|
||||||
|
local msg = player:get_player_name()
|
||||||
|
if player.is_fake_player or not player:is_player() then
|
||||||
|
if not log_non_player_actions then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
msg = msg .. "(" .. (type(player.is_fake_player) == "string"
|
||||||
|
and player.is_fake_player or "*") .. ")"
|
||||||
|
end
|
||||||
|
for _, v in ipairs({...}) do
|
||||||
|
-- translate pos
|
||||||
|
local part = is_pos(v) and minetest.pos_to_string(v) or v
|
||||||
|
-- no leading spaces before punctuation marks
|
||||||
|
msg = msg .. (string.match(part, "^[;,.]") and "" or " ") .. part
|
||||||
|
end
|
||||||
|
minetest.log("action", msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
function default.set_inventory_action_loggers(def, name)
|
||||||
|
def.on_metadata_inventory_move = function(pos, from_list, from_index,
|
||||||
|
to_list, to_index, count, player)
|
||||||
|
default.log_player_action(player, "moves stuff in", name, "at", pos)
|
||||||
|
end
|
||||||
|
def.on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||||
|
default.log_player_action(player, "moves", stack:get_name(), "to", name, "at", pos)
|
||||||
|
end
|
||||||
|
def.on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||||
|
default.log_player_action(player, "takes", stack:get_name(), "from", name, "at", pos)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
-- NOTICE: This method is not an official part of the API yet.
|
-- NOTICE: This method is not an official part of the API yet.
|
||||||
|
@ -2057,10 +2057,9 @@ local function coral_on_place(itemstack, placer, pointed_thing)
|
|||||||
|
|
||||||
if minetest.is_protected(pos_under, player_name) or
|
if minetest.is_protected(pos_under, player_name) or
|
||||||
minetest.is_protected(pos_above, player_name) then
|
minetest.is_protected(pos_above, player_name) then
|
||||||
minetest.log("action", player_name
|
default.log_player_action(placer,
|
||||||
.. " tried to place " .. itemstack:get_name()
|
"tried to place", itemstack:get_name(),
|
||||||
.. " at protected position "
|
"at protected position", pos_under)
|
||||||
.. minetest.pos_to_string(pos_under))
|
|
||||||
minetest.record_protection_violation(pos_under, player_name)
|
minetest.record_protection_violation(pos_under, player_name)
|
||||||
return itemstack
|
return itemstack
|
||||||
end
|
end
|
||||||
@ -2525,7 +2524,7 @@ local function update_bookshelf(pos)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_node("default:bookshelf", {
|
local default_bookshelf_def = {
|
||||||
description = S("Bookshelf"),
|
description = S("Bookshelf"),
|
||||||
tiles = {"default_wood.png", "default_wood.png", "default_wood.png",
|
tiles = {"default_wood.png", "default_wood.png", "default_wood.png",
|
||||||
"default_wood.png", "default_bookshelf.png", "default_bookshelf.png"},
|
"default_wood.png", "default_bookshelf.png", "default_bookshelf.png"},
|
||||||
@ -2550,21 +2549,6 @@ minetest.register_node("default:bookshelf", {
|
|||||||
end
|
end
|
||||||
return 0
|
return 0
|
||||||
end,
|
end,
|
||||||
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
|
||||||
minetest.log("action", player:get_player_name() ..
|
|
||||||
" moves stuff in bookshelf at " .. minetest.pos_to_string(pos))
|
|
||||||
update_bookshelf(pos)
|
|
||||||
end,
|
|
||||||
on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
|
||||||
minetest.log("action", player:get_player_name() ..
|
|
||||||
" puts stuff to bookshelf at " .. minetest.pos_to_string(pos))
|
|
||||||
update_bookshelf(pos)
|
|
||||||
end,
|
|
||||||
on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
|
||||||
minetest.log("action", player:get_player_name() ..
|
|
||||||
" takes stuff from bookshelf at " .. minetest.pos_to_string(pos))
|
|
||||||
update_bookshelf(pos)
|
|
||||||
end,
|
|
||||||
on_blast = function(pos)
|
on_blast = function(pos)
|
||||||
local drops = {}
|
local drops = {}
|
||||||
default.get_inventory_drops(pos, "books", drops)
|
default.get_inventory_drops(pos, "books", drops)
|
||||||
@ -2572,7 +2556,9 @@ minetest.register_node("default:bookshelf", {
|
|||||||
minetest.remove_node(pos)
|
minetest.remove_node(pos)
|
||||||
return drops
|
return drops
|
||||||
end,
|
end,
|
||||||
})
|
}
|
||||||
|
default.set_inventory_action_loggers(default_bookshelf_def, "bookshelf")
|
||||||
|
minetest.register_node("default:bookshelf", default_bookshelf_def)
|
||||||
|
|
||||||
local function register_sign(material, desc, def)
|
local function register_sign(material, desc, def)
|
||||||
minetest.register_node("default:sign_wall_" .. material, {
|
minetest.register_node("default:sign_wall_" .. material, {
|
||||||
@ -2615,8 +2601,8 @@ local function register_sign(material, desc, def)
|
|||||||
minetest.chat_send_player(player_name, S("Text too long"))
|
minetest.chat_send_player(player_name, S("Text too long"))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
minetest.log("action", player_name .. " wrote \"" .. text ..
|
default.log_player_action(sender, "wrote \"" .. text ..
|
||||||
"\" to the sign at " .. minetest.pos_to_string(pos))
|
"\" to the sign at", pos)
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
meta:set_string("text", text)
|
meta:set_string("text", text)
|
||||||
|
|
||||||
|
@ -572,8 +572,7 @@ function default.sapling_on_place(itemstack, placer, pointed_thing,
|
|||||||
return itemstack
|
return itemstack
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.log("action", player_name .. " places node "
|
default.log_player_action(placer, "places node", sapling_name, "at", pos)
|
||||||
.. sapling_name .. " at " .. minetest.pos_to_string(pos))
|
|
||||||
|
|
||||||
local take_item = not minetest.is_creative_enabled(player_name)
|
local take_item = not minetest.is_creative_enabled(player_name)
|
||||||
local newnode = {name = sapling_name}
|
local newnode = {name = sapling_name}
|
||||||
|
@ -178,8 +178,7 @@ farming.place_seed = function(itemstack, placer, pointed_thing, plantname)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- add the node and remove 1 item from the itemstack
|
-- add the node and remove 1 item from the itemstack
|
||||||
minetest.log("action", player_name .. " places node " .. plantname .. " at " ..
|
default.log_player_action(placer, "places node", plantname, "at", pt.above)
|
||||||
minetest.pos_to_string(pt.above))
|
|
||||||
minetest.add_node(pt.above, {name = plantname, param2 = 1})
|
minetest.add_node(pt.above, {name = plantname, param2 = 1})
|
||||||
tick(pt.above)
|
tick(pt.above)
|
||||||
if not minetest.is_creative_enabled(player_name) then
|
if not minetest.is_creative_enabled(player_name) then
|
||||||
|
@ -465,9 +465,7 @@ minetest.register_node("tnt:gunpowder", {
|
|||||||
on_punch = function(pos, node, puncher)
|
on_punch = function(pos, node, puncher)
|
||||||
if puncher:get_wielded_item():get_name() == "default:torch" then
|
if puncher:get_wielded_item():get_name() == "default:torch" then
|
||||||
minetest.set_node(pos, {name = "tnt:gunpowder_burning"})
|
minetest.set_node(pos, {name = "tnt:gunpowder_burning"})
|
||||||
minetest.log("action", puncher:get_player_name() ..
|
default.log_player_action(puncher, "ignites tnt:gunpowder at", pos)
|
||||||
" ignites tnt:gunpowder at " ..
|
|
||||||
minetest.pos_to_string(pos))
|
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
on_blast = function(pos, intensity)
|
on_blast = function(pos, intensity)
|
||||||
@ -635,9 +633,7 @@ function tnt.register_tnt(def)
|
|||||||
if puncher:get_wielded_item():get_name() == "default:torch" then
|
if puncher:get_wielded_item():get_name() == "default:torch" then
|
||||||
minetest.swap_node(pos, {name = name .. "_burning"})
|
minetest.swap_node(pos, {name = name .. "_burning"})
|
||||||
minetest.registered_nodes[name .. "_burning"].on_construct(pos)
|
minetest.registered_nodes[name .. "_burning"].on_construct(pos)
|
||||||
minetest.log("action", puncher:get_player_name() ..
|
default.log_player_action(puncher, "ignites", node.name, "at", pos)
|
||||||
" ignites " .. node.name .. " at " ..
|
|
||||||
minetest.pos_to_string(pos))
|
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
on_blast = function(pos, intensity)
|
on_blast = function(pos, intensity)
|
||||||
|
@ -49,7 +49,7 @@ local function update_vessels_shelf(pos)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_node("vessels:shelf", {
|
local vessels_shelf_def = {
|
||||||
description = S("Vessels Shelf"),
|
description = S("Vessels Shelf"),
|
||||||
tiles = {"default_wood.png", "default_wood.png", "default_wood.png",
|
tiles = {"default_wood.png", "default_wood.png", "default_wood.png",
|
||||||
"default_wood.png", "vessels_shelf.png", "vessels_shelf.png"},
|
"default_wood.png", "vessels_shelf.png", "vessels_shelf.png"},
|
||||||
@ -74,21 +74,6 @@ minetest.register_node("vessels:shelf", {
|
|||||||
end
|
end
|
||||||
return 0
|
return 0
|
||||||
end,
|
end,
|
||||||
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
|
||||||
minetest.log("action", player:get_player_name() ..
|
|
||||||
" moves stuff in vessels shelf at ".. minetest.pos_to_string(pos))
|
|
||||||
update_vessels_shelf(pos)
|
|
||||||
end,
|
|
||||||
on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
|
||||||
minetest.log("action", player:get_player_name() ..
|
|
||||||
" moves stuff to vessels shelf at ".. minetest.pos_to_string(pos))
|
|
||||||
update_vessels_shelf(pos)
|
|
||||||
end,
|
|
||||||
on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
|
||||||
minetest.log("action", player:get_player_name() ..
|
|
||||||
" takes stuff from vessels shelf at ".. minetest.pos_to_string(pos))
|
|
||||||
update_vessels_shelf(pos)
|
|
||||||
end,
|
|
||||||
on_blast = function(pos)
|
on_blast = function(pos)
|
||||||
local drops = {}
|
local drops = {}
|
||||||
default.get_inventory_drops(pos, "vessels", drops)
|
default.get_inventory_drops(pos, "vessels", drops)
|
||||||
@ -96,7 +81,9 @@ minetest.register_node("vessels:shelf", {
|
|||||||
minetest.remove_node(pos)
|
minetest.remove_node(pos)
|
||||||
return drops
|
return drops
|
||||||
end,
|
end,
|
||||||
})
|
}
|
||||||
|
default.set_inventory_action_loggers(vessels_shelf_def, "vessels shelf")
|
||||||
|
minetest.register_node("vessels:shelf", vessels_shelf_def)
|
||||||
|
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
output = "vessels:shelf",
|
output = "vessels:shelf",
|
||||||
|
@ -75,3 +75,6 @@ river_source_sounds (River source node sounds) bool false
|
|||||||
# Enable cloud and shadow intensity variation by the 'weather' mod.
|
# Enable cloud and shadow intensity variation by the 'weather' mod.
|
||||||
# Non-functional in V6 or Singlenode mapgens.
|
# Non-functional in V6 or Singlenode mapgens.
|
||||||
enable_weather (Enable weather) bool true
|
enable_weather (Enable weather) bool true
|
||||||
|
|
||||||
|
# If enabled, non-player actions are logged
|
||||||
|
log_non_player_actions (Log non-player action) bool false
|
||||||
|
Loading…
Reference in New Issue
Block a user