Fix: Issues 1 to 3 solved

This commit is contained in:
Boot 2025-09-06 09:09:22 +02:00
parent 1a2abd0029
commit ffd956bcfa
5 changed files with 254 additions and 89 deletions

View File

@ -1,42 +1,33 @@
# Changelog Arena PvP Mod
## Deutsch
### [0.1.0] Erste Version
- Spieler-Kisten hinzugefügt: Spieler können Inventar sichern.
- Leiter-Kiste hinzugefügt: Ausrüstung für alle Kämpfer.
- Chatbefehle `/arena_start` und `/arena_end` implementiert.
- Heilung durch Essen während des Kampfes blockiert.
### [0.2.0] Inventar-Speicher fix
- Fehler behoben: Absturz beim Speichern des Inventars (ItemStacks → Strings).
- Sicheres Speichern und Wiederherstellen von Spielerinventaren.
### [0.3.0] Arena-Schalter
- Neuer „Arena-Schalter“ (`arena_pvp:arena_switch`) hinzugefügt.
- Turnierleiter kann Kämpfe per Klick starten oder beenden.
- Kein Tippen der Chatbefehle mehr nötig.
- Verwendet bestehende Textur (`default_stone.png`) → keine zusätzlichen Ressourcen.
### [0.4.0] Mehrsprachigkeit (i18n)
- Unterstützung für Übersetzungen mit `minetest.get_translator` eingebaut.
- Alle Texte ins Übersetzungssystem integriert.
- Vorbereitete Sprachdateien (`de.po`, `en.po`, `es.po`, `ru.po`).
- Template-Datei `arena_pvp.pot` hinzugefügt.
---
## English
### [0.1.0] First version
- Added Player Chests: players can save inventory.
- Added Leader Chest: equipment chest for all fighters.
- Implemented chat commands `/arena_start` and `/arena_end`.
- Disabled healing by food during fights.
### [0.7.0] Stability and security
- Checks if a player is already using an Arena Crate before placing a new one.
- Added logging (player actions and arena events are written to the server log).
- Warning for players when an Arena crate is already occupied.
- Persistent Storage: Player and crate states are backed up in the `mod_storage` and restored on server restart.
- Inventory interactions blocked during Arena battles (incl. bags).
- `register_on_player_receive_fields` now returns `true` if the event has been processed.
### [0.2.0] Inventory save fix
- Fixed crash when saving inventory (ItemStacks → strings).
- Safe storage and restore of player inventories.
### [0.6.0] Inventory interactions blocked
- During Arena battles, inventory actions are not possible (neither from Main Inventory nor from Bags).
- Prevents players from moving, removing, or adding items during combat.
### [0.5.0] Persistence & Permissions System
- More robust inventory handling: safe backup before clearing.
- Player and arena data are now persistent.
- Support for multiple arenas simultaneously.
- Arena switch now checks permissions (configurable privilege).
- New configuration system: settings.txt in mod folder defines required priv (default: server).
- Healing is blocked but food is no longer consumed.
- Protection against multiple participation in the same fight.
### [0.4.0] Internationalization (i18n)
- Added support for translations via `minetest.get_translator`.
- All texts integrated into the translation system.
- Prepared translation files (`de.po`, `en.po`, `es.po`, `ru.po`).
- Added template file `arena_pvp.pot`.
### [0.3.0] Arena Switch
- Added new „Arena Switch“ (`arena_pvp:arena_switch`).
@ -44,8 +35,60 @@
- No more typing chat commands required.
- Reuses existing texture (`default_stone.png`) → no new assets needed.
### [0.4.0] Internationalization (i18n)
- Added support for translations via `minetest.get_translator`.
- All texts integrated into the translation system.
- Prepared translation files (`de.po`, `en.po`, `es.po`, `ru.po`).
- Added template file `arena_pvp.pot`.
### [0.2.0] Inventory save fix
- Fixed crash when saving inventory (ItemStacks → strings).
- Safe storage and restore of player inventories.
### [0.1.0] First version
- Added Player Chests: players can save inventory.
- Added Leader Chest: equipment chest for all fighters.
- Implemented chat commands `/arena_start` and `/arena_end`.
- Disabled healing by food during fights.
---
## Deutsch
### [0.7.0] Stabilität und Sicherheit
- Prüft, ob ein Spieler bereits eine Arena-Kiste benutzt, bevor eine neue gesetzt wird.
- Logging ergänzt (Spieleraktionen und Arena-Events werden ins Server-Log geschrieben).
- Warnung für Spieler, wenn eine Arena-Kiste schon belegt ist.
- Persistente Speicherung: Spieler- und Kistenzustände werden im `mod_storage` gesichert und beim Serverneustart wiederhergestellt.
- Inventarinteraktionen während Arena-Kämpfen blockiert (inkl. Bags).
- `register_on_player_receive_fields` gibt jetzt `true` zurück, wenn das Event verarbeitet wurde.
### [0.6.0] Inventarinteraktionen blockiert
- Während Arena-Kämpfen sind keine Inventaraktionen möglich (weder aus Hauptinventar noch aus Bags).
- Verhindert, dass Spieler während des Kampfes Items verschieben, entnehmen oder hinzufügen.
### [0.5.0] Persistenz & Rechte-System
- Inventarverwaltung robuster: Sicheres Backup vor dem Leeren.
- Spieler- und Arenadaten werden jetzt persistent gespeichert.
- Unterstützung für mehrere Arenen gleichzeitig.
- Arena-Schalter prüft nun Berechtigungen (einstellbares Privileg).
- Neues Konfigurationssystem: Datei settings.txt im Modverzeichnis bestimmt benötigtes Priv (Standard: server).
- Heilung blockiert, Nahrung bleibt erhalten (kein Item-Verlust mehr).
- Schutz vor mehrfacher Teilnahme am selben Kampf.
### [0.4.0] Mehrsprachigkeit (i18n)
- Unterstützung für Übersetzungen mit `minetest.get_translator` eingebaut.
- Alle Texte ins Übersetzungssystem integriert.
- Vorbereitete Sprachdateien (`de.po`, `en.po`, `es.po`, `ru.po`).
- Template-Datei `arena_pvp.pot` hinzugefügt.
### [0.3.0] Arena-Schalter
- Neuer „Arena-Schalter“ (`arena_pvp:arena_switch`) hinzugefügt.
- Turnierleiter kann Kämpfe per Klick starten oder beenden.
- Kein Tippen der Chatbefehle mehr nötig.
- Verwendet bestehende Textur (`default_stone.png`) → keine zusätzlichen Ressourcen.
### [0.2.0] Inventar-Speicher fix
- Fehler behoben: Absturz beim Speichern des Inventars (ItemStacks → Strings).
- Sicheres Speichern und Wiederherstellen von Spielerinventaren.
### [0.1.0] Erste Version
- Spieler-Kisten hinzugefügt: Spieler können Inventar sichern.
- Leiter-Kiste hinzugefügt: Ausrüstung für alle Kämpfer.
- Chatbefehle `/arena_start` und `/arena_end` implementiert.
- Heilung durch Essen während des Kampfes blockiert.

View File

@ -1,42 +1,37 @@
# Arena PvP Mod (Minetest / Luanti)
## Deutsch
Diese Mod fügt eine **Arena für PvP-Kämpfe** hinzu.
Sie ermöglicht faire 1-gegen-1 Kämpfe (später erweiterbar) mit folgenden Regeln:
- **Spieler-Kiste**: Spieler sichern ihr Inventar und erhalten für den Kampf leere Slots.
- **Leiter-Kiste**: Der Turnierleiter legt Waffen und Rüstungen hinein. Alle Kämpfer erhalten diese Ausrüstung beim Start.
- **Arena-Schalter**: Turnierleiter startet oder beendet den Kampf bequem über einen Klick (kein Chatbefehl nötig).
- **Heilung deaktiviert**: Während des Kampfes können Spieler keine Nahrung zur Heilung verwenden.
- **Nach dem Kampf**: Jeder Spieler bekommt automatisch sein ursprüngliches Inventar zurück.
### Verwendung
1. Platziere **eine Leiter-Kiste** (`arena_pvp:chest_leader`).
2. Platziere für jeden Spieler **eine Spieler-Kiste** (`arena_pvp:chest_player`).
3. Platziere den **Arena-Schalter** (`arena_pvp:arena_switch`).
4. Jeder Spieler klickt auf seine Spieler-Kiste → Inventar wird gespeichert und geleert.
5. Der Turnierleiter legt die gewünschten Waffen/Rüstungen in die Leiter-Kiste.
6. Der Turnierleiter klickt auf den Arena-Schalter → wählt „⚔ Kampf starten“.
7. Nach dem Kampf klickt der Turnierleiter auf den Arena-Schalter → „🏆 Kampf beenden“.
## Table of Contents
- [English](#english)
- [Features](#features)
- [Usage](#usage)
- [Settings](#settings)
- [Notes](#notes)
- [Deutsch](#deutsch)
- [Funktionen](#funktionen)
- [Verwendung](#verwendung)
- [Einstellungen](#einstellungen)
- [Hinweise](#hinweise)
- [License](#license)
- [Credits](#credits)
---
## English
This mod adds a **PvP arena system** for fair 1v1 fights (later expandable).
It enforces equal equipment and prevents mid-fight healing.
This mod adds a **PvP arena system** for fair 1v1 fights (expandable later).
It enforces equal equipment, blocks inventory access, and prevents mid-fight healing.
Features:
### Features
- **Player Chest**: Players save their inventory and start with empty slots.
- **Leader Chest**: The referee puts weapons and armor here. All fighters receive this gear at the start.
- **Arena Switch**: Referee can start/end fights with a simple click (no chat commands required).
- **Healing Disabled**: Eating food to heal is blocked during fights.
- **After Fight**: Each player automatically gets their original inventory back.
- **Inventory Locked**: Players cannot move, take or add items (including *bags* or expanded slots) during fights.
- **After Fight**: Each player automatically gets their original inventory back.
- **Persistence**: Player and chest states are saved via `mod_storage` and survive server restarts.
- **Configurable Privilege**: Required privilege to start/end fights can be set in `settings.txt`.
### Usage
1. Place **one Leader Chest** (`arena_pvp:chest_leader`).
2. Place **one Player Chest** (`arena_pvp:chest_player`) for each fighter.
3. Place the **Arena Switch** (`arena_pvp:arena_switch`).
@ -44,3 +39,57 @@ Features:
5. Referee fills the Leader Chest with weapons/armor.
6. Referee clicks the Arena Switch → choose „⚔ Start Fight“.
7. After the fight, referee clicks the Arena Switch → „🏆 End Fight“.
### Settings
- `arena_pvp/settings.txt` → contains the privilege needed to control fights.
- Default: `server`
- Example: change to `arena_admin` if you have a custom privilege.
### Notes
- Safe against server crashes (inventory and chest states are restored).
- Blocks bag usage during fights.
- Supports translations (German, English, Spanish, Russian).
---
## Deutsch
Diese Mod fügt eine **Arena für PvP-Kämpfe** hinzu.
Sie ermöglicht faire 1-gegen-1 Kämpfe (später erweiterbar) und sorgt für gleiche Ausrüstung, blockiert Inventarinteraktionen und verhindert Heilung.
### Funktionen
- **Spieler-Kiste**: Spieler sichern ihr Inventar und starten mit leeren Slots.
- **Leiter-Kiste**: Der Turnierleiter legt Waffen und Rüstungen hinein. Alle Kämpfer erhalten diese Ausrüstung beim Start.
- **Arena-Schalter**: Turnierleiter startet oder beendet den Kampf bequem über einen Klick (kein Chatbefehl nötig).
- **Heilung deaktiviert**: Spieler können während des Kampfes keine Nahrung nutzen.
- **Inventar gesperrt**: Keine Aktionen mit Items möglich (inkl. *Bags* und erweiterte Slots).
- **Nach dem Kampf**: Spieler erhalten automatisch ihr ursprüngliches Inventar zurück.
- **Persistenz**: Spieler- und Kistenzustände werden mit `mod_storage` gespeichert und bei Serverneustarts wiederhergestellt.
- **Konfigurierbares Privileg**: In `settings.txt` kann das nötige Privileg eingestellt werden.
### Verwendung
1. Platziere **eine Leiter-Kiste** (`arena_pvp:chest_leader`).
2. Platziere für jeden Spieler **eine Spieler-Kiste** (`arena_pvp:chest_player`).
3. Platziere den **Arena-Schalter** (`arena_pvp:arena_switch`).
4. Jeder Spieler klickt auf seine Spieler-Kiste → Inventar wird gespeichert und geleert.
5. Der Turnierleiter legt die gewünschte Ausrüstung in die Leiter-Kiste.
6. Der Turnierleiter klickt auf den Arena-Schalter → „⚔ Kampf starten“.
7. Nach dem Kampf klickt der Turnierleiter auf den Arena-Schalter → „🏆 Kampf beenden“.
### Einstellungen
- Datei `arena_pvp/settings.txt`: enthält das Privileg, das zum Starten/Beenden benötigt wird.
- Standard: `server`
- Beispiel: `arena_admin` für ein eigenes Privileg.
### Hinweise
- Sicher gegenüber Server-Abstürzen (Inventar/Kisten werden wiederhergestellt).
- Bags können nicht im Kampf verwendet werden.
- Übersetzungen vorbereitet (Deutsch, Englisch, Spanisch, Russisch).
---
## License
This project is licensed under the [MIT License](./LICENSE).
## Credits
- **ChatGPT** (OpenAI).

112
init.lua
View File

@ -1,10 +1,43 @@
local S = minetest.get_translator("arena_pvp")
local arena_players = {}
local arena_chests = {}
local leader_chest_pos = nil
local mod_storage = minetest.get_mod_storage()
local modpath = minetest.get_modpath("arena_pvp")
local settings_path = modpath .. "/settings.txt"
-- Hilfsfunktionen zum sicheren Speichern von Inventar
-- Privileg aus settings.txt lesen (oder erstellen mit Standardwert "server")
local function load_required_priv()
local file = io.open(settings_path, "r")
if file then
local priv = file:read("*l")
file:close()
if priv and priv ~= "" then
return priv
end
end
local f = io.open(settings_path, "w")
if f then
f:write("server\n")
f:close()
end
return "server"
end
local required_priv = load_required_priv()
local arena_players = minetest.deserialize(mod_storage:get_string("arena_players")) or {}
local arena_chests = minetest.deserialize(mod_storage:get_string("arena_chests")) or {}
local leader_chests = minetest.deserialize(mod_storage:get_string("leader_chests")) or {}
-- Speichern beim Shutdown
local function persist_data()
mod_storage:set_string("arena_players", minetest.serialize(arena_players))
mod_storage:set_string("arena_chests", minetest.serialize(arena_chests))
mod_storage:set_string("leader_chests", minetest.serialize(leader_chests))
end
minetest.register_on_shutdown(persist_data)
-- Hilfsfunktionen Inventar sichern/laden
local function save_inventory(invlist)
local data = {}
for i, stack in ipairs(invlist) do
@ -24,7 +57,7 @@ local function load_inventory(serialized)
return invlist
end
-- Arena-Kiste für Spieler
-- Spieler-Kiste
minetest.register_node("arena_pvp:chest_player", {
description = S("Arena-Spieler-Kiste"),
tiles = {"default_chest_top.png", "default_chest_top.png",
@ -33,16 +66,27 @@ minetest.register_node("arena_pvp:chest_player", {
groups = {choppy=2, oddly_breakable_by_hand=2},
on_rightclick = function(pos, node, clicker)
local name = clicker:get_player_name()
if arena_chests[name] then
minetest.chat_send_player(name, S("Du hast bereits eine Arena-Kiste benutzt!"))
return
end
local inv = clicker:get_inventory()
local backup = inv:get_list("main")
local meta = minetest.get_meta(pos)
meta:set_string("owner", name)
meta:set_string("backup", save_inventory(backup))
inv:set_list("main", {}) -- Inventar leeren
if not meta:get_string("backup") or meta:get_string("backup") == "" then
minetest.chat_send_player(name, S("Fehler beim Sichern des Inventars!"))
return
end
inv:set_list("main", {})
arena_chests[name] = pos
persist_data()
minetest.chat_send_player(name, S("Dein Inventar wurde gesichert!"))
minetest.log("action", "[arena_pvp] Spieler " .. name .. " hat seine Arena-Kiste gesetzt.")
end,
})
@ -56,8 +100,10 @@ minetest.register_node("arena_pvp:chest_leader", {
on_construct = function(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
inv:set_size("main", 16) -- Platz für Ausrüstung
leader_chest_pos = pos
inv:set_size("main", 16)
leader_chests[minetest.pos_to_string(pos)] = pos
persist_data()
minetest.log("action", "[arena_pvp] Leiter-Kiste platziert bei " .. minetest.pos_to_string(pos))
end,
on_rightclick = function(pos, node, clicker)
local meta = minetest.get_meta(pos)
@ -69,35 +115,35 @@ minetest.register_node("arena_pvp:chest_leader", {
end,
})
-- Kampf starten (Chatbefehl)
-- Arena Start
minetest.register_chatcommand("arena_start", {
privs = {server = true},
privs = {[required_priv] = true},
func = function(name)
if not leader_chest_pos then return false, S("Keine Leiter-Kiste gefunden!") end
local meta = minetest.get_meta(leader_chest_pos)
local leader_inv = meta:get_inventory():get_list("main")
local count = 0
for pname, pos in pairs(arena_chests) do
local player = minetest.get_player_by_name(pname)
if player then
local meta = minetest.get_meta(next(leader_chests))
local leader_inv = meta:get_inventory():get_list("main")
local inv = player:get_inventory()
inv:set_list("main", {}) -- leeren
inv:set_list("main", {})
for _, stack in ipairs(leader_inv) do
inv:add_item("main", stack)
end
arena_players[pname] = true
minetest.chat_send_player(pname, "" .. S("Der Kampf beginnt!"))
minetest.log("action", "[arena_pvp] Kampf gestartet für Spieler " .. pname)
count = count + 1
end
end
persist_data()
return true, S("Arena-Kampf gestartet mit @1 Spielern.", count)
end,
})
-- Kampf beenden (Chatbefehl)
-- Arena End
minetest.register_chatcommand("arena_end", {
privs = {server = true},
privs = {[required_priv] = true},
func = function(name)
local count = 0
for pname, pos in pairs(arena_chests) do
@ -110,28 +156,34 @@ minetest.register_chatcommand("arena_end", {
end
arena_players[pname] = nil
minetest.chat_send_player(pname, "🏆 " .. S("Der Kampf ist beendet. Dein Inventar wurde wiederhergestellt."))
minetest.log("action", "[arena_pvp] Kampf beendet für Spieler " .. pname)
count = count + 1
end
end
persist_data()
return true, S("Arena-Kampf beendet, @1 Spieler Inventare zurückgegeben.", count)
end,
})
-- Heilung blockieren (kein Essen während Arena)
-- Heilung blockieren
minetest.register_on_item_eat(function(_, _, itemstack, user)
if user and arena_players[user:get_player_name()] then
minetest.chat_send_player(user:get_player_name(), "" .. S("Heilung ist in der Arena deaktiviert!"))
return nil
return itemstack -- Nahrung bleibt erhalten
end
end)
-- Arena-Schalter (verwendet einfach die Steintextur, keine neuen Dateien nötig)
-- Arena-Schalter
minetest.register_node("arena_pvp:arena_switch", {
description = S("Arena-Schalter"),
tiles = {"default_stone.png"},
groups = {cracky=3, oddly_breakable_by_hand=2},
on_rightclick = function(pos, node, clicker)
local name = clicker:get_player_name()
if not minetest.check_player_privs(name, {[required_priv] = true}) then
minetest.chat_send_player(name, S("Du hast keine Berechtigung, Kämpfe zu steuern."))
return
end
minetest.show_formspec(name, "arena_pvp:switch",
"size[4,3]" ..
"button[0.5,0.5;3,1;arena_start;" .. S("⚔ Kampf starten") .. "]" ..
@ -139,14 +191,30 @@ minetest.register_node("arena_pvp:arena_switch", {
end,
})
-- Auswertung der Buttons im Schalter
-- Schalter-Buttons
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname == "arena_pvp:switch" then
local name = player:get_player_name()
if not minetest.check_player_privs(name, {[required_priv] = true}) then
minetest.chat_send_player(name, S("Du hast keine Berechtigung, Kämpfe zu steuern."))
return true
end
if fields.arena_start then
minetest.chatcommands["arena_start"].func(name)
return true
elseif fields.arena_end then
minetest.chatcommands["arena_end"].func(name)
return true
end
return true
end
end)
-- Inventarinteraktionen blockieren für Arena-Spieler
minetest.register_allow_player_inventory_action(function(player, action, inventory, info)
local pname = player:get_player_name()
if arena_players[pname] then
return 0 -- blockieren
end
return nil
end)

View File

@ -1,3 +1,7 @@
name = arena_pvp
description = 1vs1 Arena PvP mit Turnierleiter
depends = default
name = arena_pvp
description = Arena PvP system with leader chests, player chests and combat control.
depends = default
optional_depends = intllib
author = Boot
title = Arena PvP
version = 0.7.0

1
settings.txt Normal file
View File

@ -0,0 +1 @@
server