Remove the warning system

Warnings were a moderator tool layered on top of reports and had no
callers left outside their own command and the player list button. The
legacy module, its config and locale, the exp_scenario command and its
permissions, the discord alert block and the player list button are all
removed. Reporting from the player list no longer depends on whether the
player could give warnings, anyone can report a player who is not immune.
This commit is contained in:
bbassie
2026-09-05 19:22:37 +00:00
parent 810269971b
commit a59b2a8414
21 changed files with 2 additions and 644 deletions
@@ -5,7 +5,6 @@ return {
show_playtime = true,
entity_protection = true,
player_reports = true,
player_warnings = true,
player_bans = true,
player_mutes = true,
player_kicks = true,
@@ -9,7 +9,6 @@ local ExpUtil = require("modules/exp_util")
local Gui = require("modules/exp_gui")
local Roles = require("modules/exp_roles")
local Reports = require("modules.exp_legacy.modules.control.reports") --- @dep modules.control.reports
local Warnings = require("modules.exp_legacy.modules.control.warnings") --- @dep modules.control.warnings
local Jail = require("modules.exp_legacy.modules.control.jail") --- @dep modules.control.jail
local Colors = require("modules/exp_util/include/color")
local format_player_name = ExpUtil.format_player_name_locale
@@ -100,20 +99,6 @@ local function report_player_callback(player, reason)
Reports.report_player(selected_player.name, player.name, reason)
end
--- Gives the action player a warning, requires a reason
-- @element warn_player
local warn_player = new_button("utility/spawn_flag", { "exp-gui_player-list.warn-player" })
:on_click(function(def, player, element)
set_selected_action(player, "exp_scenario.command.create_warning")
end)
local function warn_player_callback(player, reason)
local selected_player, selected_player_color = get_action_player(player)
local by_player_name_color = format_player_name(player)
game.print{ "exp-commands_warnings.create", selected_player_color, by_player_name_color, reason }
Warnings.add_warning(selected_player.name, player.name, reason)
end
--- Jails the action player, requires a reason
-- @element jail_player
local jail_player = new_button("utility/multiplayer_waiting_icon", { "exp-gui_player-list.jail-player" })
@@ -170,18 +155,11 @@ return {
["exp_scenario.command.create_report"] = {
auth = function(player, selected_player)
if player == selected_player then return false end
if not Roles.player_has_permission(player, "exp_scenario.command.create_warning") then
return not Roles.player_has_permission(selected_player, "exp_scenario.bypass.reports")
end
end, -- can report any player that isn't immune and you aren't able to give warnings
return not Roles.player_has_permission(selected_player, "exp_scenario.bypass.reports")
end, -- can report any player that isn't immune
reason_callback = report_player_callback,
report_player,
},
["exp_scenario.command.create_warning"] = {
auth = Roles.player_outranks, -- warn a lower user, replaces report
reason_callback = warn_player_callback,
warn_player,
},
["exp_scenario.command.jail"] = {
auth = Roles.player_outranks,
reason_callback = jail_player_callback,
-38
View File
@@ -1,38 +0,0 @@
--- Config file for the warning system, this is very similar to reports but is for the use of moderators rather than normal users.
-- @config Warnings
return {
--- @type (LocalisedString[] | fun(player: LuaPlayer, by_player_name: string, number_of_warnings: number))[]
actions = { --- @setting actions what actions are taking at number of warnings
-- if a localized string is used then __1__ will by_player_name and __2__ will be the current warning count (auto inserted)
{ "warnings.received", "" },
{ "warnings.received", "" },
{ "warnings.received", { "warnings.pre-kick" } },
function(player, by_player_name, number_of_warnings)
local str = {
"You received a warning from ",
by_player_name,
". You have ",
number_of_warnings,
" warnings. You were kicked for having too many warnings; you may rejoin if you wish.",
}
game.kick_player(player, table.concat(str, "")) -- Does not support locale strings
-- game.kick_player(player, { "warnings.received", by_player_name, number_of_warnings, { "warnings.kick" } })
end,
{ "warnings.received", { "warnings.pre-pre-ban" } },
{ "warnings.received", { "warnings.pre-ban" } },
function(player, by_player_name, number_of_warnings)
local str = {
"You received a warning from ",
by_player_name,
". You have ",
number_of_warnings,
" warnings. You were banned for having too many warnings; visit https://www.explosivegaming.nl to request a ban appeal.",
}
game.kick_player(player, table.concat(str, "")) -- Does not support locale strings
-- game.ban_player(player, { "warnings.received", by_player_name, number_of_warnings, { "warnings.ban", { "links.website" } } })
end,
},
script_warning_cool_down = 30, --- @setting script_warning_cool_down time for a script warning (given by script) to be removed (in minutes)
script_warning_limit = 5, --- @setting script_warning_limit the number of script warnings (given by script) that are allowed before full warnings are given
}
-11
View File
@@ -18,14 +18,3 @@ read-readme=Make sure you have read the information gui (It can be found through
softmod=We run a softmod on our servers. A softmod is a custom scenario that runs on this server, an example is the player list.
redmew=We don't talk about redmew here; they beat us to 1000 members ;-;
lhd=All trains must be LHD! This is a long standing rule on our servers, please respect this.
[warnings]
received=You received a warning from __1__. You have __2__ warnings. __3__
pre-kick=This is your last warning before you are kicked.
kick=You were kicked for having too many warnings; you may rejoin if you wish.
pre-pre-ban=You are close to receiving a ban; successful ban appeals are unlikely.
pre-ban=This your LAST warning before you are BANNED! Successful ban appeals are unlikely.
ban=You were banned for having too many warnings; visit __1__ to request a ban appeal.
script-warning=You are receiving script warnings; if you recive too many you will receive a permanent warning (__1__/__2__)
script-warning-removed=A script warning has expired (__1__/__2__)
script-warning-limit=__1__ has received a permanent warning from the script.
-5
View File
@@ -10,11 +10,6 @@ message-cleared=Your join message has been cleared.
[quickbar]
saved=Your quickbar filters have been saved.
[exp-required]
Warnings=Warnings
Warnings-tooltip=The total number of warnings you have received from staff
Warnings-value-tooltip=The total number of warnings you have received from staff
[exp-settings]
Colour=Colour
Colour-tooltip=Your player colour
-1
View File
@@ -7,7 +7,6 @@ reason-entry=Enter Reason
goto-player=Goto player
bring-player=Bring player
report-player=Report player
warn-player=Warn player
jail-player=Jail player
kick-player=Kick player
ban-player=Ban player
-11
View File
@@ -18,14 +18,3 @@ read-readme=確保你已閱讀相關資訊。按左上 i 圖標可再次查看
softmod=這裹用了自設情境,是一種軟裝模組。
redmew=
lhd=列車必須是左則通行。這是本服務器長久以來的規則。
[warnings]
received=你已被 __1__ 警告了,現在共有 __2__ 個警告。 __3__
pre-kick=這是在被踢離之前的最後警告。
kick=你已因為被警告太多次而被請離,不過你之後還是可以回來的。
pre-pre-ban=按照你的行為,你有可能會被封禁。
pre-ban=這是在被封禁之前的最後警告。
ban=你已因為被警告太多次而被封禁; 可以到 __1__ 申訴.
script-warning=這是系統發出的自動警告 (__1__/__2__)
script-warning-removed=系統發出的自動警告已失效 (__1__/__2__)
script-warning-limit=__1__ 已被系統發出了一則自動警告。
-5
View File
@@ -10,11 +10,6 @@ message-cleared=你的加入信息已清除。
[quickbar]
saved=你的工具列已儲存。
[exp-required]
Warnings=警告
Warnings-tooltip=你所有收到的警告
Warnings-value-tooltip=你所有收到的警告
[exp-settings]
Colour=顏色
Colour-tooltip=你的人物顏色
-1
View File
@@ -7,7 +7,6 @@ reason-entry=輸入原因
goto-player=傳送到用戶
bring-player=傳送用戶到自己
report-player=舉報用戶
warn-player=警告用戶
jail-player=監禁用戶
kick-player=踢除用戶
ban-player=封禁用戶
-11
View File
@@ -18,14 +18,3 @@ read-readme=確保你已閱讀相關資訊。按左上 i 圖標可再次查看
softmod=這裹用了自設情境,是一種軟裝模組。
redmew=
lhd=列車必須是左則通行。這是本服務器長久以來的規則。
[warnings]
received=你已被 __1__ 警告了,現在共有 __2__ 個警告。 __3__
pre-kick=這是在被踢離之前的最後警告。
kick=你已因為被警告太多次而被請離,不過你之後還是可以回來的。
pre-pre-ban=按照你的行為,你有可能會被封禁。
pre-ban=這是在被封禁之前的最後警告。
ban=你已因為被警告太多次而被封禁; 可以到 __1__ 申訴.
script-warning=這是系統發出的自動警告 (__1__/__2__)
script-warning-removed=系統發出的自動警告已失效 (__1__/__2__)
script-warning-limit=__1__ 已被系統發出了一則自動警告。
-5
View File
@@ -10,11 +10,6 @@ message-cleared=你的加入信息已清除。
[quickbar]
saved=你的工具列已儲存。
[exp-required]
Warnings=警告
Warnings-tooltip=你所有收到的警告
Warnings-value-tooltip=你所有收到的警告
[exp-settings]
Colour=顏色
Colour-tooltip=你的人物顏色
-1
View File
@@ -7,7 +7,6 @@ reason-entry=輸入原因
goto-player=傳送到用戶
bring-player=傳送用戶到自己
report-player=舉報用戶
warn-player=警告用戶
jail-player=監禁用戶
kick-player=踢除用戶
ban-player=封禁用戶
@@ -1,331 +0,0 @@
--[[-- Control Module - Warnings
- Adds a way to give and remove warnings to players.
@control Warnings
@alias Warnings
@usage
-- import the module from the control modules
local Warnings = require("modules.exp_legacy.modules.control.warnings") --- @dep modules.control.warnings
-- This will add a warning to the player
Warnings.add_warning('MrBiter', 'Cooldude2606', 'Killed too many biters')
-- This will remove a warning from a player, second name is just who is doing the action
Warnings.remove_warning('MrBiter', 'Cooldude2606')
-- Script warning as similar to normal warning but are designed to have no effect for a short amount of time
-- this is so it can be used for greifer protection without being too agressive
Warnings.add_script_warning('MrBiter', 'Killed too many biters')
-- Both normal and script warnings can also be cleared, this will remove all warnings
Warnings.clear_warnings('MrBiter', 'Cooldude2606')
]]
local Event = require("modules/exp_legacy/utils/event")
local Storage = require("modules/exp_util/storage")
local config = require("modules.exp_legacy.config.warnings")
local valid_player = function(p) return type(p) == "userdata" and p or game.get_player(p) end
--- Stores the quickbar filters for a player
local PlayerData = require("modules.exp_legacy.expcore.player_data") --- @dep expcore.player_data
local PlayerWarnings = PlayerData.Required:combine("Warnings")
PlayerWarnings:set_metadata{
stringify = function(value)
if not value then return "You have no warnings" end
local count = 0
for _ in pairs(value) do count = count + 1 end
return "You have " .. count .. " warnings"
end,
}
local Warnings = {
user_warnings = PlayerWarnings,
user_script_warnings = {},
events = {
--- When a warning is added to a player
-- @event on_warning_added
-- @tparam number player_index the index of the player who recived the warning
-- @tparam string by_player_name the name of the player who gave the warning
-- @tparam string reason the reason that the player was given a warning
-- @tparam number warning_count the new number of warnings that the player has
on_warning_added = script.generate_event_name(),
--- When a warning is removed from a player
-- @event on_warning_removed
-- @tparam number player_index the index of the player who is having the warning removed
-- @tparam string warning_by_name the name of the player who gave the warning
-- @tparam string removed_by_name the name of the player who is removing the warning
-- @tparam number warning_count the new number of warnings that the player has
-- @tparam number batch_count the number of warnings removed in this batch, always one when not a batch
-- @tparam number batch the index of this event in a batch, always one when not a batch
on_warning_removed = script.generate_event_name(),
--- When a warning is added to a player, by the script
-- @event on_script_warning_added
-- @tparam number player_index the index of the player who recived the warning
-- @tparam string reason the reason that the player was given a warning
-- @tparam number warning_count the new number of warnings that the player has
on_script_warning_added = script.generate_event_name(),
--- When a warning is removed from a player, by the script
-- @event on_script_warning_removed
-- @tparam number player_index the index of the player who is having the warning removed
-- @tparam number warning_count the new number of warnings that the player has
on_script_warning_removed = script.generate_event_name(),
},
}
local user_script_warnings = Warnings.user_script_warnings
Storage.register(user_script_warnings, function(tbl)
Warnings.user_script_warnings = tbl
user_script_warnings = tbl
end)
--- Gets an array of warnings that the player has, always returns a list even if empty
-- @tparam LuaPlayer player the player to get the warning for
-- @treturn table an array of all the warnings on this player, contains tick, by_player_name and reason
function Warnings.get_warnings(player)
return PlayerWarnings:get(player.name, {})
end
--- Gets the number of warnings that a player has on them
-- @tparam LuaPlayer player the player to count the warnings for
-- @treturn number the number of warnings that the player has
function Warnings.count_warnings(player)
local warnings = PlayerWarnings:get(player.name, {})
return #warnings
end
--- Adds a warning to a player, when a warning is added a set action is done based on the number of warnings and the config file
-- @tparam LuaPlayer player the player to add a warning to
-- @tparam string by_player_name the name of the player who is doing the action
-- @tparam[opt='Non given.'] string reason the reason that the player is being warned
-- @treturn number the number of warnings that the player has
function Warnings.add_warning(player, by_player_name, reason)
player = valid_player(player)
if not player then return end
if not by_player_name then return end
reason = reason or "None given."
local warning_count --- @type number
PlayerWarnings:update(player.name, function(_, warnings)
local warning = {
by_player_name = by_player_name,
reason = reason,
}
if not warnings then
warning_count = 1
return { warning }
else
table.insert(warnings, warning)
warning_count = #warnings
end
end)
script.raise_event(Warnings.events.on_warning_added, {
name = Warnings.events.on_warning_added,
tick = game.tick,
player_index = player.index,
warning_count = warning_count,
by_player_name = by_player_name,
reason = reason,
})
local action = config.actions[warning_count]
if action then
local _type = type(action)
if _type == "function" then
action(player, by_player_name, warning_count)
elseif _type == "table" then
local current = table.deepcopy(action)
table.insert(current, 2, by_player_name)
table.insert(current, 3, warning_count)
player.print(current)
elseif type(action) == "string" then
player.print(action)
end
end
return warning_count
end
--- Event trigger for removing a waring due to it being looped in clear warnings
-- @tparam LuaPlayer player the player who is having a warning removed
-- @tparam string warning_by_name the name of the player who made the warning
-- @tparam string removed_by_name the name of the player who is doing the action
-- @tparam number warning_count the number of warnings that the player how has
-- @tparam number batch the index of this event in a batch, always one when not a batch
-- @tparam number batch_count the number of reports removed in this batch, always one when not a batch
local function warning_removed_event(player, warning_by_name, removed_by_name, warning_count, batch, batch_count)
script.raise_event(Warnings.events.on_warning_removed, {
name = Warnings.events.on_warning_removed,
tick = game.tick,
player_index = player.index,
warning_count = warning_count,
warning_by_name = warning_by_name,
removed_by_name = removed_by_name,
batch_count = batch_count or 1,
batch = batch or 1,
})
end
--- Removes a warning from a player, always removes the earliest warning, fifo
-- @tparam LuaPlayer player the player to remove a warning from
-- @tparam string by_player_name the name of the player who is doing the action
-- @treturn number the number of warnings that the player has
function Warnings.remove_warning(player, by_player_name)
player = valid_player(player)
if not player then return end
if not by_player_name then return end
local warning, warning_count
PlayerWarnings:update(player.name, function(_, warnings)
if not warnings then return end
warning = table.remove(warnings, 1)
warning_count = #warnings
end)
if not warning then return end
warning_removed_event(player, warning.by_player_name, by_player_name, warning_count)
return warning_count
end
--- Removes all warnings from a player, will trigger remove event for each warning
-- @tparam LuaPlayer player the player to clear the warnings from
-- @tparam string by_player_name the name of the player who is doing the action
-- @treturn boolean true when warnings were cleared succesfully
function Warnings.clear_warnings(player, by_player_name)
player = valid_player(player)
if not player then return end
if not by_player_name then return end
local warnings = PlayerWarnings:get(player)
if not warnings then return end
local warning_count = #warnings
for n, warning in pairs(warnings) do
warning_removed_event(player, warning.by_player_name, by_player_name, warning_count - n, n, warning_count)
end
PlayerWarnings:remove(player)
return true
end
--- Gets an array of all the script warnings that a player has
-- @tparam LuaPlayer player the player to get the script warnings of
-- @treturn table a table of all the script warnings a player has, contains tick and reason
function Warnings.get_script_warnings(player)
return user_script_warnings[player.name] or {}
end
--- Gets the number of script warnings that a player has on them
-- @tparam LuaPlayer player the player to count the script warnings of
-- @treturn number the number of script warnings that the player has
function Warnings.count_script_warnings(player)
local warnings = user_script_warnings[player.name] or {}
return #warnings
end
--- Adds a script warning to a player, this may add a full warning if max script warnings is met
-- @tparam LuaPlayer player the player to add a script warning to
-- @tparam[opt='Non given.'] string reason the reason that the player is being warned
-- @treturn number the number of script warnings that the player has
function Warnings.add_script_warning(player, reason)
player = valid_player(player)
if not player then return end
reason = reason or "Non given."
local warnings = user_script_warnings[player.name]
if not warnings then
warnings = {}
user_script_warnings[player.name] = warnings
end
table.insert(warnings, {
tick = game.tick,
reason = reason,
})
local warning_count = #warnings
script.raise_event(Warnings.events.on_script_warning_added, {
name = Warnings.events.on_script_warning_added,
tick = game.tick,
player_index = player.index,
warning_count = warning_count,
reason = reason,
})
if warning_count > config.script_warning_limit then
Warnings.add_warning(player, "<server>", reason)
end
return warning_count
end
--- Script warning removed event trigger due to it being looped in clear script warnings
-- @tparam LuaPlayer player the player who is having a script warning removed
-- @tparam number warning_count the number of warnings that the player has
local function script_warning_removed_event(player, warning_count)
script.raise_event(Warnings.events.on_script_warning_removed, {
name = Warnings.events.on_script_warning_removed,
tick = game.tick,
player_index = player.index,
warning_count = warning_count,
})
end
--- Removes a script warning from a player
-- @tparam LuaPlayer player the player to remove a script warning from
-- @treturn number the number of script warnings that the player has
function Warnings.remove_script_warning(player)
player = valid_player(player)
if not player then return end
local warnings = user_script_warnings[player.name]
if not warnings then return end
table.remove(warnings, 1)
script_warning_removed_event(player)
return #warnings
end
--- Removes all script warnings from a player, emits event for each warning removed
-- @tparam LuaPlayer player the player to clear the script warnings from
function Warnings.clear_script_warnings(player)
player = valid_player(player)
if not player then return end
local warnings = user_script_warnings[player.name]
if not warnings then return end
local warning_count = #warnings
for n, _ in pairs(warnings) do
script_warning_removed_event(player, warning_count - n)
end
user_script_warnings[player.name] = nil
return true
end
-- script warnings are removed after a certain amount of time to make them even more lienient
local script_warning_cool_down = config.script_warning_cool_down * 3600
Event.on_nth_tick(script_warning_cool_down / 4, function()
local cutoff = game.tick - script_warning_cool_down
for player_name, script_warnings in pairs(user_script_warnings) do
if #script_warnings > 0 then
for _, warning in pairs(script_warnings) do
if warning.tick < cutoff then
Warnings.remove_script_warning(player_name)
end
end
end
end
end)
return Warnings