Update init.lua

This commit is contained in:
Nicolas 2024-01-24 10:02:48 +01:00 committed by GitHub
parent 411b417c39
commit 7868547cdf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

496
init.lua
View File

@ -1,3 +1,5 @@
blockwatch = {}
local S = minetest.get_translator("BlockWatch") -- Récupérer le traducteur pour ce mod
-- Chemin vers le fichier JSON pour les événements
@ -7,41 +9,38 @@ local events_json_file_path = minetest.get_worldpath() .. "/blockwatch_data.json
local events = {}
local events_backup = {}
-- Fonction pour charger la base de données des événements
local function load_events_database()
function blockwatch.load_events_database()
local json_file = io.open(events_json_file_path, "r")
if json_file then
events = minetest.deserialize(json_file:read("*all"))
json_file:close()
minetest.log("action", S("[blockwatch] Event database loaded successfully."))
minetest.log("action", S("[blockwatch] Base de données d'événements chargée avec succès."))
else
-- Créer le fichier JSON s'il n'existe pas
local new_json_file = io.open(events_json_file_path, "w")
new_json_file:write(minetest.serialize(events))
new_json_file:close()
minetest.log("action", S("[blockwatch] New event database created."))
minetest.log("action", S("[blockwatch] Nouvelle base de données d'événements créée."))
end
end
-- Fonction pour sauvegarder les événements dans le fichier JSON
local function save_events()
function blockwatch.save_events()
local json_file = io.open(events_json_file_path, "w")
if json_file then
json_file:write(minetest.serialize(events))
json_file:close()
end
--envoie la taille de la base de donnée dans le chat et utilise la meme logique que la commande /events_stats
end
-- Charge les données depuis le fichier JSON
local function load_blockwatch_data()
minetest.log("action", S("[blockwatch] Loading data from JSON file: ") .. events_json_file_path)
function blockwatch.load_blockwatch_data()
minetest.log("action", S("[blockwatch] Chargement des données depuis le fichier JSON : ") .. events_json_file_path)
local file = io.open(events_json_file_path, "r")
if not file then
minetest.log("action", S("[blockwatch] The JSON file does not exist."))
minetest.log("action", S("[blockwatch] Le fichier JSON n'existe pas."))
return {}
end
@ -51,7 +50,7 @@ local function load_blockwatch_data()
end
-- Fonction pour sauvegarder les données sur le bloc pointé dans le fichier JSON
local function save_blockwatch_data(data)
function blockwatch.save_blockwatch_data(data)
local json_file = io.open(events_json_file_path, "w")
if json_file then
json_file:write(minetest.serialize(data))
@ -60,7 +59,7 @@ local function save_blockwatch_data(data)
end
-- Créez d'abord la fonction events_stats
local function events_stats()
function blockwatch.events_stats()
local num_events = 0
local total_size = 0
@ -71,7 +70,7 @@ local function events_stats()
if json_data then
total_size = total_size + #json_data
else
minetest.log("error", S("[blockwatch] Error during JSON serialization for events."))
minetest.log("error", S("[blockwatch] Erreur pendant la sérialisation JSON des événements."))
end
end
@ -80,10 +79,8 @@ local function events_stats()
return num_events, total_size, average_size_per_entry
end
-- Fonction pour nettoyer les anciennes sauvegardes
local function clean_old_backups(max_backups)
function blockwatch.clean_old_backups(max_backups)
local backup_dir = minetest.get_worldpath() .. "/blockwatch_data_backup"
local backups = {}
@ -109,13 +106,12 @@ local function clean_old_backups(max_backups)
-- compte le nombre de fichier dans le dossier blockwatch_data_backup
local dir_list = minetest.get_dir_list(backup_dir) or {}
-- envoie le nombre de fichier dans le chat
--minetest.chat_send_all("Nombre de fichier dans le dossier blockwatch_data_backup : " .. #dir_list .. "")
--minetest.chat_send_all("Nombre de fichiers dans le dossier blockwatch_data_backup : " .. #dir_list .. "")
end
end
-- Fonction pour enregistrer un nouvel événement
local function log_event(pos, event_type, entity, node_name)
function blockwatch.log_event(pos, event_type, entity, node_name)
local key = minetest.pos_to_string(pos)
if not events[key] then
@ -130,228 +126,111 @@ local function log_event(pos, event_type, entity, node_name)
}
table.insert(events[key], event)
save_events()
-- apelle la fonction pour avoir les le nombre d'event
local num_events, total_size, average_size_per_entry = events_stats()
-- envoie le nombre d'event dans le chat
--minetest.chat_send_all("Nombre d'event : " .. num_events)
-- si le nombre d'event est superieur a 1000 alors créer une sauvegarde de la base de donnée actuelle et vide la base de donnée
if num_events > 10000 then
-- sauvegarde la base de donnée actuelle dans un fichier json dans le dossier world dans un docier nommé blockwatch_data_backup dans un fichier nommé blockwatch_data_backup(numero de la backup).json
-- verrifie que le dossier blockwatch_data_backup existe
if not minetest.mkdir(minetest.get_worldpath() .. "/blockwatch_data_backup") then
minetest.log("error", S("[blockwatch] Error creating the blockwatch_data_backup directory."))
end
-- utilise la date et l'heure pour nommer le fichier json
local json_file = io.open(minetest.get_worldpath() .. "/blockwatch_data_backup/blockwatch_data_backup" .. os.date("%Y-%m-%dT%H:%M:%S") .. ".json", "w")
if json_file then
json_file:write(minetest.serialize(events))
json_file:close()
end
clean_old_backups(100)
-- vide la base de donnée
events = {}
save_events()
-- envoie un message dans le chat pour dire que la base de donnée a été sauvegarder et vider
--minetest.chat_send_all("La base de donnée a été sauvegarder et vider")
blockwatch.save_events()
-- appelle la fonction pour obtenir le nombre d'événements
local num_events, total_size, average_size_per_entry = blockwatch.events_stats()
-- envoie le nombre d'événements dans le chat
--minetest.chat_send_all("Nombre d'événements : " .. num_events)
-- si le nombre d'événements est supérieur à 10000 alors créer une sauvegarde de la base de données actuelle et vide la base de données
if num_events > 10000 then
-- sauvegarde la base de données actuelle dans un fichier JSON dans le dossier world dans un dossier nommé blockwatch_data_backup dans un fichier nommé blockwatch_data_backup(numero de la backup).json
-- vérifie que le dossier blockwatch_data_backup existe
if not minetest.mkdir(minetest.get_worldpath() .. "/blockwatch_data_backup") then
minetest.log("error", S("[blockwatch] Erreur lors de la création du répertoire blockwatch_data_backup."))
end
-- utilise la date et l'heure pour nommer le fichier JSON
local json_file = io.open(minetest.get_worldpath() .. "/blockwatch_data_backup/blockwatch_data_backup" .. os.date("%Y-%m-%dT%H:%M:%S") .. ".json", "w")
if json_file then
json_file:write(minetest.serialize(events))
json_file:close()
end
blockwatch.clean_old_backups(100)
-- vide la base de données
events = {}
blockwatch.save_events()
-- envoie un message dans le chat pour dire que la base de données a été sauvegardée et vidée
--minetest.chat_send_all("La base de données a été sauvegardée et vidée")
end
end
minetest.register_craftitem("blockwatch:block_data_checker", {
description = "Block Data Checker",
inventory_image = "blockwatch.png", -- Assurez-vous de remplacer "blockwatch_block_data_checker.png" par le chemin correct de votre image d'inventaire
on_use = function(itemstack, user, pointed_thing)
if pointed_thing.type == "node" then
local pos = minetest.get_pointed_thing_position(pointed_thing, false)
local key = minetest.pos_to_string(pos)
-- Vérifie si des événements sont enregistrés pour cette position
if events[key] then
minetest.chat_send_player(user:get_player_name(), "Événements enregistrés pour la position " .. key .. ":")
for _, event in ipairs(events[key]) do
local event_msg = string.format("[%s] %s %s - Node: %s",
event.timestamp, event.event_type, event.entity or "Unknown", event.node_name)
minetest.chat_send_player(user:get_player_name(), event_msg)
end
else
minetest.chat_send_player(user:get_player_name(), "Aucun événement enregistré pour la position " .. key)
end
end
end,
})
-- enregistrez un événement lorsque le joueur casse ou place un bloc
minetest.register_on_dignode(function(pos, oldnode, digger)
local node_name = oldnode.name
local entity = minetest.get_node_or_nil(pos)
local entity = minetest.get_node_or_nil(pos) -- Récupérer le nœud à la position actuelle
-- Vérifier si un joueur est impliqué
if digger and digger:is_player() then
log_event(pos, "break", digger:get_player_name(), node_name)
blockwatch.log_event(pos, "break", digger:get_player_name(), node_name)
elseif entity then
-- Vérifier si c'est une entité autre qu'un joueur
local entity_type = entity.type
if entity_type and entity_type ~= "player" then
log_event(pos, "break", "Entity:" .. entity_type, node_name)
blockwatch.log_event(pos, "break", "Entity:" .. entity_type, node_name)
else
log_event(pos, "break", "Unknown", node_name)
blockwatch.log_event(pos, "break", "Unknown", node_name)
end
else
log_event(pos, "break", "Unknown", node_name)
blockwatch.log_event(pos, "break", "Unknown", node_name)
end
end)
minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
local node_name = newnode.name
-- envoie le node_name dans le chat
--minetest.chat_send_all("Le node_name est : " .. node_name .. "")
local entity = minetest.get_node_or_nil(pos)
local entity = minetest.get_node_or_nil(pos) -- Récupérer le nœud à la position actuelle
-- Vérifier si un joueur est impliqué
if placer and placer:is_player() then
log_event(pos, "place", placer:get_player_name(), node_name)
blockwatch.log_event(pos, "place", placer:get_player_name(), node_name)
elseif entity then
-- Vérifier si c'est une entité autre qu'un joueur
local entity_type = entity.type
if entity_type and entity_type ~= "player" then
log_event(pos, "place", "Entity:" .. entity_type, node_name)
blockwatch.log_event(pos, "place", "Entity:" .. entity_type, node_name)
else
log_event(pos, "place", "Unknown", node_name)
blockwatch.log_event(pos, "place", "Unknown", node_name)
end
else
log_event(pos, "place", "Unknown", node_name)
blockwatch.log_event(pos, "place", "Unknown", node_name)
end
end)
-- Fonction pour vérifier si la base de données des événements est chargée
local function check_events_database()
if next(events) then
minetest.chat_send_all(S("[blockwatch] The events database is loaded."))
else
minetest.chat_send_all(S("[blockwatch] The events database is not loaded."))
end
end
-- Définir une permission personnalisée
minetest.register_privilege("blockwatch_perm", {
description = S("Allows access to Blockwatch commands."),
give_to_singleplayer = false, -- Permettre à un joueur unique de posséder cette permission
})
-- Commande pour recharger la base de données des événements
minetest.register_chatcommand("reload_database_blockwatch", {
privs = {blockwatch_perm=true},
description = S("Reloads the events database."),
func = function(name, param)
load_events_database()
return true, S("[blockwatch] Events database reloaded successfully.")
end,
})
-- Commande pour vérifier si la base de données des événements est chargée
minetest.register_chatcommand("check_events_database_blockwatch", {
privs = {blockwatch_perm=true},
description = S("Check if the events database is loaded."),
func = function(name, param)
check_events_database()
return true, S("[blockwatch] Events database verification complete.")
end,
})
-- Appeler la fonction load_events_database lors du chargement des mods
minetest.register_on_mods_loaded(load_events_database)
-- Commande pour vérifier les données d'un bloc
minetest.register_chatcommand("check_block_data_blockwatch", {
privs = {blockwatch_perm=true},
description = S("Check data for a specific block."),
params = "<x> <y> <z>",
func = function(name, param)
local player = minetest.get_player_by_name(name)
if not player then
return false, "Le joueur n'est pas trouvé."
end
local x, y, z = param:match("(%S+)%s+(%S+)%s+(%S+)")
if not x or not y or not z then
return false, S("Please specify the coordinates of the block (e.g., /check_block_data 10 20 30).")
end
x, y, z = tonumber(x), tonumber(y), tonumber(z)
if not x or not y or not z then
return false, S("The coordinates of the block are not valid.")
end
local pos = {x = x, y = y, z = z}
local key = minetest.pos_to_string(pos)
local blockwatch_data = load_blockwatch_data()
if not next(blockwatch_data) then
return false, S("The database is empty.")
end
if blockwatch_data[key] and #blockwatch_data[key] > 0 then
local json_data = minetest.write_json(blockwatch_data[key])
-- Formater les données pour les rendre plus lisibles
local formatted_data = ""
for _, event in ipairs(blockwatch_data[key]) do
formatted_data = formatted_data .. "entity: " .. event.entity .. "\n"
formatted_data = formatted_data .. "event_type: " .. event.event_type .. "\n"
formatted_data = formatted_data .. "node_name: " .. event.node_name .. "\n"
formatted_data = formatted_data .. "timestamp: " .. event.timestamp .. "\n\n"
end
minetest.chat_send_player(name, S("Block data at ") .. minetest.pos_to_string(pos) .. " : \n" .. formatted_data)
minetest.log("action", "[blockwatch] " .. S("Block data at ") .. minetest.pos_to_string(pos) .. " : \n" .. json_data)
else
minetest.chat_send_player(name, S("No data found for the block at ") .. minetest.pos_to_string(pos))
end
return true, S("Block data verification successful.")
end,
})
-- Fonction pour vérifier les données d'un bloc
local function check_block_data_item(itemstack, user, pointed_thing)
if not user or not pointed_thing or not pointed_thing.under then
return
end
local pos = pointed_thing.under
local key = minetest.pos_to_string(pos)
local blockwatch_data = load_blockwatch_data()
if not next(blockwatch_data) then
minetest.chat_send_player(user:get_player_name(), S("The database is empty."))
return
end
if blockwatch_data[key] and #blockwatch_data[key] > 0 then
local formatted_data = ""
for _, event in ipairs(blockwatch_data[key]) do
formatted_data = formatted_data .. "entity: " .. event.entity .. "\n"
formatted_data = formatted_data .. "event_type: " .. event.event_type .. "\n"
formatted_data = formatted_data .. "node_name: " .. event.node_name .. "\n"
formatted_data = formatted_data .. "timestamp: " .. event.timestamp .. "\n\n"
end
minetest.chat_send_player(user:get_player_name(), S("Block data at ") .. minetest.pos_to_string(pos) .. " : \n" .. formatted_data)
else
minetest.chat_send_player(user:get_player_name(), S("No data found for the block at ") .. minetest.pos_to_string(pos))
end
end
-- Enregistrement de l'item avec le préfixe "blockwatch:"
minetest.register_craftitem("blockwatch:block_data_checker", {
description = S("Block Data Checker"),
inventory_image = "blockwatch.png",
on_use = check_block_data_item,
})
-- Enregistrez ensuite la commande pour obtenir des statistiques sur la base de données des événements
minetest.register_chatcommand("events_stats", {
privs = {blockwatch_perm=true},
description = S("Event Database Statistics"),
func = function(name, param)
-- Utilisez la fonction events_stats pour obtenir les statistiques
local num_events, total_size, average_size_per_entry = events_stats()
local num_events, total_size, average_size_per_entry = blockwatch.events_stats()
-- Affiche les statistiques dans le chat du joueur
minetest.chat_send_player(name, S("Total number of events: ") .. num_events)
@ -363,64 +242,128 @@ minetest.register_chatcommand("events_stats", {
})
-- ce que renvoie la fonction events_stats comme variable
-- events_stats = {num_events = num_events, total_size = total_size, average_size_per_entry = average_size_per_entry}
--comment utiliser les variable de la fonction events_stats
--local events_stats = events_stats()
--minetest.chat_send_player(name, S("Total number of events: ") .. events_stats.num_events)
-- surveille les joueurs qui ouvre les coffres
minetest.register_on_player_receive_fields(function(player, formname, fields)
-- vérifie que le joueur a ouvert un coffre
--minetest.chat_send_all("Le joueur " .. player:get_player_name() .. " a ouvert un coffre l'uid du coffre est : " .. formname .. "")
-- Si le nom du formulaire commence par "mcl_core:chest"
if formname:find("^mcl_chests:chest") then
-- Extraire les coordonnées du nom du formulaire
local x, y, z = formname:match("^mcl_chests:chest_(%-?%d+)_([%d-]+)_([%d-]+)")
if x and y and z then
-- Convertir les coordonnées en nombres
x, y, z = tonumber(x), tonumber(y), tonumber(z)
-- Vérifie si le joueur a quitté le formulaire
if fields.quit then
-- Envoie un message global indiquant que le joueur a ouvert un coffre
--minetest.chat_send_all("Le joueur " .. player:get_player_name() .. " a ouvert un coffre aux coordonnées : (" .. x .. ", " .. y .. ", " .. z .. ")")
-- Ajoute un événement à la base de données
log_event({x = x, y = y, z = z}, "interact", player:get_player_name(), "mcl_chests:chest")
end
end
-- Fonction pour recharger la base de données des événements
function blockwatch.reload_events_database()
events = {}
blockwatch.load_events_database()
minetest.chat_send_all("[blockwatch] Base de données d'événements rechargée.")
end
-- vérifie que le joueur a ouvert un coffre (protector:chest)
if formname:find("^protector:chest_") then
--minetest.chat_send_all("Le joueur " .. player:get_player_name() .. " a ouvert un coffre l'uid du coffre est : " .. formname .. "")
-- Extraire les coordonnées du nom du formulaire c'est separer par des , comme ca : protector:chest_(-1,0,0)
local x, y, z = formname:match("^protector:chest_%((-?%d+),(-?%d+),(-?%d+)%)")
-- Commande pour recharger la base de données des événements
minetest.register_chatcommand("reload_events", {
privs = {blockwatch_perm=true},
description = S("Reload the events database"),
func = function(name, param)
blockwatch.reload_events_database()
return true, S("[blockwatch] Events database reloaded.")
end,
})
if x and y and z then
-- Convertir les coordonnées en nombres
x, y, z = tonumber(x), tonumber(y), tonumber(z)
--minetest.chat_send_all("Le joueur " .. player:get_player_name() .. " a ouvert un coffre aux coordonnées : (" .. x .. ", " .. y .. ", " .. z .. ")")
-- Ajoute un événement à la base de données
log_event({x = x, y = y, z = z}, "interact", player:get_player_name(), "protector:chest")
end
end
if formname == "default:chest" then
-- vérifie que le joueur a ouvert un coffre
if fields.quit then
-- envoie un message dans le chat pour dire que le joueur a ouvert un coffre
--minetest.chat_send_all("Le joueur " .. player:get_player_name() .. " a ouvert un coffre")
-- ajoute un event dans la base de donnée
log_event(player:get_pos(), "open", player:get_player_name(), "default:chest")
end
end
-- Enregistrez la fonction de chargement de la base de données au démarrage
minetest.register_on_mods_loaded(function()
blockwatch.load_events_database()
end)
-- commande pour rechercher les event en fonction des filtre choisi
-- /search_events <pos> <event_type> <entity> <node_name>
-- l'utilisateur peut se servir de "all" pour ne pas utiliser un filtre
-- exemple : /search_events all all all all
--ou
-- /search_events 0,0,0 all all all qui affichera tout les event a la position 0,0,0
--ou
-- /search_events all place all all qui affichera tout les event de type place
--ou
-- /search_events all all all default:stone qui affichera tout les event avec le nom de bloc default:stone
--ou
-- /search_events all all neo all qui affichera tout les event avec le pseudo neo
--ou
-- /search_events 0,0,0 place neo default:stone qui affichera tout les event a la position 0,0,0 de type place avec le pseudo neo et le nom de bloc default:stone
minetest.register_chatcommand("search_events", {
privs = {blockwatch_perm=true},
description = S("Rechercher des événements basés sur des filtres"),
params = "<pos> <event_type> <entity> <node_name>",
func = function(name, param)
-- Diviser les paramètres en utilisant l'espace comme séparateur
local params = param:split(" ")
-- Initialiser les filtres avec des valeurs par défaut
local pos_filter = params[1] or "all"
local event_type_filter = params[2] or "all"
local entity_filter = params[3] or "all"
local node_name_filter = params[4] or "all"
-- Boucle pour filtrer les événements en fonction des critères
local matching_events = {}
for key, event_list in pairs(events) do
for _, event in ipairs(event_list) do
-- envoie le key dans le chat
minetest.chat_send_all("key :" .. key .. "")
if (pos_filter == "all" or key == pos_filter)
and (event_type_filter == "all" or event.event_type == event_type_filter)
and (entity_filter == "all" or event.entity == entity_filter)
and (node_name_filter == "all" or event.node_name == node_name_filter) then
table.insert(matching_events, { key = key, event = event })
end
end
end
-- Fonction de tri en fonction de l'horodatage (timestamp)
table.sort(matching_events, function(a, b)
return a.event.timestamp < b.event.timestamp
end)
local numero_event = 0
-- Envoyer les événements filtrés au joueur
for _, item in ipairs(matching_events) do
local key = item.key
local event = item.event
numero_event = numero_event + 1
minetest.chat_send_player(name, "pos: " .. key .. " entity: " .. event.entity .. " event_type: " .. event.event_type .. " node_name: " .. event.node_name .. " timestamp: " .. event.timestamp)
end
minetest.chat_send_all("Nombre d'events : " .. numero_event)
return true, S("[blockwatch] Événements correspondants envoyés au joueur ") .. name .. "."
end,
})
@ -652,3 +595,58 @@ minetest.register_craftitem("blockwatch:block_data_checker_backup", {
on_use = check_block_data_item_backup,
})