mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-27 03:25:23 +09:00
Migrate all commands to new lib
This commit is contained in:
@@ -1,15 +1,19 @@
|
||||
--[[-- Command Authorities - Roles
|
||||
Adds a permission authority for exp roles
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local add, allow, deny = Commands.add_permission_authority, Commands.status.success, Commands.status.unauthorised
|
||||
|
||||
local Roles = require("modules/exp_legacy/expcore/roles")
|
||||
local player_allowed = Roles.player_allowed
|
||||
|
||||
local authorities = {}
|
||||
|
||||
--- If a command has the flag "character_only" then the command can only be used outside of remote view
|
||||
authorities.exp_permission =
|
||||
add(function(player, command)
|
||||
if not Roles.player_allowed(player, command.flags.exp_permission or ("command/" .. command)) then
|
||||
if not player_allowed(player, command.flags.exp_permission or ("command/" .. command)) then
|
||||
return deny{ "exp-commands-authorities_role.deny" }
|
||||
else
|
||||
return allow()
|
||||
12
exp_scenario/module/commands/_rcon.lua
Normal file
12
exp_scenario/module/commands/_rcon.lua
Normal file
@@ -0,0 +1,12 @@
|
||||
--[[-- Command Rcon - ExpCore
|
||||
Adds rcon interfaces for the legacy exp core
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local add_static, add_dynamic = Commands.add_rcon_static, Commands.add_rcon_dynamic
|
||||
|
||||
add_static("Group", require("modules.exp_legacy.expcore.permission_groups"))
|
||||
add_static("Roles", require("modules.exp_legacy.expcore.roles"))
|
||||
add_static("Gui", require("modules.exp_legacy.expcore.gui"))
|
||||
add_static("Datastore", require("modules.exp_legacy.expcore.datastore"))
|
||||
add_static("External", require("modules.exp_legacy.expcore.external"))
|
||||
@@ -16,20 +16,13 @@ local valid, invalid = Commands.status.success, Commands.status.invalid_input
|
||||
|
||||
local Roles = require("modules.exp_legacy.expcore.roles")
|
||||
local highest_role = Roles.get_player_highest_role
|
||||
local key_of_roles = Commands.types.key_of(Roles.config.roles)
|
||||
|
||||
local types = {}
|
||||
local types = {} --- @class Commands._types
|
||||
|
||||
--- A role defined by exp roles
|
||||
--- @type Commands.InputParser
|
||||
types.role =
|
||||
add("role", function(input, player)
|
||||
local _, status, rtn = parse(input, player, key_of_roles)
|
||||
return status, rtn
|
||||
end)
|
||||
types.role = add("role", Commands.types.key_of(Roles.config.roles))
|
||||
|
||||
--- A role which is lower than the players highest role
|
||||
--- @type Commands.InputParser
|
||||
types.lower_role =
|
||||
add("lower_role", function(input, player)
|
||||
local success, status, result = parse(input, player, types.role)
|
||||
@@ -45,7 +38,6 @@ types.lower_role =
|
||||
end)
|
||||
|
||||
--- A player who is of a lower role than the executing player
|
||||
--- @type Commands.InputParser
|
||||
types.lower_role_player =
|
||||
add("lower_role_player", function(input, player)
|
||||
local success, status, result = parse(input, player, Commands.types.player)
|
||||
@@ -62,9 +54,8 @@ types.lower_role_player =
|
||||
end)
|
||||
|
||||
--- A player who is of a lower role than the executing player
|
||||
--- @type Commands.InputParser
|
||||
types.lower_role_player_online =
|
||||
add("lower_role_player", function(input, player)
|
||||
add("lower_role_player_online", function(input, player)
|
||||
local success, status, result = parse(input, player, Commands.types.player_online)
|
||||
if not success then return status, result end
|
||||
--- @cast result LuaPlayer
|
||||
@@ -80,7 +71,7 @@ types.lower_role_player_online =
|
||||
|
||||
--- A player who is of a lower role than the executing player
|
||||
types.lower_role_player_alive =
|
||||
add("lower_role_player", function(input, player)
|
||||
add("lower_role_player_alive", function(input, player)
|
||||
local success, status, result = parse(input, player, Commands.types.player_alive)
|
||||
if not success then return status, result end
|
||||
--- @cast result LuaPlayer
|
||||
22
exp_scenario/module/commands/admin_chat.lua
Normal file
22
exp_scenario/module/commands/admin_chat.lua
Normal file
@@ -0,0 +1,22 @@
|
||||
--[[-- Commands - Admin Chat
|
||||
Adds a command that allows admins to talk in a private chat
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local format_player_name = Commands.format_player_name_locale
|
||||
|
||||
--- Sends a message in chat that only admins can see
|
||||
Commands.new("admin-chat", { "exp-commands_admin-chat.description" })
|
||||
:argument("message", { "exp-commands_admin-chat.arg-message" }, Commands.types.string)
|
||||
:enable_auto_concatenation()
|
||||
:add_aliases{ "ac" }
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player, message)
|
||||
--- @cast message string
|
||||
local player_name = format_player_name(player)
|
||||
for _, next_player in ipairs(game.connected_players) do
|
||||
if next_player.admin then
|
||||
next_player.print{ "exp-commands_admin-chat.format", player_name, message }
|
||||
end
|
||||
end
|
||||
end)
|
||||
96
exp_scenario/module/commands/artillery.lua
Normal file
96
exp_scenario/module/commands/artillery.lua
Normal file
@@ -0,0 +1,96 @@
|
||||
--[[-- Commands - Artillery
|
||||
Adds a command that helps shoot artillery
|
||||
]]
|
||||
|
||||
local AABB = require("modules/exp_util/aabb")
|
||||
local Commands = require("modules/exp_commands")
|
||||
local Selection = require("modules.exp_legacy.modules.control.selection") --- @dep modules.control.selection
|
||||
local SelectionName = "ExpCommand_Artillery"
|
||||
|
||||
local floor = math.floor
|
||||
local abs = math.abs
|
||||
|
||||
--- @param player LuaPlayer
|
||||
--- @param area BoundingBox
|
||||
--- @return boolean
|
||||
local function location_break(player, area)
|
||||
local surface = player.surface -- Allow remote view
|
||||
local is_charted = player.force.is_chunk_charted
|
||||
if is_charted(surface, { x = floor(area.left_top.x / 32), y = floor(area.left_top.y / 32) }) then
|
||||
return true
|
||||
elseif is_charted(surface, { x = floor(area.left_top.x / 32), y = floor(area.right_bottom.y / 32) }) then
|
||||
return true
|
||||
elseif is_charted(surface, { x = floor(area.right_bottom.x / 32), y = floor(area.left_top.y / 32) }) then
|
||||
return true
|
||||
elseif is_charted(surface, { x = floor(area.right_bottom.x / 32), y = floor(area.right_bottom.y / 32) }) then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
--- Toggle player selection mode for artillery
|
||||
Commands.new("artillery", { "exp-commands_artillery.description" })
|
||||
:register(function(player)
|
||||
if Selection.is_selecting(player, SelectionName) then
|
||||
Selection.stop(player)
|
||||
return Commands.status.success{ "exp-commands_artillery.exit" }
|
||||
else
|
||||
Selection.start(player, SelectionName)
|
||||
return Commands.status.success{ "exp-commands_artillery.enter" }
|
||||
end
|
||||
end)
|
||||
|
||||
--- when an area is selected to add protection to the area
|
||||
Selection.on_selection(SelectionName, function(event)
|
||||
--- @cast event EventData.on_player_selected_area
|
||||
local area = AABB.expand(event.area)
|
||||
local player = game.players[event.player_index]
|
||||
local surface = event.surface
|
||||
|
||||
if not (player.cheat_mode or location_break(player, event.area)) then
|
||||
player.print{ "exp-commands_artillery.invalid_area" }
|
||||
return
|
||||
end
|
||||
|
||||
local entities = surface.find_entities_filtered{
|
||||
area = area,
|
||||
type = { "unit-spawner", "turret" },
|
||||
force = "enemy"
|
||||
}
|
||||
|
||||
local count = 0
|
||||
local hits = {} --- @type MapPosition[]
|
||||
for _, entity in ipairs(entities) do
|
||||
local skip = false
|
||||
|
||||
for _, pos in ipairs(hits) do
|
||||
local x = abs(entity.position.x - pos.x)
|
||||
local y = abs(entity.position.y - pos.y)
|
||||
if x * x + y * y < 36 then
|
||||
skip = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not skip then
|
||||
surface.create_entity{
|
||||
name = "artillery-flare",
|
||||
position = entity.position,
|
||||
force = player.force,
|
||||
life_time = 240,
|
||||
movement = { 0, 0 },
|
||||
height = 0,
|
||||
vertical_speed = 0,
|
||||
frame_speed = 0
|
||||
}
|
||||
|
||||
count = count + 1
|
||||
hits[count] = entity.position
|
||||
|
||||
if count > 400 then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
28
exp_scenario/module/commands/bot_queue.lua
Normal file
28
exp_scenario/module/commands/bot_queue.lua
Normal file
@@ -0,0 +1,28 @@
|
||||
--[[-- Commands - Bot queue
|
||||
Adds a command that allows viewing and changing the construction queue limits
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
|
||||
--- Get / Set the current values for the bot queue
|
||||
Commands.new("bot-queue", { "exp-commands_bot-queue.description" })
|
||||
:optional("amount", { "exp-commands_bot-queue.arg-amount" }, Commands.types.integer_range(1, 20))
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player, amount)
|
||||
if amount then
|
||||
player.force.max_successful_attempts_per_tick_per_construction_queue = 3 * amount
|
||||
player.force.max_failed_attempts_per_tick_per_construction_queue = 5 * amount
|
||||
game.print{
|
||||
"exp-commands_bot-queue.set",
|
||||
player.force.max_successful_attempts_per_tick_per_construction_queue,
|
||||
player.force.max_failed_attempts_per_tick_per_construction_queue,
|
||||
}
|
||||
return Commands.status.success()
|
||||
end
|
||||
|
||||
return Commands.status.success{
|
||||
"exp-commands_bot-queue.get",
|
||||
player.force.max_successful_attempts_per_tick_per_construction_queue,
|
||||
player.force.max_failed_attempts_per_tick_per_construction_queue,
|
||||
}
|
||||
end)
|
||||
132
exp_scenario/module/commands/cheat.lua
Normal file
132
exp_scenario/module/commands/cheat.lua
Normal file
@@ -0,0 +1,132 @@
|
||||
--[[-- Commands - Cheats
|
||||
Adds commands for cheating such as unlocking all technology or settings always day
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local format_player_name = Commands.format_player_name_locale
|
||||
|
||||
--- Toggles cheat mode for your player, or another player.
|
||||
Commands.new("set-cheat-mode", { "exp-commands_cheat.description-cheat-mode" })
|
||||
:optional("state", { "exp-commands_cheat.arg-state" }, Commands.types.boolean)
|
||||
:optional("player", { "exp-commands_cheat.arg-player" }, Commands.types.player)
|
||||
:add_aliases{ "cheat-mode", "toggle-cheat-mode" }
|
||||
:add_flags{ "admin_only" }
|
||||
:defaults{
|
||||
player = function(player) return player end,
|
||||
}
|
||||
:register(function(player, state, other_player)
|
||||
--- @cast state boolean?
|
||||
--- @cast player LuaPlayer
|
||||
if state == nil then
|
||||
other_player.cheat_mode = not other_player.cheat_mode
|
||||
else
|
||||
other_player.cheat_mode = state
|
||||
end
|
||||
return Commands.status.success{ "exp-commands_cheat.cheat-mode", other_player.cheat_mode }
|
||||
end)
|
||||
|
||||
--- Toggle always day for your surface, or another
|
||||
Commands.new("set-always-day", { "exp-commands_cheat.description-always-day" })
|
||||
:optional("state", { "exp-commands_cheat.arg-state" }, Commands.types.boolean)
|
||||
:optional("surface", { "exp-commands_cheat.arg-surface" }, Commands.types.surface)
|
||||
:add_aliases{ "always-day", "toggle-always-day" }
|
||||
:add_flags{ "admin_only" }
|
||||
:defaults{
|
||||
surface = function(player) return player.surface end
|
||||
}
|
||||
:register(function(player, state, surface)
|
||||
--- @cast state boolean?
|
||||
--- @cast surface LuaSurface
|
||||
if state == nil then
|
||||
surface.always_day = not surface.always_day
|
||||
else
|
||||
surface.always_day = state
|
||||
end
|
||||
game.print{ "exp-commands_cheat.always-day", format_player_name(player), surface.localised_name, surface.always_day }
|
||||
end)
|
||||
|
||||
--- Toggles friendly fire for your force or another
|
||||
Commands.new("set-friendly-fire", { "exp-commands_cheat.description-friendly-fire" })
|
||||
:optional("state", { "exp-commands_cheat.arg-state" }, Commands.types.boolean)
|
||||
:optional("force", { "exp-commands_cheat.arg-force-friendly-fire" }, Commands.types.force)
|
||||
:add_aliases{ "friendly-fire", "toggle-friendly-fire" }
|
||||
:add_flags{ "admin_only" }
|
||||
:defaults{
|
||||
force = function(player) return player.force end
|
||||
}
|
||||
:register(function(player, state, force)
|
||||
--- @cast state boolean?
|
||||
--- @cast force LuaForce
|
||||
if state == nil then
|
||||
force.friendly_fire = not force.friendly_fire
|
||||
else
|
||||
force.friendly_fire = state
|
||||
end
|
||||
game.print{ "exp-commands_cheat.friendly-fire", format_player_name(player), force.name, force.friendly_fire }
|
||||
end)
|
||||
|
||||
--- Research all technology on your force, or another force.
|
||||
Commands.new("research-all", { "exp-commands_cheat.description-research-all" })
|
||||
:optional("force", { "exp-commands_cheat.arg-force-research" }, Commands.types.force)
|
||||
:add_flags{ "admin_only" }
|
||||
:defaults{
|
||||
force = function(player) return player.force end
|
||||
}
|
||||
:register(function(player, force)
|
||||
--- @cast force LuaForce
|
||||
force.research_all_technologies()
|
||||
game.print{ "exp-commands_cheat.research-all", format_player_name(player), force.name }
|
||||
return Commands.status.success()
|
||||
end)
|
||||
|
||||
--- Clear all pollution from your surface or another
|
||||
Commands.new("clear-pollution", { "exp-commands_cheat.description-clear-pollution" })
|
||||
:optional("surface", { "exp-commands_cheat.arg-surface" }, Commands.types.surface)
|
||||
:add_flags{ "admin_only" }
|
||||
:defaults{
|
||||
surface = function(player) return player.surface end -- Allow remote view
|
||||
}
|
||||
:register(function(player, surface)
|
||||
--- @cast surface LuaSurface
|
||||
surface.clear_pollution()
|
||||
game.print{ "exp-commands_cheat.clear-pollution", format_player_name(player), surface.localised_name }
|
||||
end)
|
||||
|
||||
--- Toggles pollution being enabled in the game
|
||||
Commands.new("set-pollution-enabled", { "exp-commands_cheat.description-pollution-enabled" })
|
||||
:optional("state", { "exp-commands_cheat.arg-state" }, Commands.types.boolean)
|
||||
:add_aliases{ "disable-pollution", "toggle-pollution-enabled" }
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player, state)
|
||||
--- @cast state boolean?
|
||||
if state == nil then
|
||||
game.map_settings.pollution.enabled = not game.map_settings.pollution.enabled
|
||||
else
|
||||
game.map_settings.pollution.enabled = state
|
||||
end
|
||||
|
||||
if game.map_settings.pollution.enabled == false then
|
||||
for _, surface in pairs(game.surfaces) do
|
||||
surface.clear_pollution()
|
||||
end
|
||||
end
|
||||
|
||||
game.print{ "exp-commands_cheat.pollution-enabled", format_player_name(player), game.map_settings.pollution.enabled }
|
||||
end)
|
||||
|
||||
--- Set or get the game speed
|
||||
Commands.new("set-game-speed", { "exp-commands_cheat.description-game-speed" })
|
||||
:optional("amount", { "exp-commands_cheat.arg-amount" }, Commands.types.number_range(0.2, 10))
|
||||
:add_aliases{ "game-speed" }
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player, amount)
|
||||
--- @cast amount number?
|
||||
if amount then
|
||||
game.speed = math.round(amount, 3)
|
||||
local player_name = format_player_name(player)
|
||||
game.print{ "exp-commands_cheat.game-speed-set", player_name, game.speed }
|
||||
return Commands.status.success()
|
||||
else
|
||||
return Commands.status.success{ "exp-commands_cheat.game-speed-get", game.speed }
|
||||
end
|
||||
end)
|
||||
26
exp_scenario/module/commands/clear_inventory.lua
Normal file
26
exp_scenario/module/commands/clear_inventory.lua
Normal file
@@ -0,0 +1,26 @@
|
||||
--[[-- Commands - Clear Inventory
|
||||
Adds a command that allows admins to clear people's inventory
|
||||
]]
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
local transfer_inventory = ExpUtil.transfer_inventory_to_surface
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
|
||||
--- Clears a players inventory
|
||||
Commands.new("clear-inventory", { "exp-commands_clear-inventory.description" })
|
||||
:argument("player", { "exp-commands_clear-inventory.arg-player" }, Commands.types.lower_role_player)
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player, other_player)
|
||||
local inventory = other_player.get_main_inventory()
|
||||
if not inventory then
|
||||
return Commands.status.error{ "expcore-commands.reject-player-alive" }
|
||||
end
|
||||
|
||||
transfer_inventory{
|
||||
inventory = inventory,
|
||||
surface = game.planets.nauvis.surface,
|
||||
name = "iron-chest",
|
||||
allow_creation = true,
|
||||
}
|
||||
end)
|
||||
111
exp_scenario/module/commands/connect.lua
Normal file
111
exp_scenario/module/commands/connect.lua
Normal file
@@ -0,0 +1,111 @@
|
||||
--[[-- Commands - Connect
|
||||
Adds a commands that allows you to request a player move to another server
|
||||
]]
|
||||
|
||||
local Async = require("modules/exp_util/async")
|
||||
local Commands = require("modules/exp_commands")
|
||||
|
||||
local External = require("modules.exp_legacy.expcore.external") --- @dep expcore.external
|
||||
local request_connection_async = Async.register(External.request_connection)
|
||||
|
||||
local concat = table.concat
|
||||
|
||||
--- Convert a server name into a server id, is not an Commands.InputParser because it does not accept addresses
|
||||
--- @param server string
|
||||
--- @return boolean, LocalisedString # True for success
|
||||
local function get_server_id(server)
|
||||
local servers = External.get_servers_filtered(server)
|
||||
local current_server = External.get_current_server()
|
||||
local current_version = current_server.version
|
||||
|
||||
local server_names_before, server_names = {}, {}
|
||||
local server_count_before, server_count = 0, 0
|
||||
for next_server_id, server_details in pairs(servers) do
|
||||
server_count_before = server_count_before + 1
|
||||
server_names_before[server_count_before] = server_details.name
|
||||
if server_details.version == current_version then
|
||||
server_count = server_count + 1
|
||||
server_names[server_count] = server_details.name
|
||||
else
|
||||
servers[next_server_id] = nil
|
||||
end
|
||||
end
|
||||
|
||||
if server_count > 1 then
|
||||
return false, { "exp-commands_connect.too-many-matching", concat(server_names, ", ") }
|
||||
elseif server_count == 1 then
|
||||
local server_id, server_details = next(servers)
|
||||
local status = External.get_server_status(server_id)
|
||||
if server_id == current_server.id then
|
||||
return false, { "exp-commands_connect.same-server", server_details.name }
|
||||
elseif status == "Offline" then
|
||||
return false, { "exp-commands_connect.offline", server_details.name }
|
||||
end
|
||||
return true, server_id
|
||||
elseif server_count_before > 0 then
|
||||
return false, { "exp-commands_connect.wrong-version", concat(server_names_before, ", ") }
|
||||
else
|
||||
return false, { "exp-commands_connect.none-matching" }
|
||||
end
|
||||
end
|
||||
|
||||
--- Connect to a different server
|
||||
Commands.new("connect", { "exp-commands_connect.description" })
|
||||
:argument("server", { "exp-commands_connect.arg-server" }, Commands.types.string)
|
||||
:optional("is-address", { "exp-commands_connect.is-address" }, Commands.types.boolean)
|
||||
:add_aliases{ "join" }
|
||||
:register(function(player, server, is_address)
|
||||
--- @cast server string
|
||||
--- @cast is_address boolean?
|
||||
if not is_address and External.valid() then
|
||||
local success, result = get_server_id(server)
|
||||
if not success then
|
||||
return Commands.status.invalid_input(result)
|
||||
end
|
||||
server = result
|
||||
end
|
||||
|
||||
request_connection_async(player, server, true)
|
||||
end)
|
||||
|
||||
--- Connect another player to a different server
|
||||
Commands.new("connect-player", { "exp-commands_connect.description-player" })
|
||||
:argument("player", { "exp-commands_connect.arg-player" }, Commands.types.player_online)
|
||||
:argument("server", { "exp-commands_connect.arg-server" }, Commands.types.string)
|
||||
:optional("is-address", { "exp-commands_connect.is-address" }, Commands.types.boolean)
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player, other_player, server, is_address)
|
||||
--- @cast other_player LuaPlayer
|
||||
--- @cast server string
|
||||
--- @cast is_address boolean?
|
||||
if not is_address and External.valid() then
|
||||
local success, result = get_server_id(server)
|
||||
if not success then
|
||||
return Commands.status.invalid_input(result)
|
||||
end
|
||||
server = result
|
||||
end
|
||||
|
||||
request_connection_async(other_player, server)
|
||||
end)
|
||||
|
||||
--- Connect all players to a different server
|
||||
Commands.new("connect-all", { "exp-commands_connect.description-all" })
|
||||
:argument("server", { "exp-commands_connect.arg-server" }, Commands.types.string)
|
||||
:optional("is-address", { "exp-commands_connect.is-address" }, Commands.types.boolean)
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player, server, is_address)
|
||||
--- @cast server string
|
||||
--- @cast is_address boolean?
|
||||
if not is_address and External.valid() then
|
||||
local success, result = get_server_id(server)
|
||||
if not success then
|
||||
return Commands.status.invalid_input(result)
|
||||
end
|
||||
server = result
|
||||
end
|
||||
|
||||
for _, next_player in pairs(game.connected_players) do
|
||||
request_connection_async(next_player, server)
|
||||
end
|
||||
end)
|
||||
10
exp_scenario/module/commands/debug.lua
Normal file
10
exp_scenario/module/commands/debug.lua
Normal file
@@ -0,0 +1,10 @@
|
||||
--[[-- Commands - Debug
|
||||
Adds a command that opens the debug frame
|
||||
]]
|
||||
|
||||
local DebugView = require("modules.exp_legacy.modules.gui.debug.main_view") --- @dep modules.gui.debug.main_view
|
||||
local Commands = require("modules/exp_commands")
|
||||
|
||||
--- Opens the debug gui.
|
||||
Commands.new("debug", { "exp-commands_debug.description" })
|
||||
:register(DebugView.open_debug)
|
||||
30
exp_scenario/module/commands/enemy.lua
Normal file
30
exp_scenario/module/commands/enemy.lua
Normal file
@@ -0,0 +1,30 @@
|
||||
--[[-- Commands - Enemy
|
||||
Adds a commands of handling the enemy force, such as killing all or disabling them
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
|
||||
--- Kill all enemies
|
||||
Commands.new("kill-enemies", { "exp-commands_enemy.description-kill" })
|
||||
:add_aliases{ "kill-biters" }
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player)
|
||||
game.forces["enemy"].kill_all_units()
|
||||
game.print{ "exp-commands_enemy.kill", player.name }
|
||||
end)
|
||||
|
||||
--- Remove all enemies on a surface
|
||||
Commands.new("remove-enemies", { "exp-commands_enemy.description-remove" })
|
||||
:optional("surface", { "exp-commands_enemy.arg-surface" }, Commands.types.surface)
|
||||
:add_aliases{ "remove-biters" }
|
||||
:add_flags{ "admin_only" }
|
||||
:defaults{
|
||||
surface = function(player) return player.surface end
|
||||
}
|
||||
:register(function(player, surface)
|
||||
for _, entity in pairs(surface.find_entities_filtered{ force = "enemy" }) do
|
||||
entity.destroy()
|
||||
end
|
||||
-- surface.map_gen_settings.autoplace_controls["enemy-base"].size = "none" -- TODO make this work for SA
|
||||
game.print{ "exp-commands_enemy.remove", player.name }
|
||||
end)
|
||||
116
exp_scenario/module/commands/home.lua
Normal file
116
exp_scenario/module/commands/home.lua
Normal file
@@ -0,0 +1,116 @@
|
||||
--[[-- Commands - Home
|
||||
Adds a command that allows setting and teleporting to your home position
|
||||
]]
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
local teleport = ExpUtil.teleport_player
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local Storage = require("modules/exp_util/storage")
|
||||
|
||||
--- @type table<number, table<number, [MapPosition?, MapPosition?]>>
|
||||
local homes = {} -- homes[player_index][surface_index] = { home_pos, return_pos }
|
||||
Storage.register(homes, function(tbl)
|
||||
homes = tbl
|
||||
end)
|
||||
|
||||
--- Align a position to the grid
|
||||
--- @param position MapPosition The position to align
|
||||
--- @return MapPosition, MapPosition
|
||||
local function align_to_grid(position)
|
||||
return {
|
||||
x = math.floor(position.x) + math.sign(position.x) * 0.5,
|
||||
y = math.floor(position.y) + math.sign(position.x) * 0.5,
|
||||
}, {
|
||||
x = math.floor(position.x),
|
||||
y = math.floor(position.y),
|
||||
}
|
||||
end
|
||||
|
||||
--- Teleports you to your home location on the current surface
|
||||
Commands.new("home", { "exp-commands_home.description-home" })
|
||||
:add_flags{ "character_only" }
|
||||
:register(function(player)
|
||||
local surface = player.surface
|
||||
|
||||
local player_homes = homes[player.index]
|
||||
if not player_homes then
|
||||
return Commands.status.error{ "exp-commands_home.no-home", surface.localised_name }
|
||||
end
|
||||
|
||||
local player_home = player_homes[surface.index]
|
||||
if not player_home or not player_home[1] then
|
||||
return Commands.status.error{ "exp-commands_home.no-home", surface.localised_name }
|
||||
end
|
||||
|
||||
local return_position, floor_position = align_to_grid(player.position)
|
||||
teleport(player, surface, player_home[1])
|
||||
player_home[2] = return_position
|
||||
return Commands.status.success{ "exp-commands_home.return-set", surface.localised_name, floor_position.x, floor_position.y }
|
||||
end)
|
||||
|
||||
--- Teleports you to your previous location on the current surface
|
||||
Commands.new("return", { "exp-commands_home.description-return" })
|
||||
:add_flags{ "character_only" }
|
||||
:register(function(player)
|
||||
local surface = player.surface
|
||||
|
||||
local player_homes = homes[player.index]
|
||||
if not player_homes then
|
||||
return Commands.status.error{ "exp-commands_home.no-return", surface.localised_name }
|
||||
end
|
||||
|
||||
local player_home = player_homes[surface.index]
|
||||
if not player_home or not player_home[2] then
|
||||
return Commands.status.error{ "exp-commands_home.no-return", surface.localised_name }
|
||||
end
|
||||
|
||||
local return_position, floor_position = align_to_grid(player.position)
|
||||
teleport(player, surface, player_home[2])
|
||||
player_home[2] = return_position
|
||||
return Commands.status.success{ "exp-commands_home.return-set", surface.localised_name, floor_position.x, floor_position.y }
|
||||
end)
|
||||
|
||||
--- Sets your home location on your current surface to your current position
|
||||
Commands.new("set-home", { "exp-commands_home.description-set" })
|
||||
:add_flags{ "character_only" }
|
||||
:register(function(player)
|
||||
local home_position, floor_position = align_to_grid(player.position)
|
||||
local surface = player.surface
|
||||
|
||||
local player_homes = homes[player.index]
|
||||
if not player_homes then
|
||||
homes[player.index] = {
|
||||
[surface.index] = { home_position, nil }
|
||||
}
|
||||
return Commands.status.success{ "exp-commands_home.home-set", surface.localised_name, floor_position.x, floor_position.y }
|
||||
end
|
||||
|
||||
local player_home = player_homes[surface.index]
|
||||
if not player_home then
|
||||
player_homes[surface.index] = { home_position, nil }
|
||||
return Commands.status.success{ "exp-commands_home.home-set", surface.localised_name, floor_position.x, floor_position.y }
|
||||
end
|
||||
|
||||
player_home[1] = home_position
|
||||
return Commands.status.success{ "exp-commands_home.home-set", surface.localised_name, floor_position.x, floor_position.y }
|
||||
end)
|
||||
|
||||
--- Gets your home location on your current surface, is allowed in remote view
|
||||
Commands.new("get-home", { "exp-commands_home.description-get" })
|
||||
:register(function(player)
|
||||
local surface = player.surface
|
||||
|
||||
local player_homes = homes[player.index]
|
||||
if not player_homes then
|
||||
return Commands.status.error{ "exp-commands_home.no-home", surface.localised_name }
|
||||
end
|
||||
|
||||
local player_home = player_homes[surface.index]
|
||||
if not player_home or not player_home[1] then
|
||||
return Commands.status.error{ "exp-commands_home.no-home", surface.localised_name }
|
||||
end
|
||||
|
||||
local _, floor_position = align_to_grid(player_home[1])
|
||||
return Commands.status.success{ "exp-commands_home.home-get", surface.localised_name, floor_position.x, floor_position.y }
|
||||
end)
|
||||
43
exp_scenario/module/commands/jail.lua
Normal file
43
exp_scenario/module/commands/jail.lua
Normal file
@@ -0,0 +1,43 @@
|
||||
--[[-- Commands - Jail
|
||||
Adds a commands that allow admins to jail and unjail
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local format_player_name = Commands.format_player_name_locale
|
||||
|
||||
local Jail = require("modules.exp_legacy.modules.control.jail") --- @dep modules.control.jail
|
||||
|
||||
--- Puts a player into jail and removes all other roles.
|
||||
Commands.new("jail", { "exp-commands_jail.description" })
|
||||
:argument("player", { "exp-commands_jail.arg-player" }, Commands.types.lower_role_player)
|
||||
:optional("reason", { "exp-commands_jail.arg-reason" }, Commands.types.string)
|
||||
:enable_auto_concatenation()
|
||||
:register(function(player, other_player, reason)
|
||||
--- @cast other_player LuaPlayer
|
||||
--- @cast reason string?
|
||||
if not reason then
|
||||
reason = "None Given."
|
||||
end
|
||||
|
||||
local player_name = format_player_name(player)
|
||||
local other_player_name = format_player_name(other_player)
|
||||
if Jail.jail_player(other_player, player.name, reason) then
|
||||
game.print{ "exp-commands_jail.jailed", other_player_name, player_name, reason }
|
||||
else
|
||||
return Commands.status.error{ "exp-commands_jail.already-jailed", other_player_name }
|
||||
end
|
||||
end)
|
||||
|
||||
--- Removes a player from jail and restores their old roles.
|
||||
Commands.new("unjail", { "exp-commands_unjail.description" })
|
||||
:argument("player", { "exp-commands_unjail.arg-player" }, Commands.types.lower_role_player)
|
||||
:register(function(player, other_player)
|
||||
--- @cast other_player LuaPlayer
|
||||
local player_name = format_player_name(player)
|
||||
local other_player_name = format_player_name(other_player)
|
||||
if Jail.unjail_player(other_player, player.name) then
|
||||
game.print{ "exp-commands_unjail.unjailed", other_player_name, player_name }
|
||||
else
|
||||
return Commands.status.error{ "exp-commands_unjail.not-jailed", other_player_name }
|
||||
end
|
||||
end)
|
||||
32
exp_scenario/module/commands/kill.lua
Normal file
32
exp_scenario/module/commands/kill.lua
Normal file
@@ -0,0 +1,32 @@
|
||||
--[[-- Commands - Kill
|
||||
Adds a command that allows players to kill themselves and others
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
local highest_role = Roles.get_player_highest_role
|
||||
|
||||
--- Kills yourself or another player.
|
||||
Commands.new("kill", { "exp-commands_kill.description" })
|
||||
:optional("player", { "exp-commands_kill.arg-player" }, Commands.types.lower_role_player_alive)
|
||||
:defaults{
|
||||
player = function(player)
|
||||
return player.character and player.character.health > 0 and player or nil
|
||||
end
|
||||
}
|
||||
:register(function(player, other_player)
|
||||
--- @cast other_player LuaPlayer?
|
||||
if other_player == nil then
|
||||
-- Can only be nil if the target is the player and they are already dead
|
||||
return Commands.status.error{ "exp-commands_kill.already-dead" }
|
||||
elseif other_player == player then
|
||||
-- You can always kill yourself
|
||||
other_player.character.die()
|
||||
elseif highest_role(other_player).index < highest_role(player).index then
|
||||
-- Can kill lower role players
|
||||
other_player.character.die()
|
||||
else
|
||||
return Commands.status.unauthorised{ "exp-commands_kill.lower-role" }
|
||||
end
|
||||
end)
|
||||
52
exp_scenario/module/commands/lawnmower.lua
Normal file
52
exp_scenario/module/commands/lawnmower.lua
Normal file
@@ -0,0 +1,52 @@
|
||||
--[[-- Commands - Lawnmower
|
||||
Adds a command that clean up biter corpse and nuclear hole
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local config = require("modules.exp_legacy.config.lawnmower") --- @dep config.lawnmower
|
||||
|
||||
Commands.new("lawnmower", { "exp-commands_lawnmower.description" })
|
||||
:argument("range", { "exp-commands_lawnmower.arg-range" }, Commands.types.integer_range(1, 200))
|
||||
:register(function(player, range)
|
||||
--- @cast range number
|
||||
local surface = player.surface
|
||||
|
||||
-- Intentionally left as player.position to allow use in remote view
|
||||
local entities = surface.find_entities_filtered{ position = player.position, radius = range, type = "corpse" }
|
||||
for _, entity in pairs(entities) do
|
||||
if (entity.name ~= "transport-caution-corpse" and entity.name ~= "invisible-transport-caution-corpse") then
|
||||
entity.destroy()
|
||||
end
|
||||
end
|
||||
|
||||
local replace_tiles = {}
|
||||
local tiles = surface.find_tiles_filtered{ position = player.position, radius = range, name = { "nuclear-ground" } }
|
||||
for i, tile in pairs(tiles) do
|
||||
replace_tiles[i] = { name = "grass-1", position = tile.position }
|
||||
end
|
||||
|
||||
surface.set_tiles(replace_tiles)
|
||||
surface.destroy_decoratives{ position = player.position, radius = range }
|
||||
end)
|
||||
|
||||
--- @param event EventData.on_built_entity | EventData.on_robot_built_entity | EventData.script_raised_built | EventData.script_raised_revive
|
||||
local function destroy_decoratives(event)
|
||||
local entity = event.entity
|
||||
if entity.type ~= "entity-ghost" and entity.type ~= "tile-ghost" and entity.prototype.selectable_in_game then
|
||||
entity.surface.destroy_decoratives{ area = entity.selection_box }
|
||||
end
|
||||
end
|
||||
|
||||
local e = defines.events
|
||||
local events = {}
|
||||
|
||||
if config.destroy_decoratives then
|
||||
events[e.on_built_entity] = destroy_decoratives
|
||||
events[e.on_robot_built_entity] = destroy_decoratives
|
||||
events[e.script_raised_built] = destroy_decoratives
|
||||
events[e.script_raised_revive] = destroy_decoratives
|
||||
end
|
||||
|
||||
return {
|
||||
events = events
|
||||
}
|
||||
40
exp_scenario/module/commands/locate.lua
Normal file
40
exp_scenario/module/commands/locate.lua
Normal file
@@ -0,0 +1,40 @@
|
||||
--[[-- Commands - Locate
|
||||
Adds a command that will return the last location of a player
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local format_player_name = Commands.format_player_name_locale
|
||||
|
||||
local format = string.format
|
||||
|
||||
--- Open remote view at a players last location
|
||||
Commands.new("locate", { "exp-commands_locate.description" })
|
||||
:add_aliases{ "last-location", "find" }
|
||||
:argument("player", { "exp-commands_locate.arg-player" }, Commands.types.player)
|
||||
:optional("remote", { "exp-commands_locate.arg-remote" }, Commands.types.boolean)
|
||||
:register(function(player, other_player, remote)
|
||||
--- @cast other_player LuaPlayer
|
||||
--- @cast remote boolean?
|
||||
local surface = other_player.physical_surface
|
||||
local position = other_player.physical_position
|
||||
if remote and other_player.controller_type == defines.controllers.remote then
|
||||
surface = other_player.surface
|
||||
position = other_player.position
|
||||
end
|
||||
|
||||
if player.index > 0 then
|
||||
-- This check allows rcon to use the command
|
||||
player.set_controller{
|
||||
type = defines.controllers.remote,
|
||||
surface = surface,
|
||||
position = position,
|
||||
}
|
||||
end
|
||||
|
||||
return Commands.status.success{
|
||||
"exp-commands_locate.response",
|
||||
format_player_name(other_player),
|
||||
format("%.1f", position.x),
|
||||
format("%.1f", position.y),
|
||||
}
|
||||
end)
|
||||
14
exp_scenario/module/commands/me.lua
Normal file
14
exp_scenario/module/commands/me.lua
Normal file
@@ -0,0 +1,14 @@
|
||||
--[[-- Commands - Me
|
||||
Adds a command that adds * around your message in the chat
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local format_text = Commands.format_rich_text_color_locale
|
||||
|
||||
--- Sends an action message in the chat
|
||||
Commands.new("me", { "exp-commands_me.description" })
|
||||
:argument("action", { "exp-commands_me.arg-action" }, Commands.types.string)
|
||||
:enable_auto_concatenation()
|
||||
:register(function(player, action)
|
||||
game.print(format_text({ "exp-commands_me.response", player.name, action, }, player.chat_color))
|
||||
end)
|
||||
239
exp_scenario/module/commands/protected_entities.lua
Normal file
239
exp_scenario/module/commands/protected_entities.lua
Normal file
@@ -0,0 +1,239 @@
|
||||
--[[-- Commands - Protection
|
||||
Adds commands that can add and remove protection
|
||||
]]
|
||||
|
||||
local Storage = require("modules/exp_util/storage")
|
||||
|
||||
local AABB = require("modules/exp_util/aabb")
|
||||
local contains_area = AABB.contains_area
|
||||
local expand_area = AABB.expand
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local format_player_name = Commands.format_player_name_locale
|
||||
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
local Selection = require("modules.exp_legacy.modules.control.selection") --- @dep modules.control.selection
|
||||
local EntityProtection = require("modules.exp_legacy.modules.control.protection") --- @dep modules.control.protection
|
||||
|
||||
local format_string = string.format
|
||||
local floor = math.floor
|
||||
|
||||
local SelectionName_Entity = "ExpCommand_ProtectEntity"
|
||||
local SelectionName_Area = "ExpCommand_ProtectArea"
|
||||
|
||||
local renders = {} --- @type table<number, table<string, LuaRenderObject>> Stores all renders for a player
|
||||
Storage.register({
|
||||
renders = renders,
|
||||
}, function(tbl)
|
||||
renders = tbl.renders
|
||||
end)
|
||||
|
||||
--- Get the key used in protected_entities
|
||||
--- @param entity LuaEntity
|
||||
--- @return string
|
||||
local function get_entity_key(entity)
|
||||
return format_string("%i,%i", floor(entity.position.x), floor(entity.position.y))
|
||||
end
|
||||
|
||||
--- Get the key used in protected_areas
|
||||
--- TODO expose this from EntityProtection
|
||||
--- @param area BoundingBox
|
||||
--- @return string
|
||||
local function get_area_key(area)
|
||||
return format_string("%i,%i", floor(area.left_top.x), floor(area.left_top.y))
|
||||
end
|
||||
|
||||
--- Show a protected entity to a player
|
||||
--- @param player LuaPlayer
|
||||
--- @param entity LuaEntity
|
||||
local function show_protected_entity(player, entity)
|
||||
local key = get_entity_key(entity)
|
||||
if renders[player.index][key] then return end
|
||||
local rb = entity.selection_box.right_bottom
|
||||
renders[player.index][key] = rendering.draw_sprite{
|
||||
sprite = "utility/notification",
|
||||
target = entity,
|
||||
target_offset = {
|
||||
(rb.x - entity.position.x) * 0.75,
|
||||
(rb.y - entity.position.y) * 0.75,
|
||||
},
|
||||
x_scale = 2,
|
||||
y_scale = 2,
|
||||
surface = entity.surface,
|
||||
players = { player },
|
||||
}
|
||||
end
|
||||
|
||||
--- Show a protected area to a player
|
||||
--- @param player LuaPlayer
|
||||
--- @param surface LuaSurface
|
||||
--- @param area BoundingBox
|
||||
local function show_protected_area(player, surface, area)
|
||||
local key = get_area_key(area)
|
||||
if renders[player.index][key] then return end
|
||||
renders[player.index][key] = rendering.draw_rectangle{
|
||||
color = { 1, 1, 0, 0.5 },
|
||||
filled = false,
|
||||
width = 3,
|
||||
left_top = area.left_top,
|
||||
right_bottom = area.right_bottom,
|
||||
surface = surface,
|
||||
players = { player },
|
||||
}
|
||||
end
|
||||
|
||||
--- Remove a render object for a player
|
||||
--- @param player LuaPlayer
|
||||
--- @param key string
|
||||
local function remove_render(player, key)
|
||||
local render = renders[player.index][key]
|
||||
if render and render.valid then render.destroy() end
|
||||
renders[player.index][key] = nil
|
||||
end
|
||||
|
||||
--- Toggles entity protection selection
|
||||
Commands.new("protect-entity", { "exp-commands_protection.description-entity" })
|
||||
:add_aliases{ "pe" }
|
||||
:register(function(player)
|
||||
if Selection.is_selecting(player, SelectionName_Entity) then
|
||||
Selection.stop(player)
|
||||
return Commands.status.success{ "exp-commands_protection.exit-entity" }
|
||||
else
|
||||
Selection.start(player, SelectionName_Entity)
|
||||
return Commands.status.success{ "exp-commands_protection.enter-entity" }
|
||||
end
|
||||
end)
|
||||
|
||||
--- Toggles area protection selection
|
||||
Commands.new("protect-area", { "exp-commands_protection.description-area" })
|
||||
:add_aliases{ "pa" }
|
||||
:register(function(player)
|
||||
if Selection.is_selecting(player, SelectionName_Entity) then
|
||||
Selection.stop(player)
|
||||
return Commands.status.success{ "exp-commands_protection.exit-area" }
|
||||
else
|
||||
Selection.start(player, SelectionName_Entity)
|
||||
return Commands.status.success{ "exp-commands_protection.enter-area" }
|
||||
end
|
||||
end)
|
||||
|
||||
--- When an area is selected to add protection to entities
|
||||
Selection.on_selection(SelectionName_Entity, function(event)
|
||||
--- @cast event EventData.on_player_selected_area
|
||||
local player = game.players[event.player_index]
|
||||
for _, entity in ipairs(event.entities) do
|
||||
EntityProtection.add_entity(entity)
|
||||
show_protected_entity(player, entity)
|
||||
end
|
||||
|
||||
player.print({ "exp-commands_protection.protected-entities", #event.entities }, Commands.print_settings.default)
|
||||
end)
|
||||
|
||||
--- When an area is selected to remove protection from entities
|
||||
Selection.on_alt_selection(SelectionName_Entity, function(event)
|
||||
--- @cast event EventData.on_player_alt_selected_area
|
||||
local player = game.players[event.player_index]
|
||||
for _, entity in ipairs(event.entities) do
|
||||
EntityProtection.remove_entity(entity)
|
||||
remove_render(player, get_entity_key(entity))
|
||||
end
|
||||
|
||||
player.print({ "exp-commands_protection.unprotected-entities", #event.entities }, Commands.print_settings.default)
|
||||
end)
|
||||
|
||||
--- When an area is selected to add protection to the area
|
||||
Selection.on_selection(SelectionName_Area, function(event)
|
||||
--- @cast event EventData.on_player_selected_area
|
||||
local surface = event.surface
|
||||
local area = expand_area(event.area)
|
||||
local areas = EntityProtection.get_areas(event.surface)
|
||||
local player = game.players[event.player_index]
|
||||
for _, next_area in pairs(areas) do
|
||||
if contains_area(next_area, area) then
|
||||
return player.print({ "exp-commands_protection.already-protected" }, Commands.print_settings.error)
|
||||
end
|
||||
end
|
||||
|
||||
EntityProtection.add_area(surface, area)
|
||||
show_protected_area(player, surface, area)
|
||||
player.print({ "exp-commands_protection.protected-area" }, Commands.print_settings.default)
|
||||
end)
|
||||
|
||||
--- When an area is selected to remove protection from the area
|
||||
Selection.on_alt_selection(SelectionName_Area, function(event)
|
||||
--- @cast event EventData.on_player_alt_selected_area
|
||||
local surface = event.surface
|
||||
local area = expand_area(event.area)
|
||||
local areas = EntityProtection.get_areas(surface)
|
||||
local player = game.players[event.player_index]
|
||||
for _, next_area in pairs(areas) do
|
||||
if contains_area(area, next_area) then
|
||||
EntityProtection.remove_area(surface, next_area)
|
||||
player.print({ "exp-commands_protection.unprotected-area" }, Commands.print_settings.default)
|
||||
remove_render(player, get_area_key(next_area))
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
--- When selection starts show all protected entities and protected areas
|
||||
local function on_player_selection_start(event)
|
||||
if event.selection ~= SelectionName_Entity and event.selection ~= SelectionName_Area then return end
|
||||
local player = game.players[event.player_index]
|
||||
local surface = player.surface -- Allow remote view
|
||||
renders[player.index] = {}
|
||||
|
||||
-- Show protected entities
|
||||
local entities = EntityProtection.get_entities(surface)
|
||||
for _, entity in pairs(entities) do
|
||||
show_protected_entity(player, entity)
|
||||
end
|
||||
|
||||
-- Show always protected entities by name
|
||||
if #EntityProtection.protected_entity_names > 0 then
|
||||
for _, entity in pairs(surface.find_entities_filtered{ name = EntityProtection.protected_entity_names, force = player.force }) do
|
||||
show_protected_entity(player, entity)
|
||||
end
|
||||
end
|
||||
|
||||
-- Show always protected entities by type
|
||||
if #EntityProtection.protected_entity_types > 0 then
|
||||
for _, entity in pairs(surface.find_entities_filtered{ type = EntityProtection.protected_entity_types, force = player.force }) do
|
||||
show_protected_entity(player, entity)
|
||||
end
|
||||
end
|
||||
|
||||
-- Show protected areas
|
||||
local areas = EntityProtection.get_areas(surface)
|
||||
for _, area in pairs(areas) do
|
||||
show_protected_area(player, surface, area)
|
||||
end
|
||||
end
|
||||
|
||||
--- When selection ends hide protected entities and protected areas
|
||||
local function on_player_selection_end(event)
|
||||
if event.selection ~= SelectionName_Entity and event.selection ~= SelectionName_Area then return end
|
||||
for _, render in pairs(renders[event.player_index]) do
|
||||
if render.valid then render.destroy() end
|
||||
end
|
||||
|
||||
renders[event.player_index] = nil
|
||||
end
|
||||
|
||||
--- When there is a repeat offence print it in chat
|
||||
local function on_repeat_violation(event)
|
||||
Roles.print_to_roles_higher("Regular", {
|
||||
"exp-commands_protection.repeat-offence",
|
||||
format_player_name(event.player_index),
|
||||
event.entity.localised_name,
|
||||
event.entity.position.x,
|
||||
event.entity.position.y
|
||||
})
|
||||
end
|
||||
|
||||
return {
|
||||
events = {
|
||||
[Selection.events.on_player_selection_start] = on_player_selection_start,
|
||||
[Selection.events.on_player_selection_end] = on_player_selection_end,
|
||||
[EntityProtection.events.on_repeat_violation] = on_repeat_violation,
|
||||
}
|
||||
}
|
||||
112
exp_scenario/module/commands/protected_tags.lua
Normal file
112
exp_scenario/module/commands/protected_tags.lua
Normal file
@@ -0,0 +1,112 @@
|
||||
--[[-- Commands - Protected Tags
|
||||
Adds a command that creates chart tags which can only be edited by admins
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local Storage = require("modules/exp_util/storage")
|
||||
|
||||
--- Storage variables
|
||||
local active_players = {} --- @type table<number, boolean> Stores all players in in protected mode
|
||||
local map_tags = {} --- @type table<number, boolean> Stores all protected map tags
|
||||
|
||||
Storage.register({
|
||||
active_players = active_players,
|
||||
map_tags = map_tags,
|
||||
}, function(tbl)
|
||||
active_players = tbl.active_players
|
||||
map_tags = tbl.map_tags
|
||||
end)
|
||||
|
||||
--- Toggle admin marker mode, can only be applied to yourself
|
||||
local cmd_protected_tag =
|
||||
Commands.new("protected-tag", { "exp-commands_protected-tags.description" })
|
||||
:add_aliases{ "ptag" }
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player)
|
||||
if active_players[player.index] then
|
||||
active_players[player.index] = nil
|
||||
return Commands.status.success{ "exp-commands_protected-tags.exit" }
|
||||
else
|
||||
active_players[player.index] = true
|
||||
return Commands.status.success{ "exp-commands_protected-tags.enter" }
|
||||
end
|
||||
end)
|
||||
|
||||
--- When a player leaves the game, remove them from the active list
|
||||
--- @param event EventData.on_player_left_game
|
||||
local function on_player_left_game(event)
|
||||
active_players[event.player_index] = nil
|
||||
end
|
||||
|
||||
--- Add a chart tag as protected if the player is in protected mode
|
||||
--- @param event EventData.on_chart_tag_added
|
||||
local function on_chart_tag_added(event)
|
||||
if not event.player_index then return end
|
||||
if not active_players[event.player_index] then return end
|
||||
|
||||
local tag = event.tag
|
||||
local player = game.players[event.player_index]
|
||||
map_tags[tag.force.name .. tag.tag_number] = true
|
||||
player.print{ "exp-commands_protected-tags.create" }
|
||||
end
|
||||
|
||||
--- Stop a tag from being edited or removed
|
||||
--- @param event EventData.on_chart_tag_modified | EventData.on_chart_tag_removed
|
||||
local function on_chart_tag_removed_or_modified(event)
|
||||
local tag = event.tag
|
||||
if not event.player_index then return end
|
||||
if not map_tags[tag.force.name .. tag.tag_number] then return end
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
-- Check if the player is in protected mode, and inform them that it was protected
|
||||
if active_players[event.player_index] then
|
||||
player.print{ "exp-commands_protected-tags.edit" }
|
||||
return
|
||||
end
|
||||
|
||||
-- Check how the changes need to be reverted
|
||||
if event.name == defines.events.on_chart_tag_modified then
|
||||
-- Tag was modified, revert the changes
|
||||
tag.text = event.old_text
|
||||
tag.icon = event.old_icon
|
||||
tag.surface = event.old_surface
|
||||
tag.position = event.old_position
|
||||
if event.old_player_index then
|
||||
tag.last_user = game.players[event.old_player_index]
|
||||
else
|
||||
tag.last_user = nil
|
||||
end
|
||||
|
||||
else
|
||||
-- Tag was removed, recreate the tag
|
||||
local new_tag =
|
||||
tag.force.add_chart_tag(tag.surface, {
|
||||
last_user = tag.last_user,
|
||||
position = tag.position,
|
||||
icon = tag.icon,
|
||||
text = tag.text,
|
||||
})
|
||||
|
||||
--- @cast new_tag -nil
|
||||
map_tags[tag.force.name .. tag.tag_number] = nil
|
||||
map_tags[new_tag.force.name .. new_tag.tag_number] = true
|
||||
end
|
||||
|
||||
if Commands.player_has_permission(player, cmd_protected_tag) then
|
||||
-- Player is not in protected mode, but has access to the command
|
||||
player.print({ "exp-commands_protected-tags.revert-has-access", cmd_protected_tag.name }, Commands.print_settings.error)
|
||||
else
|
||||
--- Player does not have access to protected mode
|
||||
player.print({ "exp-commands_protected-tags.revert-no-access" }, Commands.print_settings.error)
|
||||
end
|
||||
end
|
||||
|
||||
local e = defines.events
|
||||
return {
|
||||
events = {
|
||||
[e.on_chart_tag_added] = on_chart_tag_added,
|
||||
[e.on_player_left_game] = on_player_left_game,
|
||||
[e.on_chart_tag_modified] = on_chart_tag_removed_or_modified,
|
||||
[e.on_chart_tag_removed] = on_chart_tag_removed_or_modified,
|
||||
}
|
||||
}
|
||||
72
exp_scenario/module/commands/rainbow.lua
Normal file
72
exp_scenario/module/commands/rainbow.lua
Normal file
@@ -0,0 +1,72 @@
|
||||
--[[-- Commands - Rainbow
|
||||
Adds a command that prints your message in rainbow font
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local format_player_name = Commands.format_player_name_locale
|
||||
local format_text = Commands.format_rich_text_color
|
||||
|
||||
--- Wraps one component into the next
|
||||
--- @param c1 number
|
||||
--- @param c2 number
|
||||
--- @return number, number
|
||||
local function step_component(c1, c2)
|
||||
if c1 < 0 then
|
||||
return 0, c2 + c1
|
||||
elseif c1 > 1 then
|
||||
return 1, c2 - c1 + 1
|
||||
else
|
||||
return c1, c2
|
||||
end
|
||||
end
|
||||
|
||||
--- Wraps all components of a colour ensuring it remains valid
|
||||
--- @param color Color
|
||||
--- @return Color
|
||||
local function step_color(color)
|
||||
color.r, color.g = step_component(color.r, color.g)
|
||||
color.g, color.b = step_component(color.g, color.b)
|
||||
color.b, color.r = step_component(color.b, color.r)
|
||||
color.r = step_component(color.r, 0)
|
||||
return color
|
||||
end
|
||||
|
||||
--- Get the next colour in the rainbow by the given step
|
||||
--- @param color Color
|
||||
--- @param step number
|
||||
--- @return Color
|
||||
local function next_color(color, step)
|
||||
step = step or 0.1
|
||||
local new_color = { r = 0, g = 0, b = 0 }
|
||||
if color.b == 0 and color.r ~= 0 then
|
||||
new_color.r = color.r - step
|
||||
new_color.g = color.g + step
|
||||
elseif color.r == 0 and color.g ~= 0 then
|
||||
new_color.g = color.g - step
|
||||
new_color.b = color.b + step
|
||||
elseif color.g == 0 and color.b ~= 0 then
|
||||
new_color.b = color.b - step
|
||||
new_color.r = color.r + step
|
||||
end
|
||||
return step_color(new_color)
|
||||
end
|
||||
|
||||
--- Sends an rainbow message in the chat
|
||||
Commands.new("rainbow", { "exp-commands_rainbow" })
|
||||
:argument("message", { "exp-commands_rainbow.arg-message" }, Commands.types.string)
|
||||
:enable_auto_concatenation()
|
||||
:register(function(player, message)
|
||||
local color_step = 3 / message:len()
|
||||
if color_step > 1 then color_step = 1 end
|
||||
local current_color = { r = 1, g = 0, b = 0 }
|
||||
|
||||
game.print{
|
||||
"exp-commands_rainbow.response",
|
||||
format_player_name(player),
|
||||
message:gsub("%S", function(letter)
|
||||
local rtn = format_text(letter, current_color)
|
||||
current_color = next_color(current_color, color_step)
|
||||
return rtn
|
||||
end)
|
||||
}
|
||||
end)
|
||||
54
exp_scenario/module/commands/ratio.lua
Normal file
54
exp_scenario/module/commands/ratio.lua
Normal file
@@ -0,0 +1,54 @@
|
||||
--[[-- Commands - Ratio
|
||||
Adds a command to calculate the number of machines needed to fulfil a desired production
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
|
||||
Commands.new("ratio", { "exp-command_ratio.description" })
|
||||
:optional("items-per-second", { "exp-command_ratio.arg-items-per-second" }, Commands.types.number)
|
||||
:register(function(player, items_per_second)
|
||||
--- @cast items_per_second number?
|
||||
|
||||
local machine = player.selected
|
||||
if not machine then
|
||||
return Commands.status.error{ "exp-command_ratio.not-selecting" }
|
||||
end
|
||||
|
||||
if machine.type ~= "assembling-machine" and machine.type ~= "furnace" then
|
||||
return Commands.status.error{ "exp-command_ratio.not-selecting" }
|
||||
end
|
||||
|
||||
local recipe = machine.get_recipe()
|
||||
if not recipe then
|
||||
return Commands.status.error{ "exp-command_ratio.not-selecting" }
|
||||
end
|
||||
|
||||
local products = recipe.products
|
||||
local ingredients = recipe.ingredients
|
||||
local crafts_per_second = machine.crafting_speed * machine.productivity_bonus / recipe.energy
|
||||
|
||||
local amount_of_machines = 1
|
||||
if items_per_second then
|
||||
amount_of_machines = math.ceil(products[1].amount * crafts_per_second)
|
||||
end
|
||||
|
||||
for _, ingredient in ipairs(ingredients) do
|
||||
Commands.print{
|
||||
ingredient.type == "item" and "exp-command_ratio.item-out" or "exp-command_ratio.fluid-out",
|
||||
math.round(ingredient.amount * crafts_per_second, 3),
|
||||
ingredient.name
|
||||
}
|
||||
end
|
||||
|
||||
for i, product in ipairs(products) do
|
||||
Commands.print{
|
||||
product.type == "item" and "exp-command_ratio.item-out" or "exp-command_ratio.fluid-out",
|
||||
math.round(product.amount * crafts_per_second, 3),
|
||||
product.name
|
||||
}
|
||||
end
|
||||
|
||||
if amount_of_machines ~= 1 then
|
||||
Commands.print{ "exp-command_ratio.machine-count", amount_of_machines }
|
||||
end
|
||||
end)
|
||||
60
exp_scenario/module/commands/repair.lua
Normal file
60
exp_scenario/module/commands/repair.lua
Normal file
@@ -0,0 +1,60 @@
|
||||
--[[-- Commands - Repair
|
||||
Adds a command that allows an admin to repair and revive a large area
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local config = require("modules.exp_legacy.config.repair") --- @dep config.repair
|
||||
|
||||
local huge = math.huge
|
||||
|
||||
--- Repairs entities on your force around you
|
||||
Commands.new("repair", { "exp-commands_repair.description" })
|
||||
:argument("range", { "exp-commands_repair.arg-range" }, Commands.types.integer_range(1, config.max_range))
|
||||
:register(function(player, range)
|
||||
--- @cast range number
|
||||
local force = player.force
|
||||
local surface = player.surface -- Allow remote view
|
||||
local position = player.position -- Allow remote view
|
||||
local response = { "" } --- @type LocalisedString
|
||||
|
||||
if config.allow_ghost_revive then
|
||||
local revive_count = 0
|
||||
local entities = surface.find_entities_filtered{
|
||||
type = "entity-ghost",
|
||||
position = position,
|
||||
radius = range,
|
||||
force = force,
|
||||
}
|
||||
|
||||
for _, entity in ipairs(entities) do
|
||||
-- TODO test for ghost not being a blueprint, https://forums.factorio.com/viewtopic.php?f=28&t=119736
|
||||
if not config.disallow[entity.ghost_name] and (config.allow_blueprint_repair or true) then
|
||||
revive_count = revive_count + 1
|
||||
entity.silent_revive()
|
||||
end
|
||||
end
|
||||
|
||||
response[#response + 1] = { "exp-commands_repair.response-revive", revive_count }
|
||||
end
|
||||
|
||||
if config.allow_heal_entities then
|
||||
local healed_count = 0
|
||||
local entities = surface.find_entities_filtered{
|
||||
position = position,
|
||||
radius = range,
|
||||
force = force,
|
||||
}
|
||||
|
||||
for _, entity in ipairs(entities) do
|
||||
if entity.health and entity.get_health_ratio() ~= 1 then
|
||||
healed_count = healed_count + 1
|
||||
entity.health = huge
|
||||
end
|
||||
end
|
||||
|
||||
response[#response + 1] = { "exp-commands_repair.response-heal", healed_count }
|
||||
end
|
||||
|
||||
return Commands.status.success(response)
|
||||
end)
|
||||
|
||||
107
exp_scenario/module/commands/reports.lua
Normal file
107
exp_scenario/module/commands/reports.lua
Normal file
@@ -0,0 +1,107 @@
|
||||
--[[-- Commands - Reports
|
||||
Adds a commands that allow players to report other players
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local format_player_name = Commands.format_player_name_locale
|
||||
local parse_input = Commands.parse_input
|
||||
|
||||
local Roles = require("modules.exp_legacy.expcore.roles")
|
||||
local player_has_flag = Roles.player_has_flag
|
||||
|
||||
local Reports = require("modules.exp_legacy.modules.control.reports") --- @dep modules.control.reports
|
||||
|
||||
--- @type Commands.InputParser
|
||||
local function reportable_player(input, player)
|
||||
local success, status, result = parse_input(input, player, Commands.types.player)
|
||||
if not success then return status, result end
|
||||
--- @cast result LuaPlayer
|
||||
|
||||
if player_has_flag(input, "report-immune") then
|
||||
return Commands.status.invalid_input{ "exp-commands_reports.player-immune" }
|
||||
elseif player == input then
|
||||
return Commands.status.invalid_input{ "exp-commands_reports.self-report" }
|
||||
else
|
||||
return Commands.status.success(result)
|
||||
end
|
||||
end
|
||||
|
||||
--- Reports a player and notifies admins
|
||||
Commands.new("create-report", { "exp-commands_reports.description-create" })
|
||||
:argument("player", { "exp-commands_reports.arg-player-create" }, reportable_player)
|
||||
:argument("reason", { "exp-commands_reports.arg-reason" }, Commands.types.string)
|
||||
:enable_auto_concatenation()
|
||||
:add_aliases{ "report" }
|
||||
:register(function(player, other_player, reason)
|
||||
--- @cast other_player LuaPlayer
|
||||
--- @cast reason string
|
||||
local player_name = format_player_name(player)
|
||||
local other_player_name = format_player_name(other_player)
|
||||
if Reports.report_player(other_player, player.name, reason) then
|
||||
local user_message = { "exp-commands_reports.response", other_player_name, reason }
|
||||
local admin_message = { "exp-commands_reports.response-admin", other_player_name, player_name, reason }
|
||||
for _, player in ipairs(game.connected_players) do
|
||||
if player.admin then
|
||||
player.print(admin_message)
|
||||
else
|
||||
player.print(user_message)
|
||||
end
|
||||
end
|
||||
else
|
||||
return Commands.status.invalid_input{ "exp-commands_reports.already-reported" }
|
||||
end
|
||||
end)
|
||||
|
||||
--- Gets a list of all reports that a player has on them. If no player then lists all players and the number of reports on them.
|
||||
Commands.new("get-reports", { "exp-commands_reports.description-get" })
|
||||
:optional("player", { "exp-commands_reports.arg-player-get" }, Commands.types.player)
|
||||
:add_aliases{ "reports" }
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player, other_player)
|
||||
--- @cast other_player LuaPlayer?
|
||||
if other_player then
|
||||
local reports = Reports.get_reports(other_player)
|
||||
local other_player_name = format_player_name(other_player)
|
||||
Commands.print{ "exp-commands_reports.player-title", other_player_name, #reports }
|
||||
for by_player_name, reason in pairs(reports) do
|
||||
local by_player_name_formatted = format_player_name(by_player_name)
|
||||
Commands.print{ "exp-commands_reports.list-element", by_player_name_formatted, reason }
|
||||
end
|
||||
else
|
||||
local reports = Reports.user_reports
|
||||
Commands.print{ "exp-commands_reports.reports-title" }
|
||||
for player_name in pairs(reports) do
|
||||
local player_name_formatted = format_player_name(player_name)
|
||||
local report_count = Reports.count_reports(player_name)
|
||||
Commands.print{ "exp-commands_reports.list-element", player_name_formatted, report_count }
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
--- Clears all reports from a player or just the report from one player.
|
||||
Commands.new("clear-reports", { "exp-commands_reports.description-clear" })
|
||||
:argument("player", { "exp-commands_reports.arg-player-clear" }, Commands.types.player)
|
||||
:optional("from-player", { "exp-commands_reports.arg-from-player" }, Commands.types.player)
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player, other_player, from_player)
|
||||
--- @cast other_player LuaPlayer
|
||||
--- @cast from_player LuaPlayer?
|
||||
local player_name = format_player_name(player)
|
||||
local other_player_name = format_player_name(other_player)
|
||||
if from_player then
|
||||
if not Reports.remove_report(other_player, from_player.name, player.name) then
|
||||
local from_player_name = format_player_name(other_player)
|
||||
return Commands.status.invalid_input{ "exp-commands_reports.not-reported-by", from_player_name }
|
||||
else
|
||||
game.print{ "exp-commands_reports.removed", other_player_name, player_name }
|
||||
return Commands.status.success()
|
||||
end
|
||||
else
|
||||
if not Reports.remove_all(other_player, player.name) then
|
||||
return Commands.status.invalid_input{ "exp-commands_reports.not-reported" }
|
||||
else
|
||||
game.print{ "exp-commands_reports.removed-all", other_player_name, player_name }
|
||||
return Commands.status.success()
|
||||
end
|
||||
end
|
||||
end)
|
||||
71
exp_scenario/module/commands/research.lua
Normal file
71
exp_scenario/module/commands/research.lua
Normal file
@@ -0,0 +1,71 @@
|
||||
--[[-- Commands - Research
|
||||
Adds a command to enable automatic research queueing
|
||||
]]
|
||||
|
||||
local Storage = require("modules/exp_util/storage")
|
||||
local Commands = require("modules/exp_commands")
|
||||
local format_player_name = Commands.format_player_name_locale
|
||||
|
||||
local config = require("modules.exp_legacy.config.research") --- @dep config.research
|
||||
|
||||
local research = {
|
||||
res_queue_enable = false
|
||||
}
|
||||
|
||||
Storage.register(research, function(tbl)
|
||||
research = tbl
|
||||
end)
|
||||
|
||||
--- @param force LuaForce
|
||||
--- @param silent boolean True when no message should be printed
|
||||
local function res_queue(force, silent)
|
||||
local res_q = force.research_queue
|
||||
local res = force.technologies["mining-productivity-4"]
|
||||
|
||||
if #res_q < config.queue_amount then
|
||||
for i = 1, config.queue_amount - #res_q do
|
||||
force.add_research(res)
|
||||
|
||||
if not silent then
|
||||
game.print{ "exp-commands_research.queue", res.name, res.level + i }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Sets the auto research state
|
||||
Commands.new("set-auto-research", { "exp-commands_research.description" })
|
||||
:optional("state", { "exp-commands_research.arg-state" }, Commands.types.boolean)
|
||||
:add_aliases{ "auto-research" }
|
||||
:register(function(player, state)
|
||||
--- @cast state boolean?
|
||||
if state == nil then
|
||||
research.res_queue_enable = not research.res_queue_enable
|
||||
else
|
||||
research.res_queue_enable = state
|
||||
end
|
||||
|
||||
if research.res_queue_enable then
|
||||
res_queue(player.force --[[@as LuaForce]], true)
|
||||
end
|
||||
|
||||
local player_name = format_player_name(player)
|
||||
game.print{ "exp-commands_research.auto-research", player_name, research.res_queue_enable }
|
||||
end)
|
||||
|
||||
--- @param event EventData.on_research_finished
|
||||
local function on_research_finished(event)
|
||||
if not research.res_queue_enable then return end
|
||||
|
||||
local force = event.research.force
|
||||
if force.rockets_launched > 0 and force.technologies["mining-productivity-4"].level > 4 then
|
||||
res_queue(force, event.by_script)
|
||||
end
|
||||
end
|
||||
|
||||
local e = defines.events
|
||||
return {
|
||||
events = {
|
||||
[e.on_research_finished] = on_research_finished,
|
||||
}
|
||||
}
|
||||
63
exp_scenario/module/commands/roles.lua
Normal file
63
exp_scenario/module/commands/roles.lua
Normal file
@@ -0,0 +1,63 @@
|
||||
--[[-- Commands - Roles
|
||||
Adds a commands that allow interaction with the role system
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local format_player_name = Commands.format_player_name_locale
|
||||
local format_text = Commands.format_rich_text_color_locale
|
||||
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
local get_roles_ordered = Roles.get_roles_ordered
|
||||
local get_player_roles = Roles.get_player_roles
|
||||
|
||||
--- Assigns a role to a player
|
||||
Commands.new("assign-role", { "exp-commands_roles.description-assign" })
|
||||
:argument("player", { "exp-commands_roles.arg-player-assign" }, Commands.types.lower_role_player)
|
||||
:argument("role", { "exp-commands_roles.arg-role-assign" }, Commands.types.lower_role)
|
||||
:add_aliases{ "assign" }
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player, other_player, role)
|
||||
--- @cast other_player LuaPlayer
|
||||
--- @cast role any -- TODO
|
||||
Roles.assign_player(other_player, role, player.name)
|
||||
end)
|
||||
|
||||
--- Unassigns a role to a player
|
||||
Commands.new("unassign-role", { "exp-commands_roles.description-unassign" })
|
||||
:argument("player", { "exp-commands_roles.arg-player-unassign" }, Commands.types.lower_role_player)
|
||||
:argument("role", { "exp-commands_roles.arg-role-unassign" }, Commands.types.lower_role)
|
||||
:add_aliases{ "unassign" }
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player, other_player, role)
|
||||
--- @cast other_player LuaPlayer
|
||||
--- @cast role any -- TODO
|
||||
Roles.unassign_player(other_player, role, player.name)
|
||||
end)
|
||||
|
||||
--- Lists all roles in they correct order
|
||||
Commands.new("get-role", { "exp-commands_roles.description-get" })
|
||||
:optional("player", { "exp-commands_roles.arg-player-get" }, Commands.types.player)
|
||||
:add_aliases{ "roles" }
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player, other_player)
|
||||
--- @cast other_player LuaPlayer?
|
||||
local roles = get_roles_ordered()
|
||||
local roles_formatted = { "" } --- @type LocalisedString
|
||||
local response = { "exp-commands_roles.list-roles", roles_formatted }
|
||||
if other_player then
|
||||
roles = get_player_roles(other_player)
|
||||
response[1] = "exp-commands_roles.list-player"
|
||||
response[3] = format_player_name(other_player)
|
||||
end
|
||||
|
||||
for index, role in ipairs(roles) do
|
||||
local role_name = format_text(role.name, role.custom_color or Commands.color.white)
|
||||
roles_formatted[index + 1] = { "exp-commands_roles.list-element", role_name }
|
||||
end
|
||||
|
||||
local last = #roles_formatted
|
||||
--- @diagnostic disable-next-line nil-check
|
||||
roles_formatted[last] = roles_formatted[last][2]
|
||||
|
||||
return Commands.status.success(response)
|
||||
end)
|
||||
181
exp_scenario/module/commands/search.lua
Normal file
181
exp_scenario/module/commands/search.lua
Normal file
@@ -0,0 +1,181 @@
|
||||
--[[-- Commands - Inventory Search
|
||||
Adds commands that will search all players inventories for an item
|
||||
]]
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local format_player_name = Commands.format_player_name_locale
|
||||
|
||||
local format_number = require("util").format_number
|
||||
|
||||
--- A player who is of a lower role than the executing player
|
||||
--- @type Commands.InputParser
|
||||
local function parse_item(input, player)
|
||||
-- First Case - internal name is given
|
||||
-- Second Case - rich text is given
|
||||
local item_name = input:lower():gsub(" ", "-")
|
||||
local item = prototypes.item[item_name] or prototypes.item[input:match("%[item=([0-9a-z-]+)%]")]
|
||||
if item then
|
||||
return Commands.status.success(item)
|
||||
end
|
||||
|
||||
-- No item found, we do not attempt to search all prototypes as this will be expensive
|
||||
return Commands.status.invalid_input{ "exp-commands_search.invalid-item", item_name }
|
||||
end
|
||||
|
||||
--- @class SearchResult: { player: LuaPlayer, count: number, online_time: number }
|
||||
|
||||
--- Search all players for this item
|
||||
--- @param players LuaPlayer[] Players to search
|
||||
--- @param item LuaItemPrototype Item to find
|
||||
--- @return SearchResult[]
|
||||
local function search_players(players, item)
|
||||
local found = {} --- @type SearchResult[]
|
||||
local head = 1
|
||||
|
||||
-- Check the item count of all players
|
||||
for _, player in pairs(players) do
|
||||
local item_count = player.get_item_count(item.name)
|
||||
if item_count > 0 then
|
||||
-- Add the player to the array as they have the item
|
||||
found[head] = { player = player, count = item_count, online_time = player.online_time }
|
||||
head = head + 1
|
||||
end
|
||||
end
|
||||
|
||||
return found
|
||||
end
|
||||
|
||||
--- @alias SortFunction fun(result: SearchResult): number
|
||||
|
||||
--- Custom sort function which only retains 5 greatest values
|
||||
--- @param results SearchResult[] Players to sort
|
||||
--- @param func SortFunction Function to calculate value, higher better
|
||||
--- @return SearchResult[] # Top 5 results
|
||||
local function sort_results(results, func)
|
||||
local sorted = {}
|
||||
local values = {}
|
||||
local threshold = 0
|
||||
|
||||
-- Loop over all provided players
|
||||
for index, result in ipairs(results) do
|
||||
local value = func(result)
|
||||
-- Check if the item will make the top 5 elements
|
||||
if index <= 5 or value > threshold then
|
||||
local inserted = false
|
||||
values[result] = value
|
||||
|
||||
-- Find where in the top 5 to insert the element
|
||||
for next_index, next_result in ipairs(sorted) do
|
||||
if value > values[next_result] then
|
||||
table.insert(sorted, next_index, result)
|
||||
inserted = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- Update the threshold, clean up the tables, and insert if needed
|
||||
if sorted[6] then
|
||||
threshold = values[sorted[5]]
|
||||
values[sorted[6]] = nil
|
||||
sorted[6] = nil
|
||||
elseif not inserted then
|
||||
-- index <= 5 so insert at the end
|
||||
sorted[#sorted + 1] = result
|
||||
threshold = value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return sorted
|
||||
end
|
||||
|
||||
local display_players_time_format = ExpUtil.format_time_factory_locale{ format = "short", hours = true, minutes = true }
|
||||
|
||||
--- Display to the player the top players which were found
|
||||
--- @param results SearchResult[]
|
||||
--- @param item LuaItemPrototype
|
||||
--- @return LocalisedString
|
||||
local function format_response(results, item)
|
||||
if #results == 0 then
|
||||
return { "exp-commands_search.no-results", item.name }
|
||||
end
|
||||
|
||||
local response = { "", { "exp-commands_search.title", item.name } } --- @type LocalisedString
|
||||
for index, data in ipairs(results) do
|
||||
response[index + 2] = {
|
||||
"exp-commands_search.result",
|
||||
index,
|
||||
format_player_name(data.player),
|
||||
format_number(data.count, false),
|
||||
display_players_time_format(data.online_time),
|
||||
}
|
||||
end
|
||||
|
||||
return response
|
||||
end
|
||||
|
||||
--- Return the the amount of an item a player has divided by their playtime
|
||||
local function combined_sort(data)
|
||||
return data.count / data.online_time
|
||||
end
|
||||
|
||||
--- Get a list of players sorted by quantity held and play time
|
||||
Commands.new("search", { "exp-commands_search.description-search" })
|
||||
:argument("item", { "exp-commands_search.arg-item" }, parse_item)
|
||||
:enable_auto_concatenation()
|
||||
:add_aliases{ "s" }
|
||||
:register(function(player, item)
|
||||
--- @cast item LuaItemPrototype
|
||||
local results = search_players(game.players, item)
|
||||
local sorted = sort_results(results, combined_sort)
|
||||
return Commands.status.success(format_response(sorted, item))
|
||||
end)
|
||||
|
||||
--- Get a list of online players sorted by quantity held and play time
|
||||
Commands.new("search-online", { "exp-commands_search.description-online" })
|
||||
:argument("item", { "exp-commands_search.arg-item" }, parse_item)
|
||||
:enable_auto_concatenation()
|
||||
:add_aliases{ "so" }
|
||||
:register(function(player, item)
|
||||
--- @cast item LuaItemPrototype
|
||||
local results = search_players(game.connected_players, item)
|
||||
local sorted = sort_results(results, combined_sort)
|
||||
return Commands.status.success(format_response(sorted, item))
|
||||
end)
|
||||
|
||||
--- Return the amount of an item a player has
|
||||
--- @type SortFunction
|
||||
local function sort_by_count(data)
|
||||
return data.count
|
||||
end
|
||||
|
||||
--- Get a list of players sorted by the quantity of an item in their inventory
|
||||
Commands.new("search-amount", { "exp-commands_search.description-amount" })
|
||||
:argument("item", { "exp-commands_search.arg-item" }, parse_item)
|
||||
:enable_auto_concatenation()
|
||||
:add_aliases{ "sa" } -- cant use /sc
|
||||
:register(function(player, item)
|
||||
--- @cast item LuaItemPrototype
|
||||
local results = search_players(game.players, item)
|
||||
local sorted = sort_results(results, sort_by_count)
|
||||
return Commands.status.success(format_response(sorted, item))
|
||||
end)
|
||||
|
||||
--- Return the index of the player, higher means they joined more recently
|
||||
local function sort_by_recent(data)
|
||||
return data.player.index
|
||||
end
|
||||
|
||||
--- Get a list of players who have the given item, sorted by how recently they joined
|
||||
Commands.new("search-recent", { "exp-commands_search.description-recent" })
|
||||
:argument("item", { "exp-commands_search.arg-item" }, parse_item)
|
||||
:enable_auto_concatenation()
|
||||
:add_aliases{ "sr" } -- cant use /sc
|
||||
:register(function(player, item)
|
||||
--- @cast item LuaItemPrototype
|
||||
local results = search_players(game.players, item)
|
||||
local sorted = sort_results(results, sort_by_recent)
|
||||
return Commands.status.success(format_response(sorted, item))
|
||||
end)
|
||||
29
exp_scenario/module/commands/spectate.lua
Normal file
29
exp_scenario/module/commands/spectate.lua
Normal file
@@ -0,0 +1,29 @@
|
||||
--[[-- Commands - Spectate
|
||||
Adds commands relating to spectate and follow
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local Spectate = require("modules.exp_legacy.modules.control.spectate") --- @dep modules.control.spectate
|
||||
|
||||
--- Toggles spectator mode for the caller
|
||||
Commands.new("spectate", { "exp-commands_spectate.description-spectate" })
|
||||
:register(function(player)
|
||||
if Spectate.is_spectating(player) then
|
||||
Spectate.stop_spectate(player)
|
||||
else
|
||||
Spectate.start_spectate(player)
|
||||
end
|
||||
end)
|
||||
|
||||
--- Enters follow mode for the caller, following the given player.
|
||||
Commands.new("follow", { "exp-commands_spectate.description-follow" })
|
||||
:argument("player", { "exp-command_spectate.arg-player" }, Commands.types.player_online)
|
||||
:add_aliases{ "f" }
|
||||
:register(function(player, other_player)
|
||||
--- @cast other_player LuaPlayer
|
||||
if player == other_player then
|
||||
return Commands.status.invalid_input{ "exp-command_spectate.follow-self" }
|
||||
else
|
||||
Spectate.start_follow(player, other_player)
|
||||
end
|
||||
end)
|
||||
89
exp_scenario/module/commands/surface.lua
Normal file
89
exp_scenario/module/commands/surface.lua
Normal file
@@ -0,0 +1,89 @@
|
||||
--[[-- Commands - Clear Item On Ground
|
||||
Adds a command that clear item on ground so blueprint can deploy safely
|
||||
]]
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
local move_items = ExpUtil.move_items_to_surface
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local format_player_name = Commands.format_player_name_locale
|
||||
|
||||
--- @param surface LuaSurface
|
||||
--- @return LuaItemStack[]
|
||||
local function get_ground_items(surface)
|
||||
local items = {} --- @type LuaItemStack[]
|
||||
local entities = surface.find_entities_filtered{ name = "item-on-ground" }
|
||||
for index, entity in ipairs(entities) do
|
||||
items[index] = entity.stack
|
||||
end
|
||||
return items
|
||||
end
|
||||
|
||||
--- Clear all items on the ground, optional to select a single surface
|
||||
Commands.new("clear-ground-items", { "exp-commands_surface.description-items" })
|
||||
:optional("surface", { "exp-commands_surface.arg-surface" }, Commands.types.surface)
|
||||
:register(function(player, surface)
|
||||
--- @cast surface LuaSurface?
|
||||
local player_name = format_player_name(player)
|
||||
if surface then
|
||||
move_items{
|
||||
surface = surface,
|
||||
items = get_ground_items(surface),
|
||||
allow_creation = true,
|
||||
name = "iron-chest",
|
||||
}
|
||||
game.print{ "exp-commands_surface.items-surface", player_name, surface.localised_name }
|
||||
else
|
||||
for _, surface in pairs(game.surfaces) do
|
||||
move_items{
|
||||
surface = surface,
|
||||
items = get_ground_items(surface),
|
||||
allow_creation = true,
|
||||
name = "iron-chest",
|
||||
}
|
||||
end
|
||||
game.print{ "exp-commands_surface.items-all", player_name }
|
||||
end
|
||||
end)
|
||||
|
||||
--- Clear all blueprints, optional to select a single surface
|
||||
Commands.new("clear-blueprints", { "exp-commands_surface.description-blueprints" })
|
||||
:optional("surface", { "exp-commands_surface.arg-surface" }, Commands.types.surface)
|
||||
:register(function(player, surface)
|
||||
--- @cast surface LuaSurface?
|
||||
local player_name = format_player_name(player)
|
||||
if surface then
|
||||
local entities = surface.find_entities_filtered{ type = "entity-ghost" }
|
||||
for _, entity in ipairs(entities) do
|
||||
entity.destroy()
|
||||
end
|
||||
game.print{ "exp-commands_surface.blueprint-surface", player_name, surface.localised_name }
|
||||
else
|
||||
for _, surface in pairs(game.surfaces) do
|
||||
local entities = surface.find_entities_filtered{ type = "entity-ghost" }
|
||||
for _, entity in ipairs(entities) do
|
||||
entity.destroy()
|
||||
end
|
||||
end
|
||||
game.print{ "exp-commands_surface.blueprint-all", player_name }
|
||||
end
|
||||
end)
|
||||
|
||||
--- Clear all blueprints in a radius around you
|
||||
Commands.new("clear-blueprints-radius", { "exp-commands_surface.description-radius" })
|
||||
:argument("radius", { "exp-commands_surface.arg-radius" }, Commands.types.number_range(1, 1000))
|
||||
:register(function(player, radius)
|
||||
--- @cast radius number
|
||||
local player_name = format_player_name(player)
|
||||
local entities = player.surface.find_entities_filtered{
|
||||
type = "entity-ghost",
|
||||
position = player.position,
|
||||
radius = radius,
|
||||
}
|
||||
|
||||
for _, entity in ipairs(entities) do
|
||||
entity.destroy()
|
||||
end
|
||||
|
||||
game.print{ "exp-commands_surface.blueprint-radius", player_name, radius, player.surface.localised_name }
|
||||
end)
|
||||
84
exp_scenario/module/commands/teleport.lua
Normal file
84
exp_scenario/module/commands/teleport.lua
Normal file
@@ -0,0 +1,84 @@
|
||||
--[[-- Commands - Teleport
|
||||
Adds a command that allows players to teleport to other players and spawn
|
||||
]]
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
local teleport_player = ExpUtil.teleport_player
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
local player_allowed = Roles.player_allowed
|
||||
|
||||
--- Teleports a player to another player.
|
||||
Commands.new("teleport", { "exp-commands_teleport.description-teleport" })
|
||||
:argument("player", { "exp-commands_teleport.arg-player-teleport" }, Commands.types.player_alive)
|
||||
:optional("target", { "exp-commands_teleport.arg-player-to" }, Commands.types.player_alive)
|
||||
:add_aliases{ "tp" }
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player, other_player, target_player)
|
||||
--- @cast other_player LuaPlayer
|
||||
--- @cast target_player LuaPlayer?
|
||||
if target_player == nil then
|
||||
-- When no player is given, then instead behave like /goto
|
||||
if not teleport_player(player, other_player.physical_surface, other_player.physical_position) then
|
||||
return Commands.status.error{ "exp-commands_teleport.unavailable" }
|
||||
end
|
||||
elseif other_player == target_player then
|
||||
return Commands.status.invalid_input{ "exp-commands_teleport.same-player" }
|
||||
elseif not teleport_player(other_player, target_player.physical_surface, target_player.physical_position) then
|
||||
return Commands.status.error{ "exp-commands_teleport.unavailable" }
|
||||
end
|
||||
end)
|
||||
|
||||
--- Teleports a player to you.
|
||||
Commands.new("bring", { "exp-commands_teleport.description-bring" })
|
||||
:argument("player", { "exp-commands_teleport.arg-player-from" }, Commands.types.player_alive)
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player, other_player)
|
||||
--- @cast other_player LuaPlayer
|
||||
if player == other_player then
|
||||
return Commands.status.invalid_input{ "exp-commands_teleport.same-player" }
|
||||
elseif not teleport_player(other_player, player.physical_surface, player.physical_position) then
|
||||
return Commands.status.error{ "exp-commands_teleport.unavailable" }
|
||||
end
|
||||
end)
|
||||
|
||||
--- Teleports you to a player.
|
||||
Commands.new("goto", { "exp-commands_teleport.description-goto" })
|
||||
:argument("player", { "exp-commands_teleport.arg-player-to" }, Commands.types.player_alive)
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player, other_player)
|
||||
--- @cast other_player LuaPlayer
|
||||
if player == other_player then
|
||||
return Commands.status.invalid_input{ "exp-commands_teleport.same-player" }
|
||||
elseif not teleport_player(player, other_player.physical_surface, other_player.physical_position) then
|
||||
return Commands.status.error{ "exp-commands_teleport.unavailable" }
|
||||
end
|
||||
end)
|
||||
|
||||
--- Teleport to spawn
|
||||
Commands.new("spawn", { "exp-commands_teleport.description-spawn" })
|
||||
:optional("player", { "exp-commands_teleport.arg-player-spawn" }, Commands.types.player_alive)
|
||||
:defaults{
|
||||
player = function(player)
|
||||
if player.character and player.character.health > 0 then
|
||||
return player
|
||||
end
|
||||
end,
|
||||
}
|
||||
:register(function(player, other_player)
|
||||
if not other_player then
|
||||
return Commands.status.error{ "exp-commands_teleport.unavailable" }
|
||||
elseif other_player == player then
|
||||
if not teleport_player(player, game.surfaces.nauvis, { 0, 0 }, "dismount") then
|
||||
return Commands.status.error{ "exp-commands_teleport.unavailable" }
|
||||
end
|
||||
elseif player_allowed(player, "command/spawn/always") then
|
||||
if not teleport_player(other_player, game.surfaces.nauvis, { 0, 0 }, "dismount") then
|
||||
return Commands.status.error{ "exp-commands_teleport.unavailable" }
|
||||
end
|
||||
else
|
||||
return Commands.status.unauthorised()
|
||||
end
|
||||
end)
|
||||
29
exp_scenario/module/commands/trains.lua
Normal file
29
exp_scenario/module/commands/trains.lua
Normal file
@@ -0,0 +1,29 @@
|
||||
--[[-- Commands - Set Automatic Train
|
||||
Adds a command that set all train back to automatic
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local format_player_name = Commands.format_player_name_locale
|
||||
|
||||
local format_number = require("util").format_number
|
||||
|
||||
--- Set all trains to automatic
|
||||
Commands.new("set-trains-to-automatic", { "exp-commands_trains.description" })
|
||||
:optional("surface", { "exp-commands_trains.arg-surface" }, Commands.types.surface)
|
||||
:optional("force", { "exp-commands_trains.arg-force" }, Commands.types.force)
|
||||
:register(function(player, surface, force)
|
||||
--- @cast surface LuaSurface?
|
||||
--- @cast force LuaForce?
|
||||
local trains = game.train_manager.get_trains{
|
||||
has_passenger = false,
|
||||
is_manual = true,
|
||||
surface = surface,
|
||||
force = force,
|
||||
}
|
||||
|
||||
for _, train in ipairs(trains) do
|
||||
train.manual_mode = false
|
||||
end
|
||||
|
||||
game.print{ "exp-commands_trains.response", format_player_name(player), format_number(#trains, false) }
|
||||
end)
|
||||
18
exp_scenario/module/commands/vlayer.lua
Normal file
18
exp_scenario/module/commands/vlayer.lua
Normal file
@@ -0,0 +1,18 @@
|
||||
--[[-- Commands - VLayer
|
||||
Adds a virtual layer to store power to save space.
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local vlayer = require("modules.exp_legacy.modules.control.vlayer")
|
||||
|
||||
--- Print all vlayer information
|
||||
Commands.new("vlayer-info", { "exp-commands_vlayer.description" })
|
||||
:register(function(player)
|
||||
local index = 3
|
||||
local response = { "", "exp-commands_vlayer.title" } --- @type LocalisedString
|
||||
for title, value in pairs(vlayer.get_circuits()) do
|
||||
response[index] = { "exp-commands_vlayer.result", title, value }
|
||||
index = index + 1
|
||||
end
|
||||
return Commands.status.success(response)
|
||||
end)
|
||||
96
exp_scenario/module/commands/warnings.lua
Normal file
96
exp_scenario/module/commands/warnings.lua
Normal file
@@ -0,0 +1,96 @@
|
||||
--[[-- Commands - Warnings
|
||||
Adds a commands that allow admins to warn other players
|
||||
]]
|
||||
|
||||
local Commands = require("modules/exp_commands")
|
||||
local format_player_name = Commands.format_player_name_locale
|
||||
|
||||
local Warnings = require("modules.exp_legacy.modules.control.warnings") --- @dep modules.control.warnings
|
||||
local config = require("modules.exp_legacy.config.warnings") --- @dep config.warnings
|
||||
|
||||
--- Gives a warning to a player; may lead to automatic script action.
|
||||
Commands.new("create-warning", { "exp-commands_warnings.description-create" })
|
||||
:argument("player", { "exp-commands_warnings.arg-player-create" }, Commands.types.lower_role_player)
|
||||
:argument("reason", { "exp-commands_warnings.arg-reason" }, Commands.types.string)
|
||||
:enable_auto_concatenation()
|
||||
:add_aliases{ "warn" }
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player, other_player, reason)
|
||||
--- @cast other_player LuaPlayer
|
||||
--- @cast reason string
|
||||
Warnings.add_warning(other_player, player.name, reason)
|
||||
local player_name = format_player_name(player)
|
||||
local other_player_name = format_player_name(other_player)
|
||||
game.print{ "exp-commands_warnings.create", other_player_name, player_name, reason }
|
||||
end)
|
||||
|
||||
--- Gets a list of all warnings that a player has on them. If no player then lists all players and the number of warnings on them.
|
||||
Commands.new("get-warnings", { "exp-commands_warnings.description-get" })
|
||||
:optional("player", { "exp-commands_warnings.arg-player-get" }, Commands.types.player)
|
||||
:add_aliases{ "warnings" }
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player, other_player)
|
||||
--- @cast other_player LuaPlayer?
|
||||
if other_player then
|
||||
local warnings = Warnings.get_warnings(player)
|
||||
local script_warnings = Warnings.get_script_warnings(player)
|
||||
local other_player_name = format_player_name(other_player)
|
||||
Commands.print{ "exp-commands_warnings.player-title", other_player_name, #warnings, #script_warnings, config.temp_warning_limit }
|
||||
for _, warning in pairs(warnings) do
|
||||
local by_player_name_formatted = format_player_name(warning.by_player_name)
|
||||
Commands.print{ "exp-commands_warnings.list-element-player", by_player_name_formatted, warning.reason }
|
||||
end
|
||||
else
|
||||
local warnings = Warnings.user_warnings:get_all()
|
||||
local script_warnings = Warnings.user_script_warnings
|
||||
Commands.print{ "exp-commands_warnings.warnings-title" }
|
||||
for player_name, player_warnings in pairs(warnings) do
|
||||
local player_name_formatted = format_player_name(player_name)
|
||||
local script_warning_count = script_warnings[player_name] and #script_warnings[player_name] or 0
|
||||
Commands.print{ "exp-commands_warnings.list-element", player_name_formatted, #player_warnings, script_warning_count, config.temp_warning_limit }
|
||||
end
|
||||
for player_name, player_warnings in pairs(script_warnings) do
|
||||
if not warnings[player_name] then
|
||||
local player_name_formatted = format_player_name(player_name)
|
||||
Commands.print{ "exp-commands_warnings.list-element", player_name_formatted, 0, #player_warnings, config.temp_warning_limit }
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
--- Clears all warnings from a player
|
||||
Commands.new("clear-warnings", { "exp-commands_warnings.description-clear" })
|
||||
:argument("player", { "exp-commands_warnings.arg-player-clear" }, Commands.types.player)
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player, other_player)
|
||||
--- @cast other_player LuaPlayer
|
||||
Warnings.clear_warnings(other_player, player.name)
|
||||
Warnings.clear_script_warnings(other_player)
|
||||
local player_name = format_player_name(player)
|
||||
local other_player_name = format_player_name(other_player)
|
||||
game.print{ "exp-commands_warnings.cleared", other_player_name, player_name }
|
||||
end)
|
||||
|
||||
--- Clears all script warnings from a player
|
||||
Commands.new("clear-script-warnings", { "exp-commands_warnings.description-clear-script" })
|
||||
:argument("player", { "exp-commands_warnings.arg-player-clear" }, Commands.types.player)
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player, other_player)
|
||||
--- @cast other_player LuaPlayer
|
||||
Warnings.clear_script_warnings(other_player)
|
||||
local player_name = format_player_name(player)
|
||||
local other_player_name = format_player_name(other_player)
|
||||
game.print{ "exp-commands_warnings.cleared-script", other_player_name, player_name }
|
||||
end)
|
||||
|
||||
--- Clears the last warning that was given to a player
|
||||
Commands.new("clear-last-warnings", { "exp-commands_warnings.description-clear-last" })
|
||||
:argument("player", { "exp-commands_warnings.arg-player-clear" }, Commands.types.player)
|
||||
:add_flags{ "admin_only" }
|
||||
:register(function(player, other_player)
|
||||
--- @cast other_player LuaPlayer
|
||||
Warnings.remove_warning(other_player, player.name)
|
||||
local player_name = format_player_name(player)
|
||||
local other_player_name = format_player_name(other_player)
|
||||
game.print{ "exp-commands_warnings.cleared-last", other_player_name, player_name }
|
||||
end)
|
||||
69
exp_scenario/module/commands/waterfill.lua
Normal file
69
exp_scenario/module/commands/waterfill.lua
Normal file
@@ -0,0 +1,69 @@
|
||||
--[[-- Commands - Waterfill
|
||||
Adds a command that places shallow water
|
||||
]]
|
||||
|
||||
local AABB = require("modules/exp_util/aabb")
|
||||
local Commands = require("modules/exp_commands")
|
||||
local Selection = require("modules.exp_legacy.modules.control.selection") --- @dep modules.control.selection
|
||||
local SelectionName = "ExpCommand_Waterfill"
|
||||
|
||||
--- Toggle player selection mode for artillery
|
||||
Commands.new("waterfill", { "exp-commands_waterfill.description" })
|
||||
:register(function(player)
|
||||
if Selection.is_selecting(player, SelectionName) then
|
||||
Selection.stop(player)
|
||||
return Commands.status.success{ "exp-commands_waterfill.exit" }
|
||||
elseif player.get_item_count("cliff-explosives") == 0 then
|
||||
return Commands.status.error{ "exp-commands_waterfill.requires-explosives" }
|
||||
else
|
||||
Selection.start(player, SelectionName)
|
||||
return Commands.status.success{ "exp-commands_waterfill.enter" }
|
||||
end
|
||||
end)
|
||||
|
||||
--- When an area is selected to be converted to water
|
||||
Selection.on_selection(SelectionName, function(event)
|
||||
--- @cast event EventData.on_player_selected_area
|
||||
local area = AABB.expand(event.area)
|
||||
local player = game.players[event.player_index]
|
||||
local surface = event.surface
|
||||
|
||||
if surface.planet and surface.planet ~= game.planets.nauvis then
|
||||
player.print({ "exp-cods_waterfill.nauvis-only" }, Commands.print_settings.error)
|
||||
return
|
||||
end
|
||||
|
||||
local area_size = (area.right_bottom.x - area.left_top.x) * (area.right_bottom.y - area.left_top.y)
|
||||
if area_size > 1000 then
|
||||
player.print({ "exp-cods_waterfill.area-too-large", 1000, area_size }, Commands.print_settings.error)
|
||||
return
|
||||
end
|
||||
|
||||
local item_count = player.get_item_count("cliff-explosives")
|
||||
if item_count < area_size then
|
||||
player.print({ "exp-cods_waterfill.too-few-explosives", area_size, item_count }, Commands.print_settings.error)
|
||||
return
|
||||
end
|
||||
|
||||
local tile_count = 0
|
||||
local tiles_to_make = {}
|
||||
for x = area.left_top.x, area.right_bottom.x do
|
||||
for y = area.left_top.y, area.right_bottom.y do
|
||||
tile_count = tile_count + 1
|
||||
tiles_to_make[tile_count] = {
|
||||
name = "water-mud",
|
||||
position = { x, y },
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
surface.set_tiles(tiles_to_make, true, "abort_on_collision", true, false, player, 0)
|
||||
local remaining_tiles = surface.count_tiles_filtered{ area = area, name = "water-mud" }
|
||||
player.remove_item{ name = "cliff-explosives", count = tile_count - remaining_tiles }
|
||||
|
||||
if remaining_tiles > 0 then
|
||||
player.print({ "exp-cods_waterfill.part-complete", tile_count, remaining_tiles }, Commands.print_settings.default)
|
||||
else
|
||||
player.print({ "exp-cods_waterfill.complete", tile_count }, Commands.print_settings.default)
|
||||
end
|
||||
end)
|
||||
@@ -1,9 +1,43 @@
|
||||
local event_handler = require("event_handler")
|
||||
|
||||
--- @type fun(lib: { on_init: fun(), on_load: fun(), events: { [defines.events]: fun(event: EventData) } })
|
||||
local add = event_handler.add_lib
|
||||
|
||||
--- Command Extensions
|
||||
require("modules.exp_scenario/commands/types")
|
||||
require("modules.exp_scenario/commands/authorities")
|
||||
require("modules.exp_scenario/commands/_authorities")
|
||||
require("modules.exp_scenario/commands/_rcon")
|
||||
require("modules.exp_scenario/commands/_types")
|
||||
|
||||
--- Commands with events
|
||||
add(require("modules/exp_scenario/commands/protected_entities"))
|
||||
add(require("modules/exp_scenario/commands/protected_tags"))
|
||||
add(require("modules/exp_scenario/commands/research"))
|
||||
|
||||
--- Commands
|
||||
require("modules/exp_scenario/commands/admin_chat")
|
||||
require("modules/exp_scenario/commands/artillery")
|
||||
require("modules/exp_scenario/commands/bot_queues")
|
||||
require("modules/exp_scenario/commands/cheat")
|
||||
require("modules/exp_scenario/commands/clear_inventory")
|
||||
require("modules/exp_scenario/commands/connect")
|
||||
require("modules/exp_scenario/commands/debug")
|
||||
require("modules/exp_scenario/commands/enemy")
|
||||
require("modules/exp_scenario/commands/home")
|
||||
require("modules/exp_scenario/commands/jail")
|
||||
require("modules/exp_scenario/commands/kill")
|
||||
require("modules/exp_scenario/commands/lawnmower")
|
||||
require("modules/exp_scenario/commands/locate")
|
||||
require("modules/exp_scenario/commands/me")
|
||||
require("modules/exp_scenario/commands/rainbow")
|
||||
require("modules/exp_scenario/commands/ratio")
|
||||
require("modules/exp_scenario/commands/repair")
|
||||
require("modules/exp_scenario/commands/reports")
|
||||
require("modules/exp_scenario/commands/roles")
|
||||
require("modules/exp_scenario/commands/search")
|
||||
require("modules/exp_scenario/commands/spectate")
|
||||
require("modules/exp_scenario/commands/surface")
|
||||
require("modules/exp_scenario/commands/teleport")
|
||||
require("modules/exp_scenario/commands/trains")
|
||||
require("modules/exp_scenario/commands/vlayer")
|
||||
require("modules/exp_scenario/commands/warnings")
|
||||
require("modules/exp_scenario/commands/waterfill")
|
||||
|
||||
@@ -1,6 +1,282 @@
|
||||
[exp-commands-authorities_role]
|
||||
deny=Unauthorized, Access is denied due to missing permissions
|
||||
deny=Unauthorized, Access is denied due to missing permissions.
|
||||
|
||||
[exp-commands-parse_role]
|
||||
lower-role=Role is higher than your highest.
|
||||
lower-role-player=Player has a higher role.
|
||||
|
||||
[exp-commands_admin-chat]
|
||||
description=Sends a message in chat that only admins can see.
|
||||
arg-message=The message to send.
|
||||
format=[AC] __1__: __2__
|
||||
|
||||
[exp-commands_artillery]
|
||||
description=Automaticly select enemy target with artillery.
|
||||
invalid-area=The selected area is not valid.
|
||||
enter=Entered artillery selection mode.
|
||||
exit=Existed artillery selection mode.
|
||||
|
||||
[exp-commands_bot-queue]
|
||||
description-get=Get / Set the construction bot queue limits.
|
||||
arg-amount=Multiple of default value to set the queues to.
|
||||
get=Bot queue is __1__ successful attempts and __2__ failed attempts.
|
||||
set=__1__ set the bot queue to __2__ successful attempts and __3__ failed attempts.
|
||||
|
||||
[exp-commands_cheat]
|
||||
description-cheat-mode=Set cheat mode for your player, or another player.
|
||||
description-always-day=Set always day for your current surface, or another surface.
|
||||
description-friendly-fire=Set friendly fire for your force, or another force.
|
||||
description-research-all=Research all technology for your force, or another force.
|
||||
description-clear-pollution=Clear pollution from your current surface, or another surface.
|
||||
description-pollution-enabled=Set polution enabled state for this game.
|
||||
description=game-speed=Set or get the current game speed.
|
||||
arg-state=State to set, default is to toggle the current value.
|
||||
arg-player=Player to toggle cheat mode for.
|
||||
arg-force-friendly-fire=Force to research all technology for.
|
||||
arg-force-research=Force to research all technology for.
|
||||
arg-surface=Surface to toggle always day for.
|
||||
arg-amount=Amount to set, returns the current value if not given.
|
||||
cheat-mode=Cheat mode is now __1__
|
||||
always-day=__1__ has toggled always day on __2__ surface to __3__.
|
||||
friendly-fire=__1__ set friendly fire for __2__ to __3__.
|
||||
research-all=__1__ has enabled all technology for __2__ force.
|
||||
clear-pollution=__1__ has cleared pollution from __2__.
|
||||
pollution-enabled=__1__ has set the polution enabled state to __2__.
|
||||
game-speed-set=__1__ has set the game speed to __2__.
|
||||
game-speed-get=The current game speed is __1__.
|
||||
|
||||
[exp-commands_clear-inventory]
|
||||
description=Clears a players inventory, all items will be moved to the spawn point.
|
||||
arg-player=Player to clear the inventory of.
|
||||
|
||||
[exp-commands_connect]
|
||||
description=Connect to another server.
|
||||
description-player=Connect a player to a different server.
|
||||
description-all=Connect all players to another server.
|
||||
arg-player=Player to connect to another server.
|
||||
arg-server=Server name or address to connect to.
|
||||
arg-is-address=True when the input should be read as an address.
|
||||
too-many-matching=Multiple server were found with the given name: __1__
|
||||
wrong-version=Servers were found but are on a different version: __1__
|
||||
same-server=You are already connected to the server: __1__
|
||||
offline=You cannot connect as the server is currently offline: __1__
|
||||
none-matching=No servers were found with that name, if you used an address please append true to the end of your command.
|
||||
|
||||
[expcom-debug]
|
||||
description=Opens the debug gui.
|
||||
|
||||
[exp-commands_enemy]
|
||||
description-kill=Kill all enemy units.
|
||||
description-remove=Remove all enemy spawners.
|
||||
arg-surface=Surface to remove spawners from.
|
||||
|
||||
[exp-commands_home]
|
||||
description-home=Teleports you to your home location.
|
||||
description-return=Teleports you to previous location.
|
||||
description-get=Returns your current home location.
|
||||
description-set=Sets your home location to your current position.
|
||||
no-home=You have no home set on __1__.
|
||||
no-return=You can't return when /home has not been used on __1__.
|
||||
home-get=Your home point on __1__ is at x: __2__ y: __3__
|
||||
home-set=Your home point on __1__ has been set to x: __2__ y: __3__
|
||||
return-set=Your return point on __1__ has been set to x: __1__ y: __2__
|
||||
|
||||
[exp-commands_jail]
|
||||
description=Puts a player into jail and removes all other roles.
|
||||
arg-player=Player to jail.
|
||||
arg-reason=Reason to jail the player.
|
||||
jailed=__1__ was jailed by __2__. Reason: __3__
|
||||
already-jailed=__1__ is already jailed.
|
||||
|
||||
[exp-commands_unjail]
|
||||
description=Puts a player into jail and removes all other roles.
|
||||
arg-player=Player to unjail.
|
||||
unjailed=__1__ was unjailed by __2__.
|
||||
not-jailed=__1__ is not currently jailed.
|
||||
|
||||
[exp-commands_kill]
|
||||
description=Kills yourself or another player.
|
||||
arg-player=Player to kill.
|
||||
already-dead=You are already dead.
|
||||
lower-role=You must have a higher role than the target.
|
||||
|
||||
[exp-commands_lawnmower]
|
||||
description=Clean up biter corpse, decoratives and nuclear hole.
|
||||
arg-range=Range to clean up.
|
||||
|
||||
[exp-commands_locate]
|
||||
description=Opens remote view at the location of the player's last location.
|
||||
arg-player=Player to locate.
|
||||
arg-remote=If true opens at the location of the player's remote view.
|
||||
response=Last location of __1__ was [gps=__2__,__3__]
|
||||
|
||||
[exp-commands_me]
|
||||
description=Sends an action message in the chat.
|
||||
arg-action=Action you want to perform.
|
||||
response=* __1__ __2__ *
|
||||
|
||||
[expcom-protection]
|
||||
description-entity=Toggles entity protection selection, hold shift to remove protection
|
||||
description-area=Toggles area protection selection, hold shift to remove protection
|
||||
enter-entity-selection=Entered entity selection, select entites to protect, hold shift to remove protection.
|
||||
enter-area-selection=Entered area selection, select areas to protect, hold shift to remove protection.
|
||||
exit-entity=Exited entity protection selection.
|
||||
exit-area=Exited area protect selection.
|
||||
protected-entities=__1__ entities have been protected.
|
||||
unprotected-entities=__1__ entities have been unprotected.
|
||||
already-protected=This area is already protected.
|
||||
protected-area=This area is now protected.
|
||||
unprotected-area=This area is now unprotected.
|
||||
repeat-offence=__1__ has removed __2__ at [gps=__3__,__4__]
|
||||
|
||||
[exp-commands_protected-tags]
|
||||
description=Toggles protected tag mode, edit and create protected map tags.
|
||||
exit=You have left protected tag mode, any new tags will not be protected.
|
||||
enter=You have entered protected tag mode, any new tags will be protected.
|
||||
create=You have placed a protected tag.
|
||||
edit=You have edited a protected tag.
|
||||
revert-has-access=This tag is protected, use /__1__ to modify or remove.
|
||||
revert-no-access=This tag is protected, you can not modify or remove it.
|
||||
|
||||
[exp-commands_rainbow]
|
||||
description=Sends an rainbow message in the chat
|
||||
arg-message=Message to send in chat.
|
||||
response=__1__: __2__
|
||||
|
||||
[exp-commands_ratio]
|
||||
description=This command will give the input and output ratios of the selected machine. Use the parameter for calculating the machines needed for that amount of items per second.
|
||||
arg-items-per-second=Target items per second, defaults to output of a single machine.
|
||||
not-selecting=Please select an entity with a recipe.
|
||||
item-in=You need __1__ per second of [item=__2__].
|
||||
fluid-in=You need __1__ per second of [fluid=__2__].
|
||||
item-out=This will result in: __1__ [item=__2__] per second.
|
||||
fluid-out=This will result in: __1__ [fluid=__2__] per second.
|
||||
machine-count=And you will need __1__ machines (with the same speed as this one) for this.
|
||||
|
||||
[exp-commands_repair]
|
||||
description=Repairs entities on your force around you.
|
||||
arg-range=Range to repair entities within.
|
||||
# Intentional space left on the two lines below so they can be joined together.
|
||||
response-revive=__1__ entities were revived.
|
||||
response-heal=__1__ entities were healed.
|
||||
|
||||
[exp-commands_reports]
|
||||
description-create=Reports a player and notifies moderators
|
||||
description-get=Gets a list of all reports that a player has on them. If no player then lists all players and the number of reports on them.
|
||||
description-clear=Clears all reports from a player or just the report from one player.
|
||||
arg-player-create=Player you want to report.
|
||||
arg-player-get=Player to get the reports of.
|
||||
arg-player-clear=Player to clear the reports of.
|
||||
arg-reason=Reason you want to report this player.
|
||||
arg-from-player=Only remove the report from this player.
|
||||
player-immune=This player can not be reported.
|
||||
self-report=You cannot report yourself.
|
||||
response=__1__ was reported for __2__.
|
||||
response-admin=__1__ was reported by __2__ for __3__.
|
||||
already-reported=You can only report a player once, you can ask a moderator to clear this report.
|
||||
not-reported=The player had no reports on them.
|
||||
not-reported-by=The player had no reports on them from __1__.
|
||||
reports-title=The following players have reports against them:
|
||||
player-title=__1__ has __2__ __plural_for_parameter__2__{1=report|rest=reports}__ against them:
|
||||
list-element=__1__: __2__
|
||||
removed-all=__1__ has has all of their reports removed by __2__.
|
||||
removed=__1__ has a report removed by __2__.
|
||||
|
||||
[exp-commands_research]
|
||||
description-ares=Sets research to be automatically queued.
|
||||
arg-state=State to set, default is to toggle.
|
||||
auto-research=__1__ set auto research to __2__
|
||||
queue=[color=255, 255, 255] Research added to queue - [technology=__1__] - __2__[/color]
|
||||
|
||||
[exp-commands_roles]
|
||||
description-assign-role=Assigns a role to a player.
|
||||
description-unassign-role=Unassigns a role from a player.
|
||||
description-get=Get all roles that a player has, if no player provided it lists all roles.
|
||||
arg-player-assign=Player to assign the role to.
|
||||
arg-player-unassign=Player to unassign the role from.
|
||||
arg-player-get=Player to get the roles of.
|
||||
arg-role-assign=Role to assign to the player.
|
||||
arg-role-unassign=Role to unasign from the player.
|
||||
list-roles=All roles: __1__
|
||||
list-player=__2__ has: __1__
|
||||
list-element=__1__,
|
||||
|
||||
[exp-commands_search]
|
||||
description-search=Display players sorted by the quantity of an item held and playtime.
|
||||
description-online=Display online players sorted by the quantity of an item held and playtime.
|
||||
description-amount=Display players sorted by the quantity of an item held.
|
||||
description-recent=Display players who hold an item sorted by join time.
|
||||
invalid-item=No item was found with internal name __1__; try using rich text selection.
|
||||
no-results=No players have [item=__1__]
|
||||
title=Players found with [item=__1__]:
|
||||
result=\n__1__) __2__ has __3__ items. (__4__)
|
||||
|
||||
[exp-commands_spectate]
|
||||
description-spectate=Toggles spectator mode.
|
||||
description-follow=Start following a player in spectator.
|
||||
arg-player=Player to start following.
|
||||
follow-self=You can not follow yourself.
|
||||
|
||||
[exp-commands_surface]
|
||||
description-items=Clear all items on the ground.
|
||||
description-blueprints=Clear all blueprints.
|
||||
description-radius=Clear all blueprints in an radius around you.
|
||||
arg-surface=Surface to clear on, default all.
|
||||
arg-radis=Radius to clear.
|
||||
items-surface=__1__ cleared all items on the ground of __2__.
|
||||
items-all=__1__ cleared all items on the ground for all surfaces.
|
||||
blueprints-surface=__1__ cleared all blueprints on __2__.
|
||||
blueprints-all=__1__ cleared all blueprints for all surfaces.
|
||||
blueprints-radius=__1__ cleared all blueprints in a __2__ radius around them on __3__.
|
||||
|
||||
[exp-commands_trains]
|
||||
description=Set All Trains to Automatic, does not effect trains with passengers.
|
||||
arg-force=Force to set the trains for, default all.
|
||||
arg-surface=Surface to set the trains for, default all.
|
||||
response=__1__ set __2__ trains into automatic mode.
|
||||
|
||||
[exp-commands_teleport]
|
||||
description-teleport=Teleports a player to another player.
|
||||
description-bring=Teleports a player to you.
|
||||
description-goto=Teleports you to a player.
|
||||
description-spawn=Teleport to spawn
|
||||
arg-player-teleport=Player to teleport, if target is not given then you are teleported to this player.
|
||||
arg-player-from=Player to teleported.
|
||||
arg-player-to=Player who is the target.
|
||||
unavailable=They was a problem teleporting you, likely no position found, please try again later.
|
||||
same-player=Player can not be teleported to themselves.
|
||||
|
||||
[exp-commands_vlayer]
|
||||
description=Print all vlayer information.
|
||||
title=VLayer Information:
|
||||
result=__1__: __2__
|
||||
|
||||
[exp-commands_warnings]
|
||||
description-create=Gives a warning to a player; may lead to automatic script action.
|
||||
description-get=Gets the number of warnings a player has. If no player then lists all players and the number of warnings they have.
|
||||
description-clear=Clears all warnings (and script warnings) from a player.
|
||||
description-clear-script=Clears all script warnings from a player.
|
||||
description-clear-last=Clears the last warning from a player.
|
||||
arg-player-create=Player to give the warning to.
|
||||
arg-player-get=Player to get the warning of, if not given all players are returned.
|
||||
arg-player=clear=Player to clear the warnings of.
|
||||
arg-reason=Reason the user is receiving a warning.
|
||||
create=__1__ received a warning from __2__ for __3__.
|
||||
player-title=__1__ has __2__ warnings and __3__/__4__ script warnings.
|
||||
list-element-player=__1__: __2__
|
||||
warnings-title=The following players have warnings aginst them (and script warnings):
|
||||
list-element=__1__: __2__ (__3__/__4__)
|
||||
cleared=__1__ had all their warnings cleared by __2__.
|
||||
cleared-script=__1__ had all their script warnings cleared by __2__.
|
||||
cleared-last=__1__ had their last warning cleared by __2__.
|
||||
|
||||
[exp-commands_waterfill]
|
||||
description=Replace tiles with shallow water.
|
||||
requires-explosives=__ITEM__cliff-explosives__ are required to create water.
|
||||
enter=Entered waterfill selection mode, select the area to fill with water.
|
||||
exit=Exited water fill seclection mode.
|
||||
nauvis-only=Can only waterfill on Nauvis, this may change in the future.
|
||||
area-too-large=Selected area is too large, must be less than __1__ tiles, selected __2__.
|
||||
too-few-explosives=Requires __1__ __ITEM__cliff-explosives__ you have __2__.
|
||||
part-complete=__1__ tiles were filled with water, but entities are blocking __2__ tiles.
|
||||
complete=__1__ tiles were filled with water.
|
||||
|
||||
Reference in New Issue
Block a user