diff --git a/[admin]/admin2/admin_definitions.lua b/[admin]/admin2/admin_definitions.lua
index 6d84fcbe1..9e7951eb5 100644
--- a/[admin]/admin2/admin_definitions.lua
+++ b/[admin]/admin2/admin_definitions.lua
@@ -37,7 +37,7 @@ enum(
"EVENT_RESOURCE",
"EVENT_SERVER",
"EVENT_MESSAGE",
- "EVENT_BANS",
+ "EVENT_BAN",
"EVENT_NETWORK",
"EVENT_PROXY",
"EVENT_ADMIN_CHAT",
@@ -62,6 +62,7 @@ enum(
"SYNC_RESOURCE",
"SYNC_ADMINS",
"SYNC_SERVER",
+ "SYNC_BAN",
"SYNC_BANS",
"SYNC_MESSAGES"
},
diff --git a/[admin]/admin2/client/main/admin_bans.lua b/[admin]/admin2/client/main/admin_bans.lua
index b4417eb4b..8852c44be 100644
--- a/[admin]/admin2/client/main/admin_bans.lua
+++ b/[admin]/admin2/client/main/admin_bans.lua
@@ -21,12 +21,11 @@ function aBansTab.Create(tab)
guiGridListAddColumn(aBansTab.BansList, "Name", 0.22)
guiGridListAddColumn(aBansTab.BansList, "IP", 0.25)
guiGridListAddColumn(aBansTab.BansList, "Serial", 0.25)
- guiGridListAddColumn(aBansTab.BansList, "Username", 0.25)
- guiGridListAddColumn(aBansTab.BansList, "Date", 0.17)
+ guiGridListAddColumn(aBansTab.BansList, "Expires", 0.17)
guiGridListAddColumn(aBansTab.BansList, "Banned by", 0.22)
- guiGridListAddColumn(aBansTab.BansList, "Temporary", 0.22)
aBansTab.Details = guiCreateButton(0.82, 0.07, 0.17, 0.04, "Details", true, aBansTab.Tab)
- aBansTab.Unban = guiCreateButton(0.82, 0.12, 0.17, 0.04, "Unban", true, aBansTab.Tab, "unban")
+ aBansTab.Ban = guiCreateButton(0.82, 0.12, 0.17, 0.04, "Add ban", true, aBansTab.Tab, "ban")
+ aBansTab.Unban = guiCreateButton(0.82, 0.17, 0.17, 0.04, "Unban", true, aBansTab.Tab, "unban")
aBansTab.BansRefresh = guiCreateButton(0.82, 0.94, 0.17, 0.04, "Refresh", true, aBansTab.Tab, "listbans")
addEventHandler("onClientGUIChanged", aBansTab.BansListSearch, aBansTab.onBansListSearch)
@@ -41,26 +40,21 @@ function aBansTab.onClientClick(button)
if (button == "left") then
if (source == aBansTab.Details) then
if (guiGridListGetSelectedItem(aBansTab.BansList) == -1) then
- messageBox("No ban row selected!", MB_ERROR, MB_OK)
+ messageBox("No ban selected!", MB_ERROR, MB_OK)
else
- local ip = guiGridListGetItemText(aBansTab.BansList, guiGridListGetSelectedItem(aBansTab.BansList), 2)
- aBanDetails(ip)
+ local banID =
+ guiGridListGetItemData(aBansTab.BansList, guiGridListGetSelectedItem(aBansTab.BansList), 1)
+ aBanDetails.Show(banID, false)
end
+ elseif source == aBansTab.Ban then
+ aBan.Show()
elseif (source == aBansTab.Unban) then
if (guiGridListGetSelectedItem(aBansTab.BansList) == -1) then
- messageBox("No ban row selected!", MB_ERROR, MB_OK)
+ messageBox("No ban selected!", MB_ERROR, MB_OK)
else
- local selected =
- guiGridListGetItemText(aBansTab.BansList, guiGridListGetSelectedItem(aBansTab.BansList), 2)
- if (aBans["Serial"][selected]) then
- if (messageBox("Unban Serial " .. selected .. "?", MB_QUESTION, MB_YESNO ) == true) then
- triggerServerEvent ( "aBans", localPlayer, "unbanserial", selected )
- end
- else
- if (messageBox("Unban IP " .. selected .. "?", MB_QUESTION, MB_YESNO) == true) then
- triggerServerEvent ( "aBans", localPlayer, "unbanip", selected )
- end
- end
+ local banID =
+ guiGridListGetItemData(aBansTab.BansList, guiGridListGetSelectedItem(aBansTab.BansList), 1)
+ aBanDetails.Show(banID, true)
end
elseif (source == aBansTab.BansRefresh) then
guiGridListClear(aBansTab.BansList)
@@ -80,7 +74,6 @@ function aBansTab.onBansListSearch()
((ban.nick and string.find(string.upper(ban.nick), text)) or
(ban.ip and string.find(string.upper(ban.ip), text)) or
(ban.serial and string.find(string.upper(ban.serial), text)) or
- (ban.username and string.find(string.upper(ban.username), text)) or
(ban.banner and string.find(string.upper(ban.banner), text)))
then
aBansTab.AddRow(id, ban)
@@ -117,29 +110,20 @@ function aBansTab.AddRow(id, data)
guiGridListSetItemText(list, row, 1, data.nick or "Unknown", false, false)
guiGridListSetItemText(list, row, 2, data.ip or "", false, false)
guiGridListSetItemText(list, row, 3, data.serial or "", false, false)
- guiGridListSetItemText(list, row, 4, data.username or "", false, false)
- if (data.time) then
- local time = getRealTime(data.time)
- guiGridListSetItemText(
- list,
- row,
- 5,
- time.monthday .. " " .. getMonthName(time.month) .. " " .. (1900 + time.year),
- false,
- false
- )
+ if (data.unban) then
+ guiGridListSetItemText(list, row, 4, formatDate("m/d/y h:m", nil, data.unban), false, false)
else
- guiGridListSetItemText(list, row, 5, "", false, false)
+ guiGridListSetItemText(list, row, 4, "Never", false, false)
end
- guiGridListSetItemText(list, row, 6, data.banner or "", false, false)
- guiGridListSetItemText(list, row, 7, iif(data.unban, "Yes", "No"), false, false)
+ guiGridListSetItemText(list, row, 5, data.banner or "", false, false)
guiGridListSetItemData(list, row, 1, id)
end
function aBansTab.DeleteRow(id)
local list = aBansTab.BansList
- for i = 1, guiGridListGetRowCount(list) do
+ -- GridList row ids start at zero, not one
+ for i = 0, guiGridListGetRowCount(list) do
local data = guiGridListGetItemData(list, i, 1)
if (data == id) then
guiGridListRemoveRow(list, i)
diff --git a/[admin]/admin2/client/main/admin_players.lua b/[admin]/admin2/client/main/admin_players.lua
index 2127e0700..3aeb0afe0 100644
--- a/[admin]/admin2/client/main/admin_players.lua
+++ b/[admin]/admin2/client/main/admin_players.lua
@@ -168,10 +168,7 @@ function aPlayersTab.onClientClick(button)
triggerServerEvent("aPlayer", localPlayer, player, "kick", reason)
end
elseif (source == aPlayersTab.Ban) then
- local reason = inputBox("Ban player " .. name, "Enter the ban reason")
- if (reason) then
- triggerServerEvent("aPlayer", localPlayer, player, "ban", reason)
- end
+ aBan.Show(player)
elseif (source == aPlayersTab.Slap) then
triggerServerEvent("aPlayer", localPlayer, player, "slap",
guiComboBoxGetItemText(aPlayersTab.SlapOptions, guiComboBoxGetSelected(aPlayersTab.SlapOptions))
diff --git a/[admin]/admin2/client/widgets/admin_ban.lua b/[admin]/admin2/client/widgets/admin_ban.lua
index 4e726c6ba..cfee8674b 100644
--- a/[admin]/admin2/client/widgets/admin_ban.lua
+++ b/[admin]/admin2/client/widgets/admin_ban.lua
@@ -7,90 +7,271 @@
* Original File by lil_Toady
*
**************************************]]
-aBanForm = nil
-
-function aBanDetails(ip)
- if (aBanForm == nil) then
- local x, y = guiGetScreenSize()
- aBanForm = guiCreateWindow(x / 2 - 130, y / 2 - 150, 260, 300, "Ban Details", false)
- aBanIP = guiCreateLabel(0.03, 0.10, 0.80, 0.09, "", true, aBanForm)
- aBanNick = guiCreateLabel(0.03, 0.20, 0.80, 0.09, "", true, aBanForm)
- aBanDate = guiCreateLabel(0.03, 0.30, 0.80, 0.09, "", true, aBanForm)
- aBanTime = guiCreateLabel(0.03, 0.40, 0.80, 0.09, "", true, aBanForm)
- aBanBanner = guiCreateLabel(0.03, 0.50, 0.80, 0.09, "", true, aBanForm)
- aBanClose = guiCreateButton(0.80, 0.88, 0.17, 0.08, "Close", true, aBanForm)
-
- guiSetVisible(aBanForm, false)
- addEventHandler("onClientGUIClick", aBanForm, aClientBanClick)
- --Register With Admin Form
- aRegister("BanDetails", aBanForm, aBanDetails, aBanDetailsClose)
- end
- if (aBans["IP"][ip]) then
- guiSetText(aBanIP, "IP: " .. ip)
- guiSetText(aBanNick, "Nickname: " .. iif(aBans["IP"][ip]["nick"], aBans["IP"][ip]["nick"], "Unknown"))
- guiSetText(aBanDate, "Date: " .. iif(aBans["IP"][ip]["date"], aBans["IP"][ip]["date"], "Unknown"))
- guiSetText(aBanTime, "Time: " .. iif(aBans["IP"][ip]["time"], aBans["IP"][ip]["time"], "Unknown"))
- guiSetText(aBanBanner, "Bant by: " .. iif(aBans["IP"][ip]["banner"], aBans["IP"][ip]["banner"], "Unknown"))
- if (aBanReason) then
- destroyElement(aBanReason)
+aBan = {
+ Form = nil,
+ defaultDurations = {
+ {"1 second", 1},
+ {"1 hour", 60 * 60},
+ {"1 day", 60 * 60 * 24},
+ {"1 week", 60 * 60 * 24 * 7},
+ {"Permanent", 0}, -- HARDCODED AS SECOND LAST IN THIS TABLE, DO NOT MOVE
+ {"Custom", 0} -- HARDCODED AS LAST IN THIS TABLE, DO NOT MOVE
+ },
+ playerName = nil
+}
+
+function aBan.Show(player)
+ if not aBan.Form then
+ aBan.Create()
+ end
+
+ -- If a player was selected, auto-fill the form with the player's info
+ if player then
+ aBan.playerName = getPlayerName(player)
+ guiSetText(aBan.Form, "Ban player "..aBan.playerName)
+ guiSetText(aBan.SerialEditBox, getSensitiveText(aPlayers[player].serial))
+ guiSetEnabled(aBan.SerialEditBox, false)
+ guiSetText(aBan.IPEditBox, getSensitiveText(aPlayers[player].ip))
+ guiSetEnabled(aBan.IPEditBox, false)
+ end
+
+ addEventHandler("onClientGUIClick", aBan.Form, aBan.onClick)
+ addEventHandler("onClientGUIFocus", aBan.Form, aBan.onFocus)
+ addEventHandler("onClientGUIBlur", aBan.Form, aBan.onBlur)
+ guiSetVisible(aBan.Form, true)
+ guiBringToFront(aBan.Form)
+end
+
+function aBan.Close(destroy)
+ if destroy then
+ destroyElement(aBan.Form)
+ aBan.Form = nil
+ else
+ removeEventHandler("onClientGUIClick", aBan.Form, aBan.onClick)
+ guiSetVisible(aBan.Form, false)
+ aBan.Reset()
+ end
+ aBan.playerName = nil
+end
+
+function aBan.Create()
+ local sx, sy = guiGetScreenSize()
+ aBan.Form = guiCreateWindow(sx / 2 - 175, sy / 2 - 170, 350, 340, "Add ban", false)
+ aBan.ReasonLabel = guiCreateLabel(25, 40, 300, 20, "Ban reason (required):", false, aBan.Form)
+ aBan.ReasonEditBox = guiCreateEdit(25, 70, 300, 30, "Enter ban reason...", false, aBan.Form)
+ aBan.ReasonEditBoxRecievedInput = false
+ aBan.DurationLabel = guiCreateLabel(25, 110, 300, 20, "Ban duration (required):", false, aBan.Form)
+ aBan.DurationComboBox = guiCreateComboBox(25, 145, 150, 100, "Select ban duration...", false, aBan.Form)
+ for i=1, #aBan.defaultDurations do
+ guiComboBoxAddItem(aBan.DurationComboBox, aBan.defaultDurations[i][1])
+ end
+ aBan.DurationEditBox = guiCreateEdit(175, 140, 150, 30, "Duration (seconds)...", false, aBan.Form)
+ guiSetEnabled(aBan.DurationEditBox, false)
+ aBan.DurationEditBoxRecievedInput = false
+ aBan.IdentifiersLabel = guiCreateLabel(25, 180, 300, 20, "Select identifiers to use (select at least 1):", false, aBan.Form)
+ aBan.IPCheckBox = guiCreateCheckBox(45, 210, 125, 30, "Use IP address", true, false, aBan.Form)
+ aBan.IPEditBox = guiCreateEdit(175, 210, 150, 30, "Enter IP address...", false, aBan.Form)
+ aBan.IPEditBoxRecievedInput = false
+ aBan.SerialCheckBox = guiCreateCheckBox(45, 250, 125, 30, "Use MTA serial", true, false, aBan.Form)
+ aBan.SerialEditBox = guiCreateEdit(175, 250, 150, 30, "Enter MTA serial...", false, aBan.Form)
+ guiEditSetMaxLength(aBan.SerialEditBox, 32)
+ aBan.SerialEditBoxRecievedInput = false
+ aBan.SubmitButton = guiCreateButton(105, 290, 60, 40, "Submit", false, aBan.Form)
+ aBan.CancelButton = guiCreateButton(185, 290, 60, 40, "Cancel", false, aBan.Form)
+ aRegister("Ban", aBan.Form, aBan.Show, aBan.Close)
+ guiSetVisible(aBan.Form, false)
+end
+
+function aBan.Reset()
+ guiSetText(aBan.Form, "Add ban")
+ guiSetText(aBan.ReasonEditBox, "Enter ban reason...")
+ aBan.ReasonEditBoxRecievedInput = false
+ guiComboBoxSetSelected(aBan.DurationComboBox, -1)
+ guiSetText(aBan.DurationEditBox, "Duration (seconds)...")
+ guiSetEnabled(aBan.DurationEditBox, false)
+ aBan.DurationEditBoxRecievedInput = false
+ guiCheckBoxSetSelected(aBan.IPCheckBox, true)
+ guiSetText(aBan.IPEditBox, "Enter IP address")
+ guiSetEnabled(aBan.IPEditBox, true)
+ aBan.IPEditBoxRecievedInput = false
+ guiCheckBoxSetSelected(aBan.SerialCheckBox, true)
+ guiSetText(aBan.SerialEditBox, "Enter MTA serial...")
+ guiSetEnabled(aBan.SerialEditBox, true)
+ aBan.SerialEditBoxRecievedInput = false
+end
+
+function aBan.onClick(button, state)
+ if not (button == "left" and state == "up") then
+ return
+ end
+
+ -- Handle cancel button first
+ if source == aBan.CancelButton then
+ aBan.Close()
+ return
+ end
+
+ -- Autofill and enable/disable duration editbox based on choice
+ if source == aBan.DurationComboBox then
+ local selected = guiComboBoxGetSelected(aBan.DurationComboBox)
+ if selected == -1 then
+ return
+ elseif selected == #aBan.defaultDurations - 2 then
+ -- Second-last option is permanent duration - clear and disable edit box
+ guiSetText(aBan.DurationEditBox, "")
+ guiSetEnabled(aBan.DurationEditBox, false)
+ elseif selected == #aBan.defaultDurations - 1 then
+ -- Last option (should) be custom duration - enable duration edit box
+ guiSetText(aBan.DurationEditBox, "Duration (seconds)...")
+ guiSetEnabled(aBan.DurationEditBox, true)
+ aBan.DurationEditBoxRecievedInput = false
+ else
+ guiSetText(aBan.DurationEditBox, aBan.defaultDurations[selected + 1][2])
+ guiSetEnabled(aBan.DurationEditBox, false)
+ end
+ return
+ end
+
+ -- Toggle IP/serial fields based on corresponding checkboxes
+ if source == aBan.IPCheckBox and (not aBan.playerName) then
+ guiSetEnabled(aBan.IPEditBox, guiCheckBoxGetSelected(source))
+ return
+ elseif source == aBan.SerialCheckBox and (not aBan.playerName) then
+ guiSetEnabled(aBan.SerialEditBox, guiCheckBoxGetSelected(source))
+ return
+ end
+
+ -- Handle submit button
+ if source == aBan.SubmitButton then
+ aBan.verifyForm()
+ return
+ end
+end
+
+function aBan.onFocus()
+ -- Clear reason/duration/IP/serial edit boxes on first click
+ if source == aBan.ReasonEditBox then
+ if not aBan.ReasonEditBoxRecievedInput then
+ guiSetText(aBan.ReasonEditBox, "")
+ aBan.ReasonEditBoxRecievedInput = true
end
- aBanReason =
- guiCreateLabel(
- 0.03,
- 0.60,
- 0.80,
- 0.30,
- "Reason: " .. iif(aBans["IP"][ip]["reason"], aBans["IP"][ip]["reason"], "Unknown"),
- true,
- aBanForm
- )
- guiLabelSetHorizontalAlign(aBanReason, 4)
- guiSetVisible(aBanForm, true)
- guiBringToFront(aBanForm)
- elseif (aBans["Serial"][ip]) then
- guiSetText(aBanIP, "Serial: " .. ip)
- guiSetText(aBanNick, "Nickname: " .. iif(aBans["Serial"][ip]["nick"], aBans["Serial"][ip]["nick"], "Unknown"))
- guiSetText(aBanDate, "Date: " .. iif(aBans["Serial"][ip]["date"], aBans["Serial"][ip]["date"], "Unknown"))
- guiSetText(aBanTime, "Time: " .. iif(aBans["Serial"][ip]["time"], aBans["Serial"][ip]["time"], "Unknown"))
- guiSetText(
- aBanBanner,
- "Bant by: " .. iif(aBans["Serial"][ip]["banner"], aBans["Serial"][ip]["banner"], "Unknown")
- )
- if (aBanReason) then
- destroyElement(aBanReason)
+ elseif source == aBan.DurationEditBox then
+ if not aBan.DurationEditBoxRecievedInput then
+ guiSetText(aBan.DurationEditBox, "")
+ aBan.DurationEditBoxRecievedInput = true
+ end
+ elseif source == aBan.IPEditBox then
+ if not aBan.IPEditBoxRecievedInput then
+ guiSetText(aBan.IPEditBox, "")
+ aBan.IPEditBoxRecievedInput = true
+ end
+ elseif source == aBan.SerialEditBox then
+ if not aBan.SerialEditBoxRecievedInput then
+ guiSetText(aBan.SerialEditBox, "")
+ aBan.SerialEditBoxRecievedInput = true
end
- aBanReason =
- guiCreateLabel(
- 0.03,
- 0.60,
- 0.80,
- 0.30,
- "Reason: " .. iif(aBans["Serial"][ip]["reason"], aBans["Serial"][ip]["reason"], "Unknown"),
- true,
- aBanForm
- )
- guiLabelSetHorizontalAlign(aBanReason, 4)
- guiSetVisible(aBanForm, true)
- guiBringToFront(aBanForm)
end
end
-function aBanDetailsClose(destroy)
- if ((destroy) or (guiCheckBoxGetSelected(aPerformanceBan))) then
- if (aBanForm) then
- removeEventHandler("onClientGUIClick", aBanForm, aClientBanClick)
- destroyElement(aBanForm)
- aBanForm = nil
+function aBan.onBlur()
+ -- Reset default text of reason/duration/IP/serial edit boxes if they lose focus with no input
+ if source == aBan.ReasonEditBox then
+ if guiGetText(source) == "" then
+ guiSetText(aBan.ReasonEditBox, "Enter ban reason...")
+ aBan.ReasonEditBoxRecievedInput = false
+ end
+ elseif source == aBan.DurationEditBox then
+ if guiGetText(source) == "" and (guiComboBoxGetSelected(aBan.DurationComboBox) == #aBan.defaultDurations - 1) then
+ guiSetText(aBan.DurationEditBox, "Duration (seconds)...")
+ aBan.DurationEditBoxRecievedInput = false
+ end
+ elseif source == aBan.IPEditBox then
+ if guiGetText(source) == "" then
+ guiSetText(aBan.IPEditBox, "Enter IP address...")
+ aBan.IPEditBoxRecievedInput = false
+ end
+ elseif source == aBan.SerialEditBox then
+ if guiGetText(source) == "" then
+ guiSetText(aBan.SerialEditBox, "Enter MTA serial...")
+ aBan.SerialEditBoxRecievedInput = false
end
- else
- guiSetVisible(aBanForm, false)
end
end
-function aClientBanClick(button)
- if (button == "left") then
- if (source == aBanClose) then
- aBanDetailsClose(false)
+function aBan.verifyForm()
+ -- Verify ban reason
+ local banReason = guiGetText(aBan.ReasonEditBox)
+ if banReason == "" or (not aBan.ReasonEditBoxRecievedInput) then
+ messageBox("No ban reason provided.", MB_ERROR, MB_OK)
+ return
+ end
+
+ -- Verify ban duration
+ local banDuration
+ local durationSelection = guiComboBoxGetSelected(aBan.DurationComboBox)
+ if durationSelection == -1 then
+ messageBox("No ban duration provided.", MB_ERROR, MB_OK)
+ return
+ end
+ durationSelection = durationSelection + 1 -- ComboBox item indices starts at 0 instead of one
+ if durationSelection == #aBan.defaultDurations then
+ banDuration = guiGetText(aBan.DurationEditBox)
+ banDuration = tonumber(banDuration)
+ if not banDuration or banDuration <= 0 then
+ messageBox("Invalid ban duration provided.", MB_ERROR, MB_OK)
+ return
+ end
+ else
+ banDuration = aBan.defaultDurations[durationSelection][2]
+ end
+
+ -- Verify ban IP
+ local banIP = ""
+ if guiCheckBoxGetSelected(aBan.IPCheckBox) then
+ banIP = guiGetText(aBan.IPEditBox)
+ if banIP == "" or (not aBan.IPEditBoxRecievedInput) then
+ if not aBan.playerName then
+ messageBox("No IP address provided.", MB_ERROR, MB_OK)
+ return
+ end
+ end
+ end
+
+ -- Verify ban serial
+ local banSerial = ""
+ if guiCheckBoxGetSelected(aBan.SerialCheckBox) then
+ banSerial = guiGetText(aBan.SerialEditBox)
+ if banSerial == "" or (not aBan.SerialEditBoxRecievedInput) or #banSerial ~= 32 then
+ outputDebugString("len = "..#banSerial)
+ if not aBan.playerName then
+ messageBox("Invalid MTA serial provided.", MB_ERROR, MB_OK)
+ return
+ end
+ end
+ end
+
+ -- Show confirmation dialog
+ local confirmationMessage
+ if aBan.playerName then
+ confirmationMessage = "Are you sure you want to ban "..aBan.playerName.."?"
+ else
+ confirmationMessage = "Are you sure you want to add this ban?\nIP = "..(banIP ~= "" and banIP or "None").."\nSerial = "..(banSerial ~= "" and banSerial or "None")
+ end
+
+ if messageBox(confirmationMessage, MB_QUESTION, MB_YESNO) then
+ -- Build ban request "packet" and send to server
+ local actualPlayer -- Actual player may be offline
+ if aBan.playerName then
+ actualPlayer = getPlayerFromName(aBan.playerName)
end
+ local data = {
+ player = actualPlayer,
+ playerName = aBan.playerName,
+ ip = banIP,
+ serial = banSerial,
+ reason = banReason,
+ duration = banDuration
+ }
+ triggerServerEvent(EVENT_BAN, localPlayer, "ban", data)
end
end
diff --git a/[admin]/admin2/client/widgets/admin_ban_details.lua b/[admin]/admin2/client/widgets/admin_ban_details.lua
new file mode 100644
index 000000000..47d3e203c
--- /dev/null
+++ b/[admin]/admin2/client/widgets/admin_ban_details.lua
@@ -0,0 +1,106 @@
+--[[**********************************
+*
+* Multi Theft Auto - Admin Panel
+*
+* client\widgets\admin_ban_details.lua
+*
+**************************************]]
+aBanDetails = {
+ Form = nil,
+ banID = nil
+}
+
+function aBanDetails.Show(banID, showUnban)
+ if not aBanDetails.Form then
+ aBanDetails.Create()
+ end
+
+ aBanDetails.banID = banID
+ local data = aBansTab.List[banID]
+ guiSetText(aBanDetails.NickText, "Player name: "..(data.nick or "Unknown"))
+ guiSetText(aBanDetails.IPText, "IP: "..(data.ip or "None"))
+ guiSetText(aBanDetails.SerialText, "Serial: "..(data.serial or "None"))
+ guiSetText(aBanDetails.ReasonText, "Reason: "..(data.reason or "None"))
+ guiSetText(aBanDetails.AdminText, "Responsible admin: "..(data.banner or "Unknown"))
+ if data.unban then
+ guiSetText(aBanDetails.ExpireText, "Expire time: "..formatDate("m/d/y h:m", nil, data.unban))
+ else
+ guiSetText(aBanDetails.ExpireText, "Expire time: Never")
+ end
+
+ addEventHandler("onClientGUIClick", aBanDetails.Form, aBanDetails.onClick)
+ guiSetVisible(aBanDetails.Form, true)
+
+ -- Toggle visibilty of certain elements if this is being opened as a confimration dialog for unban action
+ if showUnban then
+ guiSetText(aBanDetails.ConfirmationText, "Are you sure you want to remove this ban?")
+ guiSetVisible(aBanDetails.CloseButton, false)
+ guiSetVisible(aBanDetails.SubmitButton, true)
+ guiSetVisible(aBanDetails.CancelButton, true)
+ end
+ guiBringToFront(aBanDetails.Form)
+end
+
+function aBanDetails.Close(destroy)
+ if destroy then
+ destroyElement(aBanDetails.Form)
+ aBanDetails.Form = nil
+ else
+ removeEventHandler("onClientGUIClick", aBanDetails.Form, aBanDetails.onClick)
+ guiSetVisible(aBanDetails.Form, false)
+ aBanDetails.Reset()
+ end
+ aBanDetails.banID = nil
+end
+
+function aBanDetails.Create()
+ local sx, sy = guiGetScreenSize()
+ aBanDetails.Form = guiCreateWindow(sx / 2 - 175, sy / 2 - 135, 350, 250, "Ban Details", false)
+ aBanDetails.ConfirmationText = guiCreateLabel(25, 40, 300, 20, "Ban details:", false, aBanDetails.Form)
+ aBanDetails.NickText = guiCreateLabel(50, 70, 300, 20, "Player name: Unknown", false, aBanDetails.Form)
+ aBanDetails.IPText = guiCreateLabel(50, 90, 300, 20, "IP: None", false, aBanDetails.Form)
+ aBanDetails.SerialText = guiCreateLabel(50, 110, 300, 20, "Serial: None", false, aBanDetails.Form)
+ aBanDetails.ReasonText = guiCreateLabel(50, 130, 300, 20, "Reason: None", false, aBanDetails.Form)
+ aBanDetails.AdminText = guiCreateLabel(50, 150, 300, 20, "Responsible admin: Unknown", false, aBanDetails.Form)
+ aBanDetails.ExpireText = guiCreateLabel(50, 170, 300, 20, "Expire time: Never", false, aBanDetails.Form)
+
+ aBanDetails.SubmitButton = guiCreateButton(105, 200, 60, 40, "Submit", false, aBanDetails.Form)
+ aBanDetails.CancelButton = guiCreateButton(185, 200, 60, 40, "Cancel", false, aBanDetails.Form)
+ aBanDetails.CloseButton = guiCreateButton(145, 200, 60, 40, "Close", false, aBanDetails.Form)
+ guiSetVisible(aBanDetails.CloseButton, true)
+ guiSetVisible(aBanDetails.SubmitButton, false)
+ guiSetVisible(aBanDetails.CancelButton, false)
+ aRegister("Ban Details", aBanDetails.Form, aBanDetails.Show, aBanDetails.Close)
+ guiSetVisible(aBanDetails.Form, false)
+end
+
+function aBanDetails.Reset()
+ guiSetText(aBanDetails.Form, "Ban Details")
+ guiSetText(aBanDetails.ConfirmationText, "Ban details:")
+ guiSetText(aBanDetails.NickText, "Player name: Unknown")
+ guiSetText(aBanDetails.IPText, "IP: None")
+ guiSetText(aBanDetails.SerialText, "Serial: None")
+ guiSetText(aBanDetails.ReasonText, "Reason: None")
+ guiSetText(aBanDetails.AdminText, "Responsible admin: Unknown")
+ guiSetText(aBanDetails.ExpireText, "Expire time: Never")
+ guiSetVisible(aBanDetails.CloseButton, true)
+ guiSetVisible(aBanDetails.SubmitButton, false)
+ guiSetVisible(aBanDetails.CancelButton, false)
+end
+
+function aBanDetails.onClick(button, state)
+ if not (button == "left" and state == "up") then
+ return
+ end
+
+ -- Handle cancel button first
+ if source == aBanDetails.CancelButton or source == aBanDetails.CloseButton then
+ aBanDetails.Close()
+ return
+ end
+
+ if source == aBanDetails.SubmitButton then
+ triggerServerEvent(EVENT_BAN, localPlayer, "unban", aBanDetails.banID)
+ return
+ end
+end
\ No newline at end of file
diff --git a/[admin]/admin2/conf/commands.xml b/[admin]/admin2/conf/commands.xml
index e2079d23f..f82266625 100644
--- a/[admin]/admin2/conf/commands.xml
+++ b/[admin]/admin2/conf/commands.xml
@@ -55,10 +55,10 @@
-
+
diff --git a/[admin]/admin2/conf/messages.xml b/[admin]/admin2/conf/messages.xml
index a20321d39..062dd7be5 100644
--- a/[admin]/admin2/conf/messages.xml
+++ b/[admin]/admin2/conf/messages.xml
@@ -11,9 +11,6 @@
$data2 - Additional information, not all the nodes use it.
-->
-
- ADMIN: $admin has banned $player ($data)
-
ADMIN: $admin has kicked $player ($data)
@@ -248,21 +245,15 @@
-
- IP: $data successfully removed from bans list
- ADMIN: $admin has unbanned IP $data
-
-
- SERIAL: $data successfully removed from bans list
- ADMIN: $admin has unbanned Serial $data
+
+ ADMIN: $admin has banned $player ($data)
+ ADMIN: $admin has banned $player ($data)
-
- IP: $data successfully added to bans list
- ADMIN: $admin has banned IP $data
+
+ ADMIN: $admin has added a manual ban (IP = $data, Serial = $data2)
-
- SERIAL: $data successfully added to bans list
- ADMIN: $admin has banned Serial $data
+
+ ADMIN: $admin has removed a ban (IP = $data, Serial = $data2)
diff --git a/[admin]/admin2/meta.xml b/[admin]/admin2/meta.xml
index 3f92c2800..2db5c37fa 100644
--- a/[admin]/admin2/meta.xml
+++ b/[admin]/admin2/meta.xml
@@ -1,10 +1,7 @@
-
@@ -64,6 +61,7 @@
+
@@ -111,4 +109,4 @@
-
\ No newline at end of file
+
diff --git a/[admin]/admin2/server/admin_bans.lua b/[admin]/admin2/server/admin_bans.lua
index 707b3b89b..39ff755c3 100644
--- a/[admin]/admin2/server/admin_bans.lua
+++ b/[admin]/admin2/server/admin_bans.lua
@@ -34,7 +34,7 @@ addEventHandler(
ban = getBanData(ban)
}
- aSyncData(nil, "ban", root, data, "command.listbans")
+ requestSync(root, SYNC_BAN, data)
end
)
@@ -51,7 +51,7 @@ addEventHandler(
ban = getBanData(ban)
}
- aSyncData(nil, "ban", root, data, "command.listbans")
+ requestSync(root, SYNC_BAN, data)
end
)
@@ -66,7 +66,7 @@ addEventHandler(
id = id
}
- aSyncData(nil, "ban", root, data, "command.listbans")
+ requestSync(root, SYNC_BAN, data)
aBans.List[id] = nil
end
@@ -106,3 +106,59 @@ function getBanData(ban)
return t
end
+
+local function handleBanRequest(action, data)
+ -- TODO: add commands 'ban' and 'unban'
+ -- Basic security check
+ if client and source ~= client then
+ return
+ end
+
+ -- Permissions check
+ if not hasObjectPermissionTo(source, "command."..action) then
+ outputChatBox("Access denied for '" .. tostring(action) .. "'", source, 255, 168, 0)
+ return
+ end
+
+ -- Add ban
+ if action == "ban" then
+ local ban
+ if isElement(data.player) then
+ ban = banPlayer(data.player, data.ip ~= "" and true, false, data.serial ~= "" and true, source, data.reason, data.duration)
+ else
+ ban = addBan(data.ip ~= "" and data.ip or nil, nil, data.serial ~= "" and data.serial or nil, source, data.reason, data.duration)
+ if data.playerName then
+ setBanNick(ban, data.playerName)
+ end
+ end
+ -- Unlikely to occur, but advise admin if ban failed for some reason
+ if not ban then
+ outputChatBox("Ban action failed - check ban details.", source, 255, 0, 0)
+ return
+ end
+ -- Log this action
+ if isElement(data.player) then
+ aAction("bans", "banplayer", source, data.player, data.reason or "None")
+ else
+ aAction("bans", "addban", source, nil, data.ip or "None", data.serial or "None")
+ end
+ -- Remove ban
+ elseif action == "unban" then
+ local ban = aBans.List[data]
+
+ -- Unlikely to occur, but advise admin if ban failed for some reason
+ if not ban then
+ outputChatBox("Ban action failed - check ban details.", source, 255, 0, 0)
+ return
+ end
+
+ if ban then
+ local banData = getBanData(ban)
+ removeBan(ban, source)
+ aAction("bans", "unban", source, nil, banData.ip or "None", banData.serial or "None")
+ end
+ end
+end
+
+addEvent(EVENT_BAN, true)
+addEventHandler(EVENT_BAN, root, handleBanRequest)
\ No newline at end of file
diff --git a/[admin]/admin2/server/admin_server.lua b/[admin]/admin2/server/admin_server.lua
index 3c591fa20..ae835dcab 100644
--- a/[admin]/admin2/server/admin_server.lua
+++ b/[admin]/admin2/server/admin_server.lua
@@ -397,54 +397,6 @@ addEventHandler(
end
)
-addEvent("aBans", true)
-addEventHandler(
- "aBans",
- root,
- function(action, data)
- if (hasObjectPermissionTo(client, "command." .. action)) then
- local mdata = ""
- local more = ""
- if (action == "banip") then
- mdata = data
- if (not BanIP(data, client)) then
- action = nil
- end
- elseif (action == "banserial") then
- mdata = data
- if (isValidSerial(data)) then
- if (not BanSerial(string.upper(data), client)) then
- action = nil
- end
- else
- outputChatBox("Error - Invalid serial", client, 255, 0, 0)
- action = nil
- end
- elseif (action == "unbanip") then
- mdata = data
- if (not UnbanIP(data, client)) then
- action = nil
- end
- elseif (action == "unbanserial") then
- mdata = data
- if (not UnbanSerial(data, client)) then
- action = nil
- end
- else
- action = nil
- end
-
- if (action ~= nil) then
- aAction("bans", action, client, false, mdata, more)
- triggerEvent("aSync", client, "sync", "bans")
- end
- return true
- end
- outputChatBox("Access denied for '" .. tostring(action) .. "'", client, 255, 168, 0)
- return false
- end
-)
-
addEvent("aAdminChat", true)
addEventHandler(
"aAdminChat",
diff --git a/[admin]/admin2/server/admin_sync.lua b/[admin]/admin2/server/admin_sync.lua
index 8a018b370..a41a0f885 100644
--- a/[admin]/admin2/server/admin_sync.lua
+++ b/[admin]/admin2/server/admin_sync.lua
@@ -107,6 +107,8 @@ addEventHandler(
tableOut["game"] = getGameType()
tableOut["map"] = getMapName()
tableOut["password"] = getServerPassword()
+ elseif (type == SYNC_BAN) then
+ tableOut = data
elseif (type == SYNC_BANS) then
for id, ban in pairs(getBansList()) do
tableOut[id] = getBanData(ban)
diff --git a/[admin]/admin2/shared/utils.lua b/[admin]/admin2/shared/utils.lua
index 1a5482471..8064fc691 100644
--- a/[admin]/admin2/shared/utils.lua
+++ b/[admin]/admin2/shared/utils.lua
@@ -40,3 +40,27 @@ function isAnonAdmin(aplayer)
return (getElementData(player, "AnonAdmin") == true)
end
+
+-- Source: https://wiki.multitheftauto.com/wiki/FormatDate
+-- Credit: NeonBlack
+local weekDays = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }
+function formatDate(format, escaper, timestamp)
+ --check("formatDate", "string", format, "format", {"nil","string"}, escaper, "escaper", {"nil","string"}, timestamp, "timestamp")
+
+ escaper = (escaper or "'"):sub(1, 1)
+ local time = getRealTime(timestamp)
+ local formattedDate = ""
+ local escaped = false
+
+ time.year = time.year + 1900
+ time.month = time.month + 1
+
+ local datetime = { d = ("%02d"):format(time.monthday), h = ("%02d"):format(time.hour), i = ("%02d"):format(time.minute), m = ("%02d"):format(time.month), s = ("%02d"):format(time.second), w = weekDays[time.weekday+1]:sub(1, 2), W = weekDays[time.weekday+1], y = tostring(time.year):sub(-2), Y = time.year }
+
+ for char in format:gmatch(".") do
+ if (char == escaper) then escaped = not escaped
+ else formattedDate = formattedDate..(not escaped and datetime[char] or char) end
+ end
+
+ return formattedDate
+end
\ No newline at end of file