From 0c2ee1e41d71899f0d5e1da603a6d125a7cda9e9 Mon Sep 17 00:00:00 2001 From: nixnoxus <87639406+nixnoxus@users.noreply.github.com> Date: Fri, 6 May 2022 20:04:55 +0200 Subject: [PATCH] Deduplicate player action logging, silence fake player actions (#2941) --- game_api.txt | 30 ++++++++++++++++++++++++++++ minetest.conf.example | 3 +++ mods/default/chests.lua | 16 +-------------- mods/default/functions.lua | 41 ++++++++++++++++++++++++++++++++++++++ mods/default/nodes.lua | 32 +++++++++-------------------- mods/default/trees.lua | 3 +-- mods/farming/api.lua | 3 +-- mods/tnt/init.lua | 8 ++------ mods/vessels/init.lua | 21 ++++--------------- settingtypes.txt | 3 +++ 10 files changed, 95 insertions(+), 65 deletions(-) diff --git a/game_api.txt b/game_api.txt index f6231e5a..c8b4cec3 100644 --- a/game_api.txt +++ b/game_api.txt @@ -1115,3 +1115,33 @@ This function registers a shapeless recipe that takes `ingredient` and `result` as input and outputs `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 diff --git a/minetest.conf.example b/minetest.conf.example index 24033063..bb6eb644 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -75,3 +75,6 @@ default:torch 99,default:cobble 99 # Enable cloud and shadow intensity variation by the 'weather' mod. # Non-functional in V6 or Singlenode mapgens. #enable_weather = true + +# If enabled, non-player actions are logged +#log_non_player_actions = false diff --git a/mods/default/chests.lua b/mods/default/chests.lua index f4462ae7..585b5f7c 100644 --- a/mods/default/chests.lua +++ b/mods/default/chests.lua @@ -222,21 +222,7 @@ function default.chest.register_chest(prefixed_name, d) end end - def.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 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 + default.set_inventory_action_loggers(def, "chest") local def_opened = table.copy(def) local def_closed = table.copy(def) diff --git a/mods/default/functions.lua b/mods/default/functions.lua index 4d89a384..0afd97ed 100644 --- a/mods/default/functions.lua +++ b/mods/default/functions.lua @@ -715,6 +715,47 @@ function default.register_craft_metadata_copy(ingredient, result) 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. diff --git a/mods/default/nodes.lua b/mods/default/nodes.lua index a2974517..269c578c 100644 --- a/mods/default/nodes.lua +++ b/mods/default/nodes.lua @@ -2057,10 +2057,9 @@ local function coral_on_place(itemstack, placer, pointed_thing) if minetest.is_protected(pos_under, player_name) or minetest.is_protected(pos_above, player_name) then - minetest.log("action", player_name - .. " tried to place " .. itemstack:get_name() - .. " at protected position " - .. minetest.pos_to_string(pos_under)) + default.log_player_action(placer, + "tried to place", itemstack:get_name(), + "at protected position", pos_under) minetest.record_protection_violation(pos_under, player_name) return itemstack end @@ -2525,7 +2524,7 @@ local function update_bookshelf(pos) end end -minetest.register_node("default:bookshelf", { +local default_bookshelf_def = { description = S("Bookshelf"), tiles = {"default_wood.png", "default_wood.png", "default_wood.png", "default_wood.png", "default_bookshelf.png", "default_bookshelf.png"}, @@ -2550,21 +2549,6 @@ minetest.register_node("default:bookshelf", { end return 0 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) local drops = {} default.get_inventory_drops(pos, "books", drops) @@ -2572,7 +2556,9 @@ minetest.register_node("default:bookshelf", { minetest.remove_node(pos) return drops 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) 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")) return end - minetest.log("action", player_name .. " wrote \"" .. text .. - "\" to the sign at " .. minetest.pos_to_string(pos)) + default.log_player_action(sender, "wrote \"" .. text .. + "\" to the sign at", pos) local meta = minetest.get_meta(pos) meta:set_string("text", text) diff --git a/mods/default/trees.lua b/mods/default/trees.lua index 569beee8..24a96cf0 100644 --- a/mods/default/trees.lua +++ b/mods/default/trees.lua @@ -572,8 +572,7 @@ function default.sapling_on_place(itemstack, placer, pointed_thing, return itemstack end - minetest.log("action", player_name .. " places node " - .. sapling_name .. " at " .. minetest.pos_to_string(pos)) + default.log_player_action(placer, "places node", sapling_name, "at", pos) local take_item = not minetest.is_creative_enabled(player_name) local newnode = {name = sapling_name} diff --git a/mods/farming/api.lua b/mods/farming/api.lua index 15d126e2..c892a779 100644 --- a/mods/farming/api.lua +++ b/mods/farming/api.lua @@ -178,8 +178,7 @@ farming.place_seed = function(itemstack, placer, pointed_thing, plantname) end -- add the node and remove 1 item from the itemstack - minetest.log("action", player_name .. " places node " .. plantname .. " at " .. - minetest.pos_to_string(pt.above)) + default.log_player_action(placer, "places node", plantname, "at", pt.above) minetest.add_node(pt.above, {name = plantname, param2 = 1}) tick(pt.above) if not minetest.is_creative_enabled(player_name) then diff --git a/mods/tnt/init.lua b/mods/tnt/init.lua index 1c4ead33..f4d4681b 100644 --- a/mods/tnt/init.lua +++ b/mods/tnt/init.lua @@ -465,9 +465,7 @@ minetest.register_node("tnt:gunpowder", { on_punch = function(pos, node, puncher) if puncher:get_wielded_item():get_name() == "default:torch" then minetest.set_node(pos, {name = "tnt:gunpowder_burning"}) - minetest.log("action", puncher:get_player_name() .. - " ignites tnt:gunpowder at " .. - minetest.pos_to_string(pos)) + default.log_player_action(puncher, "ignites tnt:gunpowder at", pos) end end, on_blast = function(pos, intensity) @@ -635,9 +633,7 @@ function tnt.register_tnt(def) if puncher:get_wielded_item():get_name() == "default:torch" then minetest.swap_node(pos, {name = name .. "_burning"}) minetest.registered_nodes[name .. "_burning"].on_construct(pos) - minetest.log("action", puncher:get_player_name() .. - " ignites " .. node.name .. " at " .. - minetest.pos_to_string(pos)) + default.log_player_action(puncher, "ignites", node.name, "at", pos) end end, on_blast = function(pos, intensity) diff --git a/mods/vessels/init.lua b/mods/vessels/init.lua index 71a06893..4bd0fb4d 100644 --- a/mods/vessels/init.lua +++ b/mods/vessels/init.lua @@ -49,7 +49,7 @@ local function update_vessels_shelf(pos) end end -minetest.register_node("vessels:shelf", { +local vessels_shelf_def = { description = S("Vessels Shelf"), tiles = {"default_wood.png", "default_wood.png", "default_wood.png", "default_wood.png", "vessels_shelf.png", "vessels_shelf.png"}, @@ -74,21 +74,6 @@ minetest.register_node("vessels:shelf", { end return 0 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) local drops = {} default.get_inventory_drops(pos, "vessels", drops) @@ -96,7 +81,9 @@ minetest.register_node("vessels:shelf", { minetest.remove_node(pos) return drops end, -}) +} +default.set_inventory_action_loggers(vessels_shelf_def, "vessels shelf") +minetest.register_node("vessels:shelf", vessels_shelf_def) minetest.register_craft({ output = "vessels:shelf", diff --git a/settingtypes.txt b/settingtypes.txt index a597fc7e..445510ff 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -75,3 +75,6 @@ river_source_sounds (River source node sounds) bool false # Enable cloud and shadow intensity variation by the 'weather' mod. # Non-functional in V6 or Singlenode mapgens. enable_weather (Enable weather) bool true + +# If enabled, non-player actions are logged +log_non_player_actions (Log non-player action) bool false