mirror of
https://github.com/Refactorio/RedMew.git
synced 2024-12-04 09:42:30 +02:00
parent
9da9fd021a
commit
4b040d1048
@ -1052,6 +1052,7 @@ stds.factorio_defines = {
|
||||
'on_gui_elem_changed',
|
||||
'on_gui_opened',
|
||||
'on_gui_selection_state_changed',
|
||||
'on_gui_switch_state_changed',
|
||||
'on_gui_text_changed',
|
||||
'on_gui_value_changed',
|
||||
'on_land_mine_armed',
|
||||
|
@ -470,6 +470,9 @@ global.config = {
|
||||
clear_corpses = true,
|
||||
battery_charge = true,
|
||||
}
|
||||
},
|
||||
admin_panel = {
|
||||
enabled = true,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,6 +135,11 @@ if config.map_info.enabled then
|
||||
require 'features.gui.info'
|
||||
require 'features.gui.description_generator'
|
||||
end
|
||||
if config.admin_panel.enabled then
|
||||
require 'features.gui.admin_panel.player_manager'
|
||||
require 'features.gui.admin_panel.map_manager'
|
||||
require 'features.gui.admin_panel.lua_console'
|
||||
end
|
||||
if config.player_list.enabled then
|
||||
require 'features.gui.player_list'
|
||||
end
|
||||
|
@ -24,8 +24,8 @@ Global.register(
|
||||
)
|
||||
|
||||
--- Informs the actor that there is no target. Acts as a central place where this message can be changed.
|
||||
local function print_no_target(target_name)
|
||||
Game.player_print({'common.fail_no_target', target_name}, Color.fail)
|
||||
local function print_no_target(target_name, player)
|
||||
Game.player_print({'common.fail_no_target', target_name}, Color.fail, player)
|
||||
end
|
||||
|
||||
local function know_player_or_rerun(player_name, actor, command_name)
|
||||
@ -38,7 +38,7 @@ local function know_player_or_rerun(player_name, actor, command_name)
|
||||
return true;
|
||||
end
|
||||
|
||||
Game.player_print({'common.rerun_no_target', player_name}, Color.fail)
|
||||
Game.player_print({'common.rerun_no_target', player_name}, Color.fail, actor)
|
||||
return false
|
||||
end
|
||||
|
||||
@ -57,21 +57,21 @@ end
|
||||
--- Toggles cheat mode for a player
|
||||
local function toggle_cheat_mode(_, player)
|
||||
player.cheat_mode = not player.cheat_mode
|
||||
Game.player_print({'admin_commands.toggle_cheat_mode', tostring(player.cheat_mode)})
|
||||
Game.player_print({'admin_commands.toggle_cheat_mode', tostring(player.cheat_mode)}, nil, player)
|
||||
end
|
||||
|
||||
--- Promote someone to regular
|
||||
local function add_regular(args)
|
||||
local function add_regular(args, player)
|
||||
local target_name = args.player
|
||||
local maybe_target_player = game.get_player(target_name)
|
||||
local actor = Utils.get_actor()
|
||||
local actor = args.actor or Utils.get_actor()
|
||||
|
||||
if not maybe_target_player and not know_player_or_rerun(target_name, actor, 'regular') then
|
||||
return
|
||||
end
|
||||
|
||||
if Rank.less_than(target_name, Ranks.guest) then
|
||||
Game.player_print({'admin_commands.regular_add_fail_probation'}, Color.fail)
|
||||
Game.player_print({'admin_commands.regular_add_fail_probation'}, Color.fail, player)
|
||||
return
|
||||
end
|
||||
|
||||
@ -82,15 +82,15 @@ local function add_regular(args)
|
||||
maybe_target_player.print({'admin_commands.regular_add_notify_target'}, Color.warning)
|
||||
end
|
||||
else
|
||||
Game.player_print({'admin_commands.regular_add_fail', target_name, Rank.get_player_rank_name(target_name)}, Color.fail)
|
||||
Game.player_print({'admin_commands.regular_add_fail', target_name, Rank.get_player_rank_name(target_name)}, Color.fail, player)
|
||||
end
|
||||
end
|
||||
|
||||
--- Demote someone from regular
|
||||
local function remove_regular(args)
|
||||
local function remove_regular(args, player)
|
||||
local target_name = args.player
|
||||
local maybe_target_player = game.get_player(target_name)
|
||||
local actor = Utils.get_actor()
|
||||
local actor = args.actor or Utils.get_actor()
|
||||
|
||||
if not maybe_target_player and not know_player_or_rerun(target_name, actor, 'regular-remove') then
|
||||
return
|
||||
@ -104,22 +104,22 @@ local function remove_regular(args)
|
||||
end
|
||||
else
|
||||
local rank_name = Rank.get_player_rank_name(target_name)
|
||||
Game.player_print({'admin_commands.regular_remove_fail', target_name, rank_name}, Color.fail)
|
||||
Game.player_print({'admin_commands.regular_remove_fail', target_name, rank_name}, Color.fail, player)
|
||||
end
|
||||
end
|
||||
|
||||
--- Put someone on probation
|
||||
local function probation_add(args)
|
||||
local function probation_add(args, player)
|
||||
local target_name = args.player
|
||||
local maybe_target_player = game.get_player(target_name)
|
||||
local actor = Utils.get_actor()
|
||||
local actor = args.actor or Utils.get_actor()
|
||||
|
||||
if not maybe_target_player and not know_player_or_rerun(target_name, actor, 'probation') then
|
||||
return
|
||||
end
|
||||
|
||||
if Rank.equal(target_name, Ranks.admin) then
|
||||
Game.player_print({'admin_commands.probation_add_fail_admin'}, Color.fail)
|
||||
Game.player_print({'admin_commands.probation_add_fail_admin'}, Color.fail, player)
|
||||
if maybe_target_player then
|
||||
maybe_target_player.print({'admin_commands.probation_warn_admin', actor}, Color.warning)
|
||||
end
|
||||
@ -133,15 +133,15 @@ local function probation_add(args)
|
||||
maybe_target_player.print({'admin_commands.probation_add_notify_target'}, Color.warning)
|
||||
end
|
||||
else
|
||||
Game.player_print({'admin_commands.probation_add_fail', target_name}, Color.fail)
|
||||
Game.player_print({'admin_commands.probation_add_fail', target_name}, Color.fail, player)
|
||||
end
|
||||
end
|
||||
|
||||
--- Remove someone from probation
|
||||
local function probation_remove(args)
|
||||
local function probation_remove(args, player)
|
||||
local target_name = args.player
|
||||
local maybe_target_player = game.get_player(target_name)
|
||||
local actor = Utils.get_actor()
|
||||
local actor = args.actor or Utils.get_actor()
|
||||
|
||||
if not maybe_target_player and not know_player_or_rerun(target_name, actor, 'probation-remove') then
|
||||
return
|
||||
@ -154,7 +154,7 @@ local function probation_remove(args)
|
||||
maybe_target_player.print({'admin_commands.probation_remove_notify_target'}, Color.warning)
|
||||
end
|
||||
else
|
||||
Game.player_print({'admin_commands.probation_remove_fail', target_name}, Color.fail)
|
||||
Game.player_print({'admin_commands.probation_remove_fail', target_name}, Color.fail, player)
|
||||
end
|
||||
end
|
||||
|
||||
@ -169,7 +169,7 @@ local function jail_player(args, player)
|
||||
local target = Utils.validate_player(target_ident)
|
||||
|
||||
if not target then
|
||||
print_no_target(target_ident)
|
||||
print_no_target(target_ident, player)
|
||||
return
|
||||
end
|
||||
|
||||
@ -182,7 +182,7 @@ local function unjail_player(args, player)
|
||||
local target = Utils.validate_player(target_ident)
|
||||
|
||||
if not target then
|
||||
print_no_target(target_ident)
|
||||
print_no_target(target_ident, player)
|
||||
return
|
||||
end
|
||||
Report.unjail(target, player)
|
||||
@ -199,6 +199,7 @@ local function pool(_, player)
|
||||
end
|
||||
player.surface.set_tiles(t)
|
||||
player.surface.create_entity {name = 'fish', position = {p.x + 0.5, p.y + 5}}
|
||||
Game.player_print({'admin_commands.create_pool'}, Color.success, player)
|
||||
end
|
||||
|
||||
--- Takes a target and teleports them to player
|
||||
@ -207,13 +208,13 @@ local function invoke(args, player)
|
||||
local target = Utils.validate_player(target_ident)
|
||||
|
||||
if not target then
|
||||
print_no_target(target_ident)
|
||||
print_no_target(target_ident, player)
|
||||
return
|
||||
end
|
||||
|
||||
local pos = player.surface.find_non_colliding_position('character', player.position, 50, 1)
|
||||
if not pos then
|
||||
Game.player_print({'admin_commands.invoke_fail_no_location'})
|
||||
Game.player_print({'admin_commands.invoke_fail_no_location'}, player)
|
||||
return
|
||||
end
|
||||
target.teleport({pos.x, pos.y}, player.surface)
|
||||
@ -226,7 +227,7 @@ local function teleport_player(args, player)
|
||||
local target = Utils.validate_player(target_ident)
|
||||
|
||||
if not target then
|
||||
print_no_target(target_ident)
|
||||
print_no_target(target_ident, player)
|
||||
return
|
||||
end
|
||||
|
||||
@ -234,27 +235,27 @@ local function teleport_player(args, player)
|
||||
local surface = target.surface
|
||||
local pos = surface.find_non_colliding_position('character', target.position, 50, 1)
|
||||
if not pos then
|
||||
Game.player_print({'admin_commands.tp_fail_no_location'})
|
||||
Game.player_print({'admin_commands.tp_fail_no_location'}, Color.fail, player)
|
||||
return
|
||||
end
|
||||
player.teleport(pos, surface)
|
||||
game.print({'admin_commands.tp_player_announce', target_name})
|
||||
Game.player_print({'admin_commands.tp_player_success', target_name})
|
||||
Game.player_print({'admin_commands.tp_player_success', target_name}, Color.success, player)
|
||||
end
|
||||
|
||||
--- Takes a selected entity and teleports player to it
|
||||
local function teleport_location(_, player)
|
||||
if not player.selected then
|
||||
Game.player_print({'admin_commands.tp_ent_fail_no_ent'})
|
||||
Game.player_print({'admin_commands.tp_ent_fail_no_ent'}, Color.fail, player)
|
||||
return
|
||||
end
|
||||
local pos = player.surface.find_non_colliding_position('character', player.selected.position, 50, 1)
|
||||
if not pos then
|
||||
Game.player_print({'admin_commands.tp_fail_no_location'})
|
||||
Game.player_print({'admin_commands.tp_fail_no_location'}, Color.fail, player)
|
||||
return
|
||||
end
|
||||
player.teleport(pos)
|
||||
Game.player_print({'admin_commands.tp_end_success'})
|
||||
Game.player_print({'admin_commands.tp_end_success'}, Color.success, player)
|
||||
end
|
||||
|
||||
--- If a player is in the tp_players list, remove ghosts they place and teleport them to that position
|
||||
@ -280,10 +281,10 @@ local function toggle_tp_mode(_, player)
|
||||
|
||||
if toggled then
|
||||
tp_players[index] = nil
|
||||
Game.player_print({'admin_commands.tp_mode_off'})
|
||||
Game.player_print({'admin_commands.tp_mode_off'}, nil, player)
|
||||
else
|
||||
tp_players[index] = true
|
||||
Game.player_print({'admin_commands.tp_mode_on'})
|
||||
Game.player_print({'admin_commands.tp_mode_on'}, nil, player)
|
||||
end
|
||||
end
|
||||
|
||||
@ -303,19 +304,22 @@ end
|
||||
local function revive_ghosts(args, player)
|
||||
local radius = args.radius
|
||||
local pos = player.position
|
||||
local count = 0
|
||||
for _, e in pairs(player.surface.find_entities_filtered {area = {{pos.x - radius, pos.y - radius}, {pos.x + radius, pos.y + radius}}, type = 'entity-ghost'}) do
|
||||
e.revive()
|
||||
count = count + 1
|
||||
end
|
||||
Game.player_print({'admin_commands.revive_ghosts', count}, Color.success, player)
|
||||
end
|
||||
|
||||
--- Destroys the player's selected entity
|
||||
local function destroy_selected(_, player)
|
||||
local ent = player.selected
|
||||
if ent then
|
||||
Game.player_print({'admin_commands.destroy_success', ent.localised_name})
|
||||
Game.player_print({'admin_commands.destroy_success', ent.localised_name}, player)
|
||||
ent.destroy()
|
||||
else
|
||||
Game.player_print({'admin_commands.destroy_fail'})
|
||||
Game.player_print({'admin_commands.destroy_fail'}, player)
|
||||
end
|
||||
end
|
||||
|
||||
@ -472,3 +476,19 @@ Command.add(
|
||||
},
|
||||
destroy_selected
|
||||
)
|
||||
|
||||
return {
|
||||
create_pool = pool,
|
||||
destroy_selected = destroy_selected,
|
||||
invoke_player = invoke,
|
||||
jail_player = jail_player,
|
||||
probation_add = probation_add,
|
||||
probation_remove = probation_remove,
|
||||
regular_add = add_regular,
|
||||
regular_remove = remove_regular,
|
||||
revive_ghosts = revive_ghosts,
|
||||
show_reports = show_reports,
|
||||
teleport_command = teleport_command,
|
||||
toggle_cheat_mode = toggle_cheat_mode,
|
||||
unjail_player = unjail_player,
|
||||
}
|
214
features/gui/admin_panel/core.lua
Normal file
214
features/gui/admin_panel/core.lua
Normal file
@ -0,0 +1,214 @@
|
||||
local Event = require 'utils.event'
|
||||
local Gui = require 'utils.gui'
|
||||
local Global = require 'utils.global'
|
||||
local Config = require 'config'.admin_panel
|
||||
|
||||
local main_button_name = Gui.uid_name()
|
||||
local main_frame_name = Gui.uid_name()
|
||||
local close_button_name = Gui.uid_name()
|
||||
|
||||
local pages = {
|
||||
--[[
|
||||
{
|
||||
type = 'sprite-button',
|
||||
sprite = 'item/programmable-speaker',
|
||||
tooltip = 'First page',
|
||||
},
|
||||
{
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/spawn_flag',
|
||||
tooltip = 'Second page',
|
||||
},
|
||||
{
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/scripting_editor_icon',
|
||||
tooltip = 'Third page',
|
||||
},
|
||||
{
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/surface_editor_icon',
|
||||
tooltip = 'Fourth page',
|
||||
},
|
||||
]]
|
||||
}
|
||||
|
||||
Global.register(pages, function(tbl) pages = tbl end)
|
||||
|
||||
local Public = {}
|
||||
|
||||
function Public.get_pages()
|
||||
return pages
|
||||
end
|
||||
|
||||
function Public.get_canvas(player)
|
||||
return Gui.get_data(Public.get_main_frame(player)).right
|
||||
end
|
||||
|
||||
function Public.get_main_frame(player)
|
||||
local frame = player.gui.screen[main_frame_name]
|
||||
if frame and frame.valid then
|
||||
return frame
|
||||
end
|
||||
|
||||
frame = player.gui.screen.add {
|
||||
type = 'frame',
|
||||
name = main_frame_name,
|
||||
direction = 'vertical',
|
||||
style = 'frame',
|
||||
}
|
||||
frame.auto_center = true
|
||||
player.opened = frame
|
||||
Gui.set_style(frame, {
|
||||
horizontally_stretchable = true,
|
||||
vertically_stretchable = true,
|
||||
natural_width = 400,
|
||||
natural_height = 400,
|
||||
top_padding = 8,
|
||||
bottom_padding = 8,
|
||||
})
|
||||
|
||||
local data = {}
|
||||
|
||||
do -- title
|
||||
local flow = frame.add { type = 'flow', direction = 'horizontal' }
|
||||
Gui.set_style(flow, { horizontal_spacing = 8, vertical_align = 'center', bottom_padding = 4 })
|
||||
|
||||
local label = flow.add { type = 'label', caption = 'Admin panel', style = 'heading_1_label' }
|
||||
label.drag_target = frame
|
||||
|
||||
local dragger = flow.add { type = 'empty-widget', style = 'draggable_space_header' }
|
||||
dragger.drag_target = frame
|
||||
Gui.set_style(dragger, { height = 24, horizontally_stretchable = true })
|
||||
|
||||
flow.add {
|
||||
type = 'sprite-button',
|
||||
name = close_button_name,
|
||||
sprite = 'utility/close_white',
|
||||
clicked_sprite = 'utility/close_black',
|
||||
style = 'close_button',
|
||||
tooltip = {'gui.close-instruction'}
|
||||
}
|
||||
end
|
||||
|
||||
local main_flow = frame.add { type = 'flow', name = 'flow', direction = 'horizontal' }
|
||||
Gui.set_style(main_flow, { horizontal_spacing = 12 })
|
||||
|
||||
do -- left
|
||||
local left = main_flow
|
||||
.add { type = 'flow', name = 'left', direction = 'vertical' }
|
||||
.add { type = 'frame', direction = 'vertical', style = 'inside_deep_frame' }
|
||||
.add { type = 'flow', direction = 'vertical' }
|
||||
Gui.set_style(left, {
|
||||
vertically_stretchable = true,
|
||||
horizontal_align = 'center',
|
||||
padding = 10,
|
||||
vertical_spacing = 10,
|
||||
})
|
||||
|
||||
for _, page in pairs(pages) do
|
||||
left.add(page)
|
||||
end
|
||||
data.left = left
|
||||
end
|
||||
|
||||
do -- right
|
||||
local right = main_flow
|
||||
.add { type = 'frame', name = 'right', style = 'inside_shallow_frame_with_padding' }
|
||||
.add { type = 'flow', name = 'flow', direction = 'vertical' }
|
||||
Gui.set_style(right, {
|
||||
minimal_width = 300,
|
||||
minimal_height = 300,
|
||||
vertically_stretchable = true,
|
||||
horizontally_stretchable = true,
|
||||
})
|
||||
data.right = right
|
||||
end
|
||||
|
||||
Gui.set_data(frame, data)
|
||||
end
|
||||
|
||||
function Public.update_top_button(player)
|
||||
if not Config.enabled then
|
||||
return
|
||||
end
|
||||
|
||||
local button = Gui.add_top_element(player, {
|
||||
type = 'sprite-button',
|
||||
name = main_button_name,
|
||||
sprite = 'item/power-armor-mk2',
|
||||
tooltip = {'admin_panel.info_tooltip'},
|
||||
})
|
||||
button.visible = player.admin
|
||||
end
|
||||
|
||||
function Public.toggle_main_button(player)
|
||||
local main_frame = player.gui.screen[main_frame_name]
|
||||
if main_frame then
|
||||
Gui.destroy(main_frame)
|
||||
else
|
||||
Public.get_main_frame(player)
|
||||
end
|
||||
end
|
||||
|
||||
function Public.close_all_pages(player)
|
||||
local frame = player.gui.screen[main_frame_name]
|
||||
if not (frame and frame.valid) then
|
||||
return
|
||||
end
|
||||
|
||||
for _, button in pairs(Gui.get_data(frame).left.children) do
|
||||
button.toggled = false
|
||||
end
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_player_created, function(event)
|
||||
local player = game.get_player(event.player_index)
|
||||
if not (player and player.valid) then
|
||||
return
|
||||
end
|
||||
Public.update_top_button(player)
|
||||
end)
|
||||
|
||||
Event.add(defines.events.on_player_joined_game, function(event)
|
||||
local player = game.get_player(event.player_index)
|
||||
if not (player and player.valid) then
|
||||
return
|
||||
end
|
||||
Public.update_top_button(player)
|
||||
local frame = player.gui.screen[main_frame_name]
|
||||
if (frame and frame.valid and not player.admin) then
|
||||
Gui.destroy(frame)
|
||||
end
|
||||
end)
|
||||
|
||||
Event.add(defines.events.on_gui_closed, function(event)
|
||||
local element = event.element
|
||||
if not (element and element.valid) then
|
||||
return
|
||||
end
|
||||
|
||||
local player = game.get_player(event.player_index)
|
||||
if not (player and player.valid) then
|
||||
return
|
||||
end
|
||||
|
||||
if element.name == main_frame_name then
|
||||
Public.toggle_main_button(player)
|
||||
end
|
||||
end)
|
||||
|
||||
Gui.allow_player_to_toggle_top_element_visibility(main_button_name)
|
||||
|
||||
Gui.on_click(main_button_name, function(event)
|
||||
Public.toggle_main_button(event.player)
|
||||
end)
|
||||
|
||||
Gui.on_click(close_button_name, function(event)
|
||||
Public.toggle_main_button(event.player)
|
||||
end)
|
||||
|
||||
Gui.on_player_show_top(main_button_name, function(event)
|
||||
Public.update_top_button(event.player)
|
||||
end)
|
||||
|
||||
return Public
|
143
features/gui/admin_panel/functions.lua
Normal file
143
features/gui/admin_panel/functions.lua
Normal file
@ -0,0 +1,143 @@
|
||||
local Color = require 'resources.color_presets'
|
||||
local Game = require 'utils.game'
|
||||
local Performance = require 'features.performance'
|
||||
local Report = require 'features.report'
|
||||
|
||||
-- == ACTIONS =================================================================
|
||||
|
||||
local Actions = require 'features.admin_commands'
|
||||
|
||||
---@param filename? string
|
||||
---@param player? LuaPlayer
|
||||
function Actions.save_game(filename, player)
|
||||
filename = filename or 'currently-running'
|
||||
game.auto_save(filename)
|
||||
Game.player_print('Saving map: _autosave-' .. filename ..'.zip', Color.success, player)
|
||||
end
|
||||
|
||||
---@param player? LuaPlayer
|
||||
function Actions.remove_all_ghost_entities(player)
|
||||
local count = 0
|
||||
for _, surface in pairs(game.surfaces) do
|
||||
for _, ghost in pairs(surface.find_entities_filtered { type = { 'entity-ghost', 'tile-ghost' }}) do
|
||||
ghost.destroy()
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
Game.player_print(count .. ' ghost entities removed from all surfaces.', Color.success, player)
|
||||
end
|
||||
|
||||
---@param player? LuaPlayer
|
||||
function Actions.destroy_all_speakers(player)
|
||||
local count = 0
|
||||
for _, surface in pairs(game.surfaces) do
|
||||
for _, speaker in pairs(surface.find_entities_filtered { type = 'programmable-speaker' }) do
|
||||
if speaker.parameters.playback_globally == true then
|
||||
speaker.die('player')
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
Game.player_print(count .. ' speakers removed from all surfaces.', Color.success, player)
|
||||
end
|
||||
|
||||
---@param player? LuaPlayer
|
||||
function Actions.kill_all_enemy_units(player)
|
||||
game.forces.enemy.kill_all_units()
|
||||
Game.player_print('All enemy units have been killed.', Color.success, player)
|
||||
end
|
||||
|
||||
---@param player? LuaPlayer
|
||||
function Actions.kill_all_enemies(player)
|
||||
local count = 0
|
||||
for _, surface in pairs(game.surfaces) do
|
||||
for _, enemy in pairs(surface.find_entities_filtered { force = 'enemy' }) do
|
||||
enemy.die('player')
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
game.forces.enemy.kill_all_units()
|
||||
Game.player_print(count .. ' enemies have been killed.', Color.success, player)
|
||||
end
|
||||
|
||||
---@param target_name string
|
||||
---@param reason? string
|
||||
---@param admin? LuaPlayer
|
||||
function Actions.ban_player(target_name, reason, admin)
|
||||
local player = game.get_player(target_name)
|
||||
if not (player and player.valid) then
|
||||
Game.player_print('Could not ban player: ' .. target_name, Color.fail, admin)
|
||||
return
|
||||
end
|
||||
Report.ban_player(player, reason, admin)
|
||||
end
|
||||
|
||||
---@param target_player string
|
||||
---@param source_player LuaPlayer
|
||||
function Actions.spank(target_name, source_player)
|
||||
local target_player = game.get_player(target_name)
|
||||
local character = target_player.character
|
||||
if not (character and character.valid) then
|
||||
return
|
||||
end
|
||||
if character.health > 5 then
|
||||
character.damage(5, 'player')
|
||||
end
|
||||
target_player.surface.create_entity { name = 'water-splash', position = target_player.position }
|
||||
game.print(source_player.name .. ' spanked ' .. target_player.name, Color.warning)
|
||||
end
|
||||
|
||||
-- == SURFACE =================================================================
|
||||
|
||||
local Surface = {}
|
||||
|
||||
---@param scale number
|
||||
function Surface.performance_scale_set(scale)
|
||||
Performance.set_time_scale(scale)
|
||||
local stat_mod = Performance.get_player_stat_modifier()
|
||||
game.print({'performance.stat_preamble'})
|
||||
game.print({'performance.generic_stat', {'performance.game_speed'}, string.format('%.2f', Performance.get_time_scale())})
|
||||
local stat_string = string.format('%.2f', stat_mod)
|
||||
game.print({'performance.output_formatter', {'performance.running_speed'}, stat_string, {'performance.manual_mining_speed'}, stat_string, {'performance.manual_crafting_speed'}, stat_string})
|
||||
end
|
||||
|
||||
---@param player LuaPlayer
|
||||
---@param radius number
|
||||
function Surface.chart_map(player, radius)
|
||||
local position = player.position
|
||||
local area = {
|
||||
left_top = { x = position.x - radius, y = position.y - radius },
|
||||
right_bottom = { x = position.x + radius, y = position.y + radius }
|
||||
}
|
||||
player.force.chart(player.surface, area)
|
||||
Game.player_print('Revealing the area around you...', Color.success, player)
|
||||
end
|
||||
|
||||
---@param player LuaPlayer
|
||||
function Surface.hide_all(player)
|
||||
local surface = player.surface
|
||||
local force = player.force
|
||||
for chunk in surface.get_chunks() do
|
||||
force.unchart_chunk({ x = chunk.x, y = chunk.y }, surface)
|
||||
end
|
||||
Game.player_print('Hidden all of ' ..surface.name .. ' surface', Color.success, player)
|
||||
end
|
||||
|
||||
---@param player LuaPlayer
|
||||
function Surface.reveal_all(player)
|
||||
player.force.chart_all()
|
||||
Game.player_print('Removing the fog from ' .. player.surface.name .. ' surface', Color.success, player)
|
||||
end
|
||||
|
||||
---@param player LuaPlayer
|
||||
function Surface.rechart_all(player)
|
||||
player.force.rechart()
|
||||
Game.player_print('Revealing all of ' .. player.surface.name .. ' surface', Color.success, player)
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
|
||||
return {
|
||||
actions = Actions,
|
||||
surface = Surface,
|
||||
}
|
117
features/gui/admin_panel/lua_console.lua
Normal file
117
features/gui/admin_panel/lua_console.lua
Normal file
@ -0,0 +1,117 @@
|
||||
local Gui = require 'utils.gui'
|
||||
local Global = require 'utils.global'
|
||||
local AdminPanel = require 'features.gui.admin_panel.core'
|
||||
|
||||
local main_button_name = Gui.uid_name()
|
||||
local clear_button_name = Gui.uid_name()
|
||||
local dry_run_button_name = Gui.uid_name()
|
||||
local confirm_button_name = Gui.uid_name()
|
||||
|
||||
local this = {
|
||||
last_lua_input = {},
|
||||
last_lua_output = {},
|
||||
}
|
||||
|
||||
Global.register(this, function(tbl) this = tbl end)
|
||||
|
||||
local pages = AdminPanel.get_pages()
|
||||
pages[#pages +1] = {
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/scripting_editor_icon',
|
||||
tooltip = '[font=default-bold]Lua console[/font]',
|
||||
name = main_button_name,
|
||||
auto_toggle = true,
|
||||
}
|
||||
|
||||
local function draw_gui(player)
|
||||
local canvas = AdminPanel.get_canvas(player)
|
||||
Gui.clear(canvas)
|
||||
|
||||
this.last_lua_input[player.index] = this.last_lua_input[player.index] or ''
|
||||
this.last_lua_output[player.index] = this.last_lua_output[player.index] or ''
|
||||
|
||||
local info = canvas.add { type = 'frame', style = 'deep_frame_in_shallow_frame_for_tabs', direction = 'vertical' }
|
||||
Gui.set_style(info, { padding = 12, horizontally_stretchable = true })
|
||||
info.add { type = 'label', caption = '[font=default-bold][color=green]Input:[/color][/font]' }
|
||||
info.add { type = 'label', caption = ' - no need to append `/c` at the beginning of the code' }
|
||||
info.add { type = 'label', caption = ' - can accept pure strings instead of commands' }
|
||||
info.add { type = 'label', caption = '[font=default-bold][color=red]Output:[/color][/font]' }
|
||||
info.add { type = 'label', caption = ' - errors of the code will be displayed here, if any' }
|
||||
|
||||
local input = canvas
|
||||
.add { type = 'frame', style = 'bordered_frame', direction = 'vertical', caption = 'Input' }
|
||||
.add { type = 'text-box', name = 'input' }
|
||||
input.word_wrap = true
|
||||
input.text = this.last_lua_input[player.index]
|
||||
Gui.set_style(input, { minimal_height = 240, minimal_width = 460, maximal_height = 800 })
|
||||
|
||||
local output = canvas
|
||||
.add { type = 'frame', style = 'bordered_frame', direction = 'vertical', caption = 'Output' }
|
||||
.add { type = 'text-box', name = 'output' }
|
||||
output.word_wrap = true
|
||||
output.text = this.last_lua_output[player.index]
|
||||
Gui.set_style(output, { minimal_height = 60, minimal_width = 460, maximal_height = 120 })
|
||||
|
||||
local button_flow = canvas.add { type = 'flow', direction = 'horizontal' }
|
||||
Gui.add_pusher(button_flow)
|
||||
button_flow.add { type = 'button', name = clear_button_name, style = 'red_back_button', caption = 'Clear' }
|
||||
local dry_run = button_flow.add { type = 'button', name = dry_run_button_name, style = 'forward_button', caption = 'Dry run' }
|
||||
local confirm = button_flow.add { type = 'button', name = confirm_button_name, style = 'confirm_double_arrow_button', caption = 'Confirm', tooltip = 'Run input code' }
|
||||
Gui.set_style(confirm, { left_margin = - 4 })
|
||||
|
||||
Gui.set_data(dry_run, { input = input, output = output })
|
||||
Gui.set_data(confirm, { input = input, output = output })
|
||||
end
|
||||
|
||||
local function process_command(event)
|
||||
local player = event.player
|
||||
local data = Gui.get_data(event.element)
|
||||
local input, output = data.input, data.output
|
||||
|
||||
local cmd = input.text
|
||||
this.last_lua_input[player.index] = cmd
|
||||
rawset(game, 'player', player)
|
||||
|
||||
local f, err, _
|
||||
f, err = loadstring(cmd)
|
||||
if not f then
|
||||
cmd = 'game.players[' .. player.index .. '].print(' .. cmd .. ')'
|
||||
f, err = loadstring(cmd)
|
||||
end
|
||||
|
||||
if event.element.name ~= dry_run_button_name then
|
||||
_, err = pcall(f)
|
||||
end
|
||||
rawset(game, 'player', nil)
|
||||
|
||||
if err then
|
||||
local text = ''
|
||||
text = text .. cmd .. '\n'
|
||||
text = text .. '----------------------------------------------------------------------\n'
|
||||
text = text .. err:sub(1, err:find('\n'))
|
||||
output.text = text
|
||||
this.last_lua_output[player.index] = text
|
||||
end
|
||||
end
|
||||
|
||||
Gui.on_click(main_button_name, function(event)
|
||||
local player = event.player
|
||||
local element = event.element
|
||||
if element.toggled then
|
||||
AdminPanel.close_all_pages(player)
|
||||
event.element.toggled = true
|
||||
draw_gui(player)
|
||||
else
|
||||
Gui.clear(AdminPanel.get_canvas(player))
|
||||
end
|
||||
end)
|
||||
|
||||
Gui.on_click(dry_run_button_name, process_command)
|
||||
Gui.on_click(confirm_button_name, process_command)
|
||||
|
||||
Gui.on_click(clear_button_name, function(event)
|
||||
local player = event.player
|
||||
this.last_lua_input[player.index] = ''
|
||||
this.last_lua_output[player.index] = ''
|
||||
draw_gui(player)
|
||||
end)
|
354
features/gui/admin_panel/map_manager.lua
Normal file
354
features/gui/admin_panel/map_manager.lua
Normal file
@ -0,0 +1,354 @@
|
||||
local AdminPanel = require 'features.gui.admin_panel.core'
|
||||
local Event = require 'utils.event'
|
||||
local Gui = require 'utils.gui'
|
||||
local math = require 'utils.math'
|
||||
local Surface = require 'features.gui.admin_panel.functions'.surface
|
||||
|
||||
local main_button_name = Gui.uid_name()
|
||||
local slider_tag_name = Gui.uid_name()
|
||||
|
||||
local on_performance_speed = Gui.uid_name()
|
||||
local on_slow_down = Gui.uid_name()
|
||||
local on_speed_up = Gui.uid_name()
|
||||
local on_pollution_ageing = Gui.uid_name()
|
||||
local on_pollution_diffusion = Gui.uid_name()
|
||||
local on_pollution_attack_modifier = Gui.uid_name()
|
||||
local on_evolution_value = Gui.uid_name()
|
||||
local on_evolution_destroy_factor= Gui.uid_name()
|
||||
local on_evolution_time_factor = Gui.uid_name()
|
||||
local on_map_chart = Gui.uid_name()
|
||||
local on_map_hide = Gui.uid_name()
|
||||
local on_map_reveal = Gui.uid_name()
|
||||
local on_map_rechart = Gui.uid_name()
|
||||
|
||||
local pages = AdminPanel.get_pages()
|
||||
pages[#pages +1] = {
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/surface_editor_icon',
|
||||
tooltip = '[font=default-bold]Map manager[/font]',
|
||||
name = main_button_name,
|
||||
auto_toggle = true,
|
||||
}
|
||||
|
||||
local function make_button(parent, params)
|
||||
local button = parent.add {
|
||||
type = 'button',
|
||||
caption = params.caption,
|
||||
name = params.name,
|
||||
tooltip = params.tooltip,
|
||||
}
|
||||
Gui.set_style(button, {
|
||||
horizontally_stretchable = true,
|
||||
})
|
||||
return button
|
||||
end
|
||||
|
||||
local function make_slider(parent, params)
|
||||
local flow = parent.add { type = 'flow', direction = 'horizontal' }
|
||||
Gui.set_style(flow, { vertical_align = 'center', maximal_width = 467 })
|
||||
local button = flow.add(params.button)
|
||||
Gui.set_style(button, { width = 150 })
|
||||
params.slider.value = math.clamp(params.value, params.slider.minimum_value, params.slider.maximum_value)
|
||||
local slider = flow.add(params.slider)
|
||||
slider.tags = { name = slider_tag_name }
|
||||
slider.tooltip = string.format(params.format, slider.slider_value)
|
||||
Gui.set_style(slider, { width = 250 })
|
||||
local label = flow.add { type = 'label', caption = string.format(params.format, params.value), tooltip = params.tooltip or 'Current value' }
|
||||
Gui.set_style(label, { width = 52, horizontal_align = 'right' })
|
||||
|
||||
local data = { button = button, slider = slider, label = label, format = params.format }
|
||||
Gui.set_data(button, data)
|
||||
Gui.set_data(slider, data)
|
||||
end
|
||||
|
||||
local function update_slider(element)
|
||||
local data = Gui.get_data(element)
|
||||
data.label.caption = string.format(data.format, data.slider.slider_value)
|
||||
return data.slider.slider_value
|
||||
end
|
||||
|
||||
local function draw_gui(player)
|
||||
local canvas = AdminPanel.get_canvas(player)
|
||||
Gui.clear(canvas)
|
||||
|
||||
local ms = game.map_settings
|
||||
local evolution = ms.enemy_evolution
|
||||
local pollution = ms.pollution
|
||||
|
||||
local row_1 = canvas.add { type = 'frame', style = 'bordered_frame', direction = 'vertical', caption = 'Game speed' }
|
||||
make_slider(row_1, {
|
||||
button = {
|
||||
type = 'button',
|
||||
name = on_performance_speed,
|
||||
caption = 'Performance speed',
|
||||
tooltip = {'command_description.performance_scale_set'},
|
||||
},
|
||||
slider = {
|
||||
type = 'slider',
|
||||
minimum_value = 0.05,
|
||||
maximum_value = 1,
|
||||
value_step = 0.05,
|
||||
},
|
||||
format = '%.2f',
|
||||
value = game.speed,
|
||||
})
|
||||
make_slider(row_1, {
|
||||
button = {
|
||||
type = 'button',
|
||||
name = on_slow_down,
|
||||
caption = 'Slow down'
|
||||
},
|
||||
slider = {
|
||||
type = 'slider',
|
||||
minimum_value = 0.05,
|
||||
maximum_value = 1,
|
||||
value_step = 0.05,
|
||||
},
|
||||
format = '%.2f',
|
||||
value = game.speed,
|
||||
})
|
||||
make_slider(row_1, {
|
||||
button = {
|
||||
type = 'button',
|
||||
name = on_speed_up,
|
||||
caption = 'Speed up'
|
||||
},
|
||||
slider = {
|
||||
type = 'slider',
|
||||
minimum_value = 1,
|
||||
maximum_value = 10,
|
||||
value_step = 0.5,
|
||||
},
|
||||
format = '%.2f',
|
||||
value = game.speed,
|
||||
})
|
||||
|
||||
local row_2 = canvas.add { type = 'frame', style = 'bordered_frame', direction = 'vertical', caption = 'Pollution' }
|
||||
make_slider(row_2, {
|
||||
button = {
|
||||
type = 'button',
|
||||
name = on_pollution_ageing,
|
||||
caption = 'Ageing'
|
||||
},
|
||||
slider = {
|
||||
type = 'slider',
|
||||
style = 'notched_slider',
|
||||
minimum_value = 0.1,
|
||||
maximum_value = 1,
|
||||
value_step = 0.1,
|
||||
},
|
||||
format = '%.2f',
|
||||
value = pollution.ageing,
|
||||
})
|
||||
make_slider(row_2, {
|
||||
button = {
|
||||
type = 'button',
|
||||
name = on_pollution_diffusion,
|
||||
caption = 'Diffusion ratio'
|
||||
},
|
||||
slider = {
|
||||
type = 'slider',
|
||||
style = 'notched_slider',
|
||||
minimum_value = 0,
|
||||
maximum_value = 0.1,
|
||||
value_step = 0.02,
|
||||
},
|
||||
format = '%.2f',
|
||||
value = pollution.diffusion_ratio,
|
||||
})
|
||||
make_slider(row_2, {
|
||||
button = {
|
||||
type = 'button',
|
||||
name = on_pollution_attack_modifier,
|
||||
caption = 'Atk. modifier'
|
||||
},
|
||||
slider = {
|
||||
type = 'slider',
|
||||
style = 'notched_slider',
|
||||
minimum_value = 0.1,
|
||||
maximum_value = 1,
|
||||
value_step = 0.1,
|
||||
},
|
||||
format = '%.2f',
|
||||
value = pollution.enemy_attack_pollution_consumption_modifier,
|
||||
})
|
||||
|
||||
local row_3 = canvas.add { type = 'frame', style = 'bordered_frame', direction = 'vertical', caption = 'Evolution' }
|
||||
make_slider(row_3, {
|
||||
button = {
|
||||
type = 'button',
|
||||
name = on_evolution_value,
|
||||
caption = 'Enemy evolution'
|
||||
},
|
||||
slider = {
|
||||
type = 'slider',
|
||||
minimum_value = 0,
|
||||
maximum_value = 100,
|
||||
value_step = 0.01,
|
||||
},
|
||||
format = '%.2f',
|
||||
value = game.forces.enemy.evolution_factor * 100,
|
||||
tooltip = 'Current value, %',
|
||||
})
|
||||
make_slider(row_3, {
|
||||
button = {
|
||||
type = 'button',
|
||||
name = on_evolution_destroy_factor,
|
||||
caption = 'Destroy factor'
|
||||
},
|
||||
slider = {
|
||||
type = 'slider',
|
||||
style = 'notched_slider',
|
||||
minimum_value = 0.00,
|
||||
maximum_value = 1.00,
|
||||
value_step = 0.05,
|
||||
},
|
||||
format = '%.2f',
|
||||
value = evolution.destroy_factor * 100,
|
||||
tooltip = 'Current value, x100',
|
||||
})
|
||||
make_slider(row_3, {
|
||||
button = {
|
||||
type = 'button',
|
||||
name = on_evolution_time_factor,
|
||||
caption = 'Time factor'
|
||||
},
|
||||
slider = {
|
||||
type = 'slider',
|
||||
minimum_value = 0.000,
|
||||
maximum_value = 0.100,
|
||||
value_step = 0.002,
|
||||
},
|
||||
format = '%.3f',
|
||||
value = evolution.time_factor * 1000,
|
||||
tooltip = 'Current value, x1000',
|
||||
})
|
||||
|
||||
local row_4 = canvas.add { type = 'frame', style = 'bordered_frame', direction = 'vertical', caption = 'Exploration' }
|
||||
make_slider(row_4, {
|
||||
button = {
|
||||
type = 'button',
|
||||
name = on_map_chart,
|
||||
caption = 'Chart map'
|
||||
},
|
||||
slider = {
|
||||
type = 'slider',
|
||||
minimum_value = 1,
|
||||
maximum_value = 5000,
|
||||
value_step = 1,
|
||||
},
|
||||
format = '%d',
|
||||
value = 0,
|
||||
})
|
||||
local table_4 = row_4.add { type = 'table', column_count = 3 }
|
||||
for _, button in pairs({
|
||||
{ name = on_map_hide, caption = 'Hide all' },
|
||||
{ name = on_map_reveal, caption = 'Reveal all' },
|
||||
{ name = on_map_rechart, caption = 'Re-chart all' },
|
||||
}) do make_button(table_4, button) end
|
||||
end
|
||||
|
||||
Gui.on_click(main_button_name, function(event)
|
||||
local player = event.player
|
||||
local element = event.element
|
||||
if element.toggled then
|
||||
AdminPanel.close_all_pages(player)
|
||||
event.element.toggled = true
|
||||
draw_gui(player)
|
||||
else
|
||||
Gui.clear(AdminPanel.get_canvas(player))
|
||||
end
|
||||
end)
|
||||
|
||||
Event.add(defines.events.on_gui_value_changed, function(event)
|
||||
local element = event.element
|
||||
if not (element and element.valid) then
|
||||
return
|
||||
end
|
||||
|
||||
local tag = element.tags and element.tags.name
|
||||
if not tag or tag ~= slider_tag_name then
|
||||
return
|
||||
end
|
||||
|
||||
local data = Gui.get_data(element)
|
||||
data.slider.tooltip = string.format(data.format, data.slider.slider_value)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_performance_speed, function(event)
|
||||
local element = event.element
|
||||
local value = update_slider(element)
|
||||
Surface.performance_scale_set(value)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_slow_down, function(event)
|
||||
local element = event.element
|
||||
local value = update_slider(element)
|
||||
game.speed = value
|
||||
game.print(string.format('Game speed: %.2f', game.speed))
|
||||
end)
|
||||
|
||||
Gui.on_click(on_speed_up, function(event)
|
||||
local element = event.element
|
||||
local value = update_slider(element)
|
||||
game.speed = value
|
||||
game.print(string.format('Game speed: %.2f', game.speed))
|
||||
end)
|
||||
|
||||
Gui.on_click(on_pollution_ageing, function(event)
|
||||
local element = event.element
|
||||
local value = update_slider(element)
|
||||
game.map_settings.pollution.ageing = value
|
||||
end)
|
||||
|
||||
Gui.on_click(on_pollution_diffusion, function(event)
|
||||
local element = event.element
|
||||
local value = update_slider(element)
|
||||
game.map_settings.pollution.diffusion_ratio = value
|
||||
end)
|
||||
|
||||
Gui.on_click(on_pollution_attack_modifier, function(event)
|
||||
local element = event.element
|
||||
local value = update_slider(element)
|
||||
game.map_settings.pollution.enemy_attack_pollution_consumption_modifier = value
|
||||
end)
|
||||
|
||||
Gui.on_click(on_evolution_value, function(event)
|
||||
local element = event.element
|
||||
local value = update_slider(element)
|
||||
game.forces.enemy.evolution_factor = value / 100
|
||||
end)
|
||||
|
||||
Gui.on_click(on_evolution_destroy_factor, function(event)
|
||||
local element = event.element
|
||||
local value = update_slider(element)
|
||||
game.map_settings.enemy_evolution.destroy_factor = value / 100
|
||||
end)
|
||||
|
||||
Gui.on_click(on_evolution_time_factor, function(event)
|
||||
local element = event.element
|
||||
local value = update_slider(element)
|
||||
game.map_settings.enemy_evolution.time_factor = value / 1000
|
||||
end)
|
||||
|
||||
Gui.on_click(on_map_chart, function(event)
|
||||
local element = event.element
|
||||
local player = event.player
|
||||
local value = update_slider(element)
|
||||
Surface.chart_map(player, value)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_map_hide, function(event)
|
||||
local player = event.player
|
||||
Surface.hide_all(player)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_map_reveal, function(event)
|
||||
local player = event.player
|
||||
Surface.reveal_all(player)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_map_rechart, function(event)
|
||||
local player = event.player
|
||||
Surface.rechart_all(player)
|
||||
end)
|
323
features/gui/admin_panel/player_manager.lua
Normal file
323
features/gui/admin_panel/player_manager.lua
Normal file
@ -0,0 +1,323 @@
|
||||
local Actions = require 'features.gui.admin_panel.functions'.actions
|
||||
local AdminPanel = require 'features.gui.admin_panel.core'
|
||||
local Global = require 'utils.global'
|
||||
local Gui = require 'utils.gui'
|
||||
local Table = require 'utils.table'
|
||||
|
||||
local main_button_name = Gui.uid_name()
|
||||
local selection_switch_name = Gui.uid_name()
|
||||
local selection_dropdown_name = Gui.uid_name()
|
||||
|
||||
local on_cheat_mode = Gui.uid_name()
|
||||
local on_show_reports = Gui.uid_name()
|
||||
local on_create_pool = Gui.uid_name()
|
||||
local on_revive_ghosts = Gui.uid_name()
|
||||
local on_save_game = Gui.uid_name()
|
||||
local on_delete_blueprints = Gui.uid_name()
|
||||
local on_destroy_speakers = Gui.uid_name()
|
||||
local on_remove_biters = Gui.uid_name()
|
||||
local on_remove_enemies = Gui.uid_name()
|
||||
local on_add_regular = Gui.uid_name()
|
||||
local on_add_probation = Gui.uid_name()
|
||||
local on_jail_player = Gui.uid_name()
|
||||
local on_remove_regular = Gui.uid_name()
|
||||
local on_remove_probation = Gui.uid_name()
|
||||
local on_unjail_player = Gui.uid_name()
|
||||
local on_invoke_player = Gui.uid_name()
|
||||
local on_goto_player = Gui.uid_name()
|
||||
local on_spank_player = Gui.uid_name()
|
||||
local on_ban_player = Gui.uid_name()
|
||||
-- local on_teleport = Gui.uid_name()
|
||||
-- local on_destroy_selected = Gui.uid_name()
|
||||
|
||||
local this = {
|
||||
---@type table<number, table< index: number, name: string >>
|
||||
player_selection = {},
|
||||
---@type table<number, string>
|
||||
selection_switch = {},
|
||||
---@type table<number, table<string>>
|
||||
player_ban_items = {},
|
||||
}
|
||||
|
||||
Global.register(this, function(tbl) this = tbl end)
|
||||
|
||||
local pages = AdminPanel.get_pages()
|
||||
pages[#pages +1] = {
|
||||
type = 'sprite-button',
|
||||
sprite = 'entity/character',
|
||||
tooltip = '[font=default-bold]Player manager[/font]',
|
||||
name = main_button_name,
|
||||
auto_toggle = true,
|
||||
}
|
||||
|
||||
local ban_items = {}
|
||||
for _, text in pairs({
|
||||
'damaging base',
|
||||
'griefing',
|
||||
'insulting other players',
|
||||
'mass deconstruction',
|
||||
'offensive language',
|
||||
'resource hoarding',
|
||||
'tanking server UPS',
|
||||
'toxic behavior',
|
||||
}) do table.insert(ban_items, { name = Gui.uid_name(), caption = text }) end
|
||||
|
||||
local function get_selected_player(player)
|
||||
return this.player_selection[player.index].name or '__NIL__'
|
||||
end
|
||||
|
||||
local function get_player_list(player_index)
|
||||
local player_list = { '-- ▼ -- select player -- ▼ --' }
|
||||
local mode = this.selection_switch[player_index] or 'none'
|
||||
if mode == 'none' then -- all
|
||||
for _, p in pairs(game.players) do
|
||||
player_list[#player_list +1] = p.name
|
||||
end
|
||||
elseif mode == 'left' then --- online
|
||||
for _, p in pairs(game.connected_players) do
|
||||
player_list[#player_list +1] = p.name
|
||||
end
|
||||
elseif mode == 'right' then -- offline
|
||||
for _, p in pairs(game.players) do
|
||||
if not p.connected then
|
||||
player_list[#player_list +1] = p.name
|
||||
end
|
||||
end
|
||||
end
|
||||
return player_list
|
||||
end
|
||||
|
||||
local function generate_ban_text(player)
|
||||
local items = this.player_ban_items[player.index]
|
||||
return table.concat(items, ', ') .. '. To appeal ban visit redmew.com/discord #helpdesk.'
|
||||
end
|
||||
|
||||
local function make_button(parent, params)
|
||||
local button = parent.add {
|
||||
type = 'button',
|
||||
caption = params.caption,
|
||||
name = params.name,
|
||||
tooltip = params.tooltip,
|
||||
}
|
||||
Gui.set_style(button, {
|
||||
horizontally_stretchable = true,
|
||||
})
|
||||
return button
|
||||
end
|
||||
|
||||
local function make_checkbox(parent, params)
|
||||
local checkbox = parent.add {
|
||||
type = 'checkbox',
|
||||
caption = params.caption,
|
||||
name = params.name,
|
||||
tooltip = params.tooltip,
|
||||
state = params.state or false,
|
||||
}
|
||||
Gui.set_style(checkbox, {
|
||||
horizontally_stretchable = true,
|
||||
})
|
||||
return checkbox
|
||||
end
|
||||
|
||||
local function make_player_dropdown(parent)
|
||||
local player_index = parent.player_index
|
||||
local player_list = get_player_list(player_index)
|
||||
local selection_data = this.player_selection[player_index]
|
||||
if selection_data.index > #player_list then
|
||||
selection_data.index = 1
|
||||
end
|
||||
selection_data.name = player_list[selection_data.index]
|
||||
|
||||
local selection_flow = parent.add { type = 'flow', direction = 'horizontal' }
|
||||
Gui.set_style(selection_flow, { vertical_align = 'center' })
|
||||
|
||||
selection_flow.add { type = 'label', caption = '[font=default-small][color=255,230,192]ONLINE[/color][/font]' }
|
||||
selection_flow.add { type = 'switch', name = selection_switch_name, switch_state = this.selection_switch[player_index], allow_none_state = true }
|
||||
selection_flow.add { type = 'label', caption = '[font=default-small][color=255,230,192]OFFLINE[/color][/font]' }
|
||||
|
||||
local dropdown = selection_flow.add { type = 'drop-down', name = selection_dropdown_name, selected_index = selection_data.index, items = player_list }
|
||||
Gui.set_style(dropdown, { horizontally_stretchable = true })
|
||||
return selection_flow
|
||||
end
|
||||
|
||||
local function draw_gui(player)
|
||||
local canvas = AdminPanel.get_canvas(player)
|
||||
Gui.clear(canvas)
|
||||
|
||||
this.player_selection[player.index] = this.player_selection[player.index] or { index = 1 }
|
||||
this.selection_switch[player.index] = this.selection_switch[player.index] or 'none'
|
||||
this.player_ban_items[player.index] = this.player_ban_items[player.index] or {}
|
||||
|
||||
local row_1 = canvas.add { type = 'frame', style = 'bordered_frame', direction = 'vertical', caption = 'General actions' }
|
||||
local table_1 = row_1.add { type = 'table', column_count = 3 }
|
||||
for _, button in pairs({
|
||||
{ name = on_cheat_mode, caption = 'Cheat mode' },
|
||||
{ name = on_show_reports, caption = 'Show reports' },
|
||||
{ name = on_create_pool, caption = 'Create pool' },
|
||||
{ name = on_revive_ghosts, caption = 'Revive ghosts' },
|
||||
{ name = on_save_game, caption = 'Save game' },
|
||||
{ name = on_delete_blueprints, caption = 'Destroy ghost entities' },
|
||||
{ name = on_destroy_speakers, caption = 'Destroy speakers' },
|
||||
{ name = on_remove_biters, caption = 'Remove biters' },
|
||||
{ name = on_remove_enemies, caption = 'Remove all enemies' },
|
||||
-- { name = on_teleport, caption = 'Teleport' },
|
||||
-- { name = on_destroy_selected, caption = 'Destroy selected' }
|
||||
}) do make_button(table_1, button) end
|
||||
|
||||
local row_2 = canvas.add { type = 'frame', style = 'bordered_frame', direction = 'vertical', caption = 'Players management' }
|
||||
local table_2 = row_2.add { type = 'table', column_count = 3 }
|
||||
for _, button in pairs({
|
||||
{ name = on_add_regular, caption = 'Add regular' },
|
||||
{ name = on_add_probation, caption = 'Add probation' },
|
||||
{ name = on_jail_player, caption = 'Jail player' },
|
||||
{ name = on_remove_regular, caption = 'Remove regular' },
|
||||
{ name = on_remove_probation, caption = 'Remove probation' },
|
||||
{ name = on_unjail_player, caption = 'Unjail player' },
|
||||
{ name = on_invoke_player, caption = 'Invoke player' },
|
||||
{ name = on_goto_player, caption = 'Goto player' },
|
||||
{ name = on_spank_player, caption = 'Spank player' },
|
||||
}) do make_button(table_2, button) end
|
||||
make_player_dropdown(row_2)
|
||||
|
||||
local row_3 = canvas.add { type = 'frame', style = 'bordered_frame', direction = 'vertical', caption = 'Players ban' }
|
||||
local table_3 = row_3.add { type = 'table', column_count = 2 }
|
||||
for _, item in pairs(ban_items) do
|
||||
make_checkbox(table_3, {
|
||||
caption = item.caption,
|
||||
name = item.name,
|
||||
state = Table.contains(this.player_ban_items[player.index], item.caption),
|
||||
})
|
||||
end
|
||||
make_player_dropdown(row_3)
|
||||
|
||||
local textbox = row_3.add { type = 'text-box', text = generate_ban_text(player) }
|
||||
Gui.set_style(textbox, { minimal_width = 460, maximal_width = 460, minimal_height = 72, horizontally_stretchable = true, vertically_stretchable = true })
|
||||
textbox.word_wrap = true
|
||||
textbox.clear_and_focus_on_right_click = true
|
||||
|
||||
local flow_3 = row_3.add { type = 'flow', direction = 'horizontal' }
|
||||
Gui.add_pusher(flow_3)
|
||||
local ban_button = flow_3.add { type = 'button', name = on_ban_player, style = 'confirm_button', caption = 'Ban player' }
|
||||
Gui.set_data(ban_button, { textbox = textbox })
|
||||
end
|
||||
|
||||
Gui.on_click(main_button_name, function(event)
|
||||
local player = event.player
|
||||
local element = event.element
|
||||
if element.toggled then
|
||||
AdminPanel.close_all_pages(player)
|
||||
event.element.toggled = true
|
||||
draw_gui(player)
|
||||
else
|
||||
Gui.clear(AdminPanel.get_canvas(player))
|
||||
end
|
||||
end)
|
||||
|
||||
Gui.on_switch_state_changed(selection_switch_name, function(event)
|
||||
local player = event.player
|
||||
this.selection_switch[player.index] = event.element.switch_state
|
||||
this.player_selection[player.index].index = 1
|
||||
draw_gui(player)
|
||||
end)
|
||||
|
||||
Gui.on_selection_state_changed(selection_dropdown_name, function(event)
|
||||
local player = event.player
|
||||
local element = event.element
|
||||
this.player_selection[player.index].index = element.selected_index
|
||||
draw_gui(player)
|
||||
end)
|
||||
|
||||
for _, ban_item in pairs(ban_items) do
|
||||
Gui.on_checked_state_changed(ban_item.name, function(event)
|
||||
local player = event.player
|
||||
local element = event.element
|
||||
if element.state then
|
||||
table.insert(this.player_ban_items[player.index], element.caption)
|
||||
else
|
||||
Table.remove_element(this.player_ban_items[player.index], element.caption)
|
||||
end
|
||||
draw_gui(player)
|
||||
end)
|
||||
end
|
||||
|
||||
Gui.on_click(on_ban_player, function(event)
|
||||
local data = Gui.get_data(event.element)
|
||||
local target_name = get_selected_player(event.player)
|
||||
Actions.ban_player(target_name, data.textbox.text, event.player)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_cheat_mode, function(event)
|
||||
Actions.toggle_cheat_mode(nil, event.player)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_show_reports, function(event)
|
||||
Actions.show_reports(nil, event.player)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_create_pool, function(event)
|
||||
Actions.create_pool(nil, event.player)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_revive_ghosts, function(event)
|
||||
Actions.revive_ghosts({ radius = 32 * 10 }, event.player)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_save_game, function(event)
|
||||
Actions.save_game(nil, event.player)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_delete_blueprints, function(event)
|
||||
Actions.remove_all_ghost_entities(event.player)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_destroy_speakers, function(event)
|
||||
Actions.destroy_all_speakers(event.player)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_remove_biters, function(event)
|
||||
Actions.kill_all_enemy_units(event.player)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_remove_enemies, function(event)
|
||||
Actions.kill_all_enemies(event.player)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_add_regular, function(event)
|
||||
local target_name = get_selected_player(event.player)
|
||||
Actions.regular_add({ player = target_name, actor = event.player.name }, event.player)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_add_probation, function(event)
|
||||
local target_name = get_selected_player(event.player)
|
||||
Actions.probation_add({ player = target_name, actor = event.player.name }, event.player)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_jail_player, function(event)
|
||||
local target_name = get_selected_player(event.player)
|
||||
Actions.jail_player({ player = target_name }, event.player)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_remove_regular, function(event)
|
||||
local target_name = get_selected_player(event.player)
|
||||
Actions.regular_remove({ player = target_name, actor = event.player.name }, event.player)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_remove_probation, function(event)
|
||||
local target_name = get_selected_player(event.player)
|
||||
Actions.probation_remove({ player = target_name, actor = event.player.name }, event.player)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_unjail_player, function(event)
|
||||
local target_name = get_selected_player(event.player)
|
||||
Actions.unjail_player({ player = target_name }, event.player)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_spank_player, function(event)
|
||||
local target_name = get_selected_player(event.player)
|
||||
Actions.spank(target_name, event.player)
|
||||
end)
|
||||
|
||||
Gui.on_click(on_invoke_player, function(event)
|
||||
local target_name = get_selected_player(event.player)
|
||||
Actions.invoke_player({ player = target_name }, event.player)
|
||||
end)
|
@ -84,7 +84,7 @@ Command.add(
|
||||
p({'performance.stat_preamble'})
|
||||
p({'performance.generic_stat', {'performance.game_speed'}, format('%.2f', Performance.get_time_scale())})
|
||||
local stat_string = format('%.2f', stat_mod)
|
||||
p({'performance.output_formatter', {'performance.game_speed'}, stat_string, {'performance.manual_mining_speed'}, stat_string, {'performance.manual_crafting_speed'}, stat_string})
|
||||
p({'performance.output_formatter', {'performance.running_speed'}, stat_string, {'performance.manual_mining_speed'}, stat_string, {'performance.manual_crafting_speed'}, stat_string})
|
||||
end
|
||||
)
|
||||
|
||||
@ -98,7 +98,7 @@ Command.add(
|
||||
local stat_mod = Performance.get_player_stat_modifier()
|
||||
p({'performance.generic_stat', {'performance.game_speed'}, format('%.2f', Performance.get_time_scale())})
|
||||
local stat_string = format('%.2f', stat_mod)
|
||||
p({'performance.output_formatter', {'performance.game_speed'}, stat_string, {'performance.manual_mining_speed'}, stat_string, {'performance.manual_crafting_speed'}, stat_string})
|
||||
p({'performance.output_formatter', {'performance.running_speed'}, stat_string, {'performance.manual_mining_speed'}, stat_string, {'performance.manual_crafting_speed'}, stat_string})
|
||||
end
|
||||
)
|
||||
|
||||
|
@ -47,12 +47,12 @@ local function report_command(args, player)
|
||||
local reported_player = game.get_player(reported_player_name)
|
||||
|
||||
if not reported_player then
|
||||
Game.player_print(reported_player_name .. ' does not exist.')
|
||||
Game.player_print(reported_player_name .. ' does not exist.', Color.fail, player)
|
||||
return nil
|
||||
end
|
||||
|
||||
Module.report(player, reported_player, args.message)
|
||||
Game.player_print('Your report has been sent.')
|
||||
Game.player_print('Your report has been sent.', Color.success, player)
|
||||
end
|
||||
|
||||
local function draw_report(parent, report_id)
|
||||
@ -380,7 +380,7 @@ function Module.unjail(target_player, player)
|
||||
local permissions = game.permissions
|
||||
local jail_permission_group = permissions.get_group(jail_name)
|
||||
if (not jail_permission_group) or target_player.permission_group ~= jail_permission_group or not target_jail_data then
|
||||
Game.player_print(format('%s is already not in Jail.', target_name))
|
||||
Game.player_print(format('%s is already not in Jail.', target_name), Color.warning, player)
|
||||
return
|
||||
end
|
||||
|
||||
@ -416,7 +416,7 @@ function Module.unjail(target_player, player)
|
||||
-- Check that it worked
|
||||
if target_player.permission_group == permission_group then
|
||||
-- Let admin know it worked, let target know what's going on.
|
||||
Game.player_print(target_name .. ' has been returned to the default group. They have been advised of this.')
|
||||
Game.player_print(target_name .. ' has been returned to the default group. They have been advised of this.', Color.success, player)
|
||||
target_player.print(prefix)
|
||||
target_player.print('Your ability to perform actions has been restored', Color.light_green)
|
||||
target_player.print(prefix_e)
|
||||
@ -426,14 +426,15 @@ function Module.unjail(target_player, player)
|
||||
-- Let admin know it didn't work.
|
||||
Game.player_print(format(
|
||||
'Something went wrong in the unjailing of %s. You can still change their group via /permissions and inform them.',
|
||||
target_name))
|
||||
target_name), Color.fail, player)
|
||||
end
|
||||
end
|
||||
|
||||
--- Bans the player and reports the ban to moderation log channel.
|
||||
-- @param player<LuaPlayer>
|
||||
-- @param reason<string?> defaults to empty string.
|
||||
function Module.ban_player(player, reason)
|
||||
-- @param player <LuaPlayer>
|
||||
-- @param reason <string?> defaults to empty string.
|
||||
-- @param actor <LuaPlayer?> the player performing the ban action, if any
|
||||
function Module.ban_player(player, reason, actor)
|
||||
if not player or not player.valid then
|
||||
return
|
||||
end
|
||||
@ -448,10 +449,16 @@ function Module.ban_player(player, reason)
|
||||
|
||||
local server_id = Server.get_server_id()
|
||||
local server_name = Server.get_server_name()
|
||||
local actor_name = '<script>'
|
||||
if actor and actor.valid then
|
||||
actor_name = actor.name
|
||||
end
|
||||
|
||||
Server.report_ban(player.name, actor_name, reason)
|
||||
|
||||
local text = {'**'}
|
||||
text[#text + 1] = Utils.sanitise_string_for_discord(player.name)
|
||||
text[#text + 1] = ' was banned by <script>**\\n'
|
||||
text[#text + 1] = ' was banned by ' .. actor_name .. '**\\n'
|
||||
|
||||
if server_id ~= '' then
|
||||
text[#text + 1] = 'Server: s'
|
||||
@ -476,7 +483,8 @@ end
|
||||
--- kicks the player and reports the kick to moderation log channel.
|
||||
-- @param player<LuaPlayer>
|
||||
-- @param reason<string?> defaults to empty string.
|
||||
function Module.kick_player(player, reason)
|
||||
-- @param actor <LuaPlayer?> the player performing the kick action, if any
|
||||
function Module.kick_player(player, reason, actor)
|
||||
if not player or not player.valid then
|
||||
return
|
||||
end
|
||||
@ -491,10 +499,14 @@ function Module.kick_player(player, reason)
|
||||
|
||||
local server_id = Server.get_server_id()
|
||||
local server_name = Server.get_server_name()
|
||||
local actor_name = '<script>'
|
||||
if actor and actor.valid then
|
||||
actor_name = actor.name
|
||||
end
|
||||
|
||||
local text = {'**'}
|
||||
text[#text + 1] = Utils.sanitise_string_for_discord(player.name)
|
||||
text[#text + 1] = ' was kicked by <script>**\\n'
|
||||
text[#text + 1] = ' was kicked by ' .. actor_name .. '**\\n'
|
||||
|
||||
if server_id ~= '' then
|
||||
text[#text + 1] = 'Server: s'
|
||||
|
@ -55,6 +55,7 @@ local data_tracked_tag = '[DATA-TRACKED]'
|
||||
local query_players_tag = '[QUERY-PLAYERS]'
|
||||
local player_join_tag = '[PLAYER-JOIN]'
|
||||
local player_leave_tag = '[PLAYER-LEAVE]'
|
||||
local player_banned_tag = '[BAN]'
|
||||
|
||||
Public.raw_print = raw_print
|
||||
|
||||
@ -180,6 +181,17 @@ function Public.to_discord_named_embed_raw(channel_name, message)
|
||||
raw_print(concat({discord_named_embed_raw_tag, channel_name, ' ', message}))
|
||||
end
|
||||
|
||||
--- Tells the server that a ban has happend, this will overwrite any existing bans.
|
||||
-- The purpose is that game.ban doesn't report the admin so we use this function to fill that in.
|
||||
-- @param player_name<string> the player to ban.
|
||||
-- @param admin_name<string> the admin that did the ban.
|
||||
-- @param reason<string> the optional reason for the ban.
|
||||
function Public.report_ban(player_name, admin_name, reason)
|
||||
assert_non_empty_string_and_no_spaces(player_name, 'player_name')
|
||||
assert_non_empty_string_and_no_spaces(admin_name, 'admin_name')
|
||||
raw_print(concat({player_banned_tag, ' ', player_name, ' was banned by ', admin_name, '. Reason: ', reason}))
|
||||
end
|
||||
|
||||
--- Stops and saves the factorio server and starts the named scenario.
|
||||
-- @param scenario_name<string> The name of the scenario as appears in the scenario table on http://redmew.com/admin
|
||||
-- @usage
|
||||
|
@ -31,6 +31,8 @@ tp_mode_off=tp mode is now off
|
||||
tp_mode_on=tp mode is now on - place a ghost entity to teleport there.
|
||||
destroy_success=__1__ destroyed
|
||||
destroy_fail=Nothing found to destroy. (You must have an entity under your cursor when you hit enter)
|
||||
revive_ghosts=Revived __1__ ghost(s).
|
||||
create_pool=Ready to swim!
|
||||
|
||||
[redmew_commands]
|
||||
kill_fail_suicide_no_character=Sorry, you don't have a character to kill.
|
||||
|
@ -133,3 +133,6 @@ battery_charge_caption=Battery recharge
|
||||
battery_charge_tooltip=[font=default-bold]Battery recharge[/font] - Recharge battery equipments in your armor from nearby accumulators.\nThey must have at least 3MJ of energy stored.
|
||||
auto_stash_caption=Auto stash
|
||||
auto_stash_tooltip=[font=default-bold]Auto stash[/font] - Sort your inventory into nearby chests.\n[color=yellow][font=default-bold]LMB[/font][/color]: Everything, excluding quickbar items.\n[color=yellow][font=default-bold]RMB[/font][/color]: Only ores to nearby chests, excluding quickbar items.\n[color=yellow][font=default-bold]CTRL + RMB[/font][/color]: Fill nearby furnaces.\n[color=yellow][font=default-bold]SHIFT + LMB[/font][/color]: Everything onto filtered slots to wagon/chests.\n[color=yellow][font=default-bold]SHIFT + RMB[/font][/color]: Only ores to wagon.
|
||||
|
||||
[admin_panel]
|
||||
info_tooltip=[font=default-bold]Admin panel[/font] - Toggle your admin panel
|
@ -30,10 +30,11 @@ end
|
||||
--- Prints to player or console.
|
||||
-- @param msg <string|table> table if locale is used
|
||||
-- @param color <table> defaults to white
|
||||
function Game.player_print(msg, color)
|
||||
-- @param player <LuaPlayer?>
|
||||
function Game.player_print(msg, color, player)
|
||||
color = color or Color.white
|
||||
local player = game.player
|
||||
if player then
|
||||
player = player or game.player
|
||||
if player and player.valid then
|
||||
player.print(msg, color)
|
||||
else
|
||||
print(msg)
|
||||
|
@ -304,6 +304,12 @@ Gui.on_text_changed = handler_factory(defines.events.on_gui_text_changed)
|
||||
-- Adds a player field to the event table.
|
||||
Gui.on_value_changed = handler_factory(defines.events.on_gui_value_changed)
|
||||
|
||||
-- Register a handler for the on_gui_switch_state_changed event for LuaGuiElements with element_name.
|
||||
-- Can only have one handler per element name.
|
||||
-- Guarantees that the element and the player are valid when calling the handler.
|
||||
-- Adds a player field to the event table.
|
||||
Gui.on_switch_state_changed = handler_factory(defines.events.on_gui_switch_state_changed)
|
||||
|
||||
-- Register a handler for when the player shows the top LuaGuiElements with element_name.
|
||||
-- Assuming the element_name has been added with Gui.allow_player_to_toggle_top_element_visibility.
|
||||
-- Can only have one handler per element name.
|
||||
|
@ -7,8 +7,8 @@ Declare.module({'utils', 'Gui'}, function()
|
||||
Declare.module('can toggle top buttons', function()
|
||||
local function count_gui_elements(player)
|
||||
-- local gui = player.gui
|
||||
-- return #gui.top.children + #gui.left.children + #gui.center.children
|
||||
return #Gui.get_top_flow(player).children + #Gui.get_left_flow(player).children + #player.gui.center.children
|
||||
-- return #gui.top.children + #gui.left.children + #gui.center.children + #gui.screen.children
|
||||
return #Gui.get_top_flow(player).children + #Gui.get_left_flow(player).children + #player.gui.center.children + #player.gui.screen.children
|
||||
end
|
||||
|
||||
local function is_ignored_element(element)
|
||||
|
Loading…
Reference in New Issue
Block a user