feature/control-separation

This commit is contained in:
Cooldude2606
2019-07-22 16:31:05 +01:00
435 changed files with 52086 additions and 22747 deletions

View File

@@ -76,7 +76,7 @@ end
--- Reports added and removed
if config.player_reports then
local Reports = require 'modules.addons.reports-control'
local Reports = require 'modules.control.reports'
Event.add(Reports.events.on_player_reported,function(event)
local player_name,by_player_name = get_player_name(event)
emit_event{
@@ -88,32 +88,33 @@ if config.player_reports then
['Reason:']=event.reason
}
end)
Event.add(Reports.events.on_player_report_removed,function(event)
local player_name,by_player_name = get_player_name(event)
Event.add(Reports.events.on_report_removed,function(event)
local player_name = get_player_name(event)
emit_event{
title='Report Removed',
description='A player has a report removed',
color=Colors.green,
['Player:']='<inline>'..player_name,
['By:']='<inline>'..by_player_name
['By:']='<inline>'..event.removed_by_name
}
end)
end
--- Warnings added and removed
if config.player_warnings then
local Warnings = require 'modules.addons.warnings-control'
Event.add(Warnings.events.on_player_warned,function(event)
local Warnings = require 'modules.control.warnings'
Event.add(Warnings.events.on_warning_added,function(event)
local player_name,by_player_name = get_player_name(event)
emit_event{
title='Warning',
description='A player has been given a warning',
color=Colors.yellow,
['Player:']='<inline>'..player_name,
['By:']='<inline>'..by_player_name
['By:']='<inline>'..by_player_name,
['Reason:']=event.reason
}
end)
Event.add(Warnings.events.on_player_warning_removed,function(event)
Event.add(Warnings.events.on_warning_removed,function(event)
local player_name,by_player_name = get_player_name(event)
emit_event{
title='Warning Removed',

View File

@@ -1,99 +0,0 @@
local Roles = require 'expcore.roles'
local Game = require 'utils.game'
local Global = require 'utils.global'
local move_items = ext_require('expcore.common','move_items')
local Jail = {
old_roles = {},
temp_bans = {},
events = {
on_player_jailed=script.generate_event_name(),
on_player_unjailed=script.generate_event_name(),
on_player_temp_banned=script.generate_event_name(),
on_player_temp_ban_cleared=script.generate_event_name()
}
}
Global.register({
old_roles = Jail.old_roles,
temp_bans = Jail.temp_bans
},function(tbl)
Jail.old_roles = tbl.old_roles
Jail.temp_bans = tbl.temp_bans
end)
local function event_emit(event,player,by_player_name,reason)
script.raise_event(event,{
name=event,
tick=game.tick,
player_index=player.index,
by_player_name=by_player_name,
reason=reason
})
end
--- Jails a player, this is only the logic there is no output to players
-- @tparam LuaPlayer player the player that will be jailed, must not be in jail
-- @tparam[opt='<server>'] string by_player_name the name of the player doing the action used in logs
-- @treturn the number of roles that were removed, nil if there was an error
function Jail.jail_player(player,by_player_name)
player = Game.get_player_from_any(player)
if not player then return end
if Roles.player_has_role(player,'Jail') then return end
local old_roles = Roles.get_player_roles(player)
Jail.old_roles[player.name] = old_roles
Roles.unassign_player(player,old_roles,by_player_name,true)
Roles.assign_player(player,'Jail',by_player_name,true)
event_emit(Jail.events.on_player_jailed,player,by_player_name)
return #old_roles
end
--- Unjails a player, this is only the logic there is no output to players
-- @tparam LuaPlayer player the player that will be unjailed, must be in jail
-- @tparam[opt='<server>'] string string by_player_name the name of the player who is doing the action
-- @treturn the number of roles that were added, nil if there was an error
function Jail.unjail_player(player,by_player_name)
player = Game.get_player_from_any(player)
if not player then return end
if not Roles.player_has_role(player,'Jail') then return end
local old_roles = Jail.old_roles[player.name]
Roles.unassign_player(player,'Jail',by_player_name,true)
Roles.assign_player(player,old_roles,by_player_name,true)
event_emit(Jail.events.on_player_unjailed,player,by_player_name)
return #old_roles
end
--- Temp bans a player which is similar to jail but will store the reason for the action and clears items
-- @tparam LuaPlayer player the player that will be temp baned, must not be temp banned
-- @tparam[opt='<server>'] string by_player_name the name of the player that is doing the action
-- @tparam[opt='None string Given.'] reason the reason that will be stored for this temp ban
-- @treturn boolean true if successful else will return nil
function Jail.temp_ban_player(player,by_player_name,reason)
player = Game.get_player_from_any(player)
reason = reason or 'None Given.'
if not player then return end
if Jail.temp_bans[player.name] then return end
Jail.jail_player(player,by_player_name)
Jail.temp_bans[player.name] = {reason,by_player_name}
local inv = player.get_main_inventory()
move_items(inv.get_contents())
inv.clear()
event_emit(Jail.events.on_player_temp_banned,player,by_player_name,reason)
return true
end
--- Removes temp ban from a player, note this does not restore the items
-- @tparam LuaPlayer player the player that will be cleared from temp baned, must be temp banned
-- @tparam[opt='<server>'] string by_player_name the name of the player that is doing the action
-- @treturn boolean true if successful else will return nil
function Jail.clear_temp_ban_player(player,by_player_name)
player = Game.get_player_from_any(player)
if not player then return end
if not Jail.temp_bans[player.name] then return end
Jail.unjail_player(player,by_player_name)
Jail.temp_bans[player.name] = nil
event_emit(Jail.events.on_player_temp_ban_cleared,player,by_player_name)
return true
end
return Jail

View File

@@ -1,141 +0,0 @@
local Game = require 'utils.game'
local Global = require 'utils.global'
local Reports = {
user_reports={},
events = {
on_player_reported = script.generate_event_name(),
on_player_report_removed = script.generate_event_name()
}
}
Global.register(Reports.user_reports,function(tbl)
Reports.user_reports = tbl
end)
local function event_emit(event,player,by_player_name)
local reports = Reports.user_reports[player.name]
local reason = reports and reports[by_player_name]
script.raise_event(event,{
name=event,
tick=game.tick,
player_index=player.index,
by_player_name=by_player_name,
reason=reason
})
end
--- Adds a report to a player, reports are stored in global table and can be accessed later
-- @tparam LuaPlayer player the player that will be reported
-- @tparam[opt='Non string Given.'] reason the reason that the player is being reported
-- @tparam[opt='<server>'] string by_player_name the name of the player doing the action
-- @treturn boolean true if the report was added, nil if there is an error
function Reports.report_player(player,reason,by_player_name)
player = Game.get_player_from_any(player)
if not player then return end
reason = reason or 'Non Given.'
by_player_name = by_player_name or '<server>'
local reports = Reports.user_reports[player.name]
if not reports then
Reports.user_reports[player.name] = {
[by_player_name] = reason
}
elseif not reports[by_player_name] then
reports[by_player_name] = reason
else return false end
event_emit(Reports.events.on_player_reported,player,by_player_name)
return true
end
--- Removes a report from a player by the given player, see clear_player_reports to remove all
-- @tparam LuaPlayer player the player that will have the report removed
-- @tparam[opt='<server>'] string by_player_name the name of the player doing the action
-- @treturn boolean true if the report was removed, nil if there was an error
function Reports.remove_player_report(player,by_player_name)
player = Game.get_player_from_any(player)
if not player then return end
by_player_name = by_player_name or '<server>'
local reports = Reports.user_reports[player.name]
if reports and reports[by_player_name] then
event_emit(Reports.events.on_player_report_removed,player,by_player_name)
reports[by_player_name] = nil
if Reports.count_player_reports(player) == 0 then
Reports.user_reports[player.name] = nil
end
return true
end
return false
end
--- Clears all reports from a player, will emit an event for each individual report as if remove_player_report was used
-- @tparam LuaPlayer player the player to clear the reports of
-- @treturn boolean true if the reports were cleared, nil if error
function Reports.clear_player_reports(player)
player = Game.get_player_from_any(player)
if not player then return end
local reports = Reports.user_reports[player.name]
if reports then
for by_player_name,reason in pairs(reports) do
event_emit(Reports.events.on_player_report_removed,player,by_player_name)
end
Reports.user_reports[player.name] = nil
return true
end
return false
end
--- Test for if a player has been reported by another player, can also return the reason from that player
-- @tparam LuaPlayer player the player to check the reports of
-- @tparam string by_player_name the player that made if the report if present (note server is not default here)
-- @tparam[opt=false] boolean rtn_reason true will return the reason for the report rather than a boolean
-- @treturn boolean true if a report from the player is present unless rtn_reason is true when a string is returned (or false)
function Reports.player_is_reported_by(player,by_player_name,rtn_reason)
player = Game.get_player_from_any(player)
if not player then return end
local reports = Reports.user_reports[player.name]
if reports and reports[by_player_name] then
return rtn_reason and reports[by_player_name] or true
end
return false
end
--- Gets all the reports that are on a player
-- @tparam LuaPlayer player the player to get the reports of
-- @treturn table a table of all the reports for this player, empty table if no reports
function Reports.get_player_reports(player)
player = Game.get_player_from_any(player)
if not player then return end
return Reports.user_reports[player.name] or {}
end
--- Counts all reports on a player returning a number, a custom count function can be given which should return a number
-- @tparam LuaPlayer player the player to count the reports of
-- @tparam[opt] number function count_callback should return a or true (for 1) this will be passed every report on the player
-- count_callback param - player_name string - the name of the player who made the report
-- count_callback param - reason string - the reason the reason was made
-- count_callback return - number or boolean - if number then this will be added to the count, if boolean then false = 0 and true = 1
-- @treturn number the number of reports on the player
function Reports.count_player_reports(player,count_callback)
player = Game.get_player_from_any(player)
if not player then return end
local reports = Reports.user_reports[player.name] or {}
if not count_callback then
local ctn = 0
for _ in pairs(reports) do
ctn=ctn+1
end
return ctn
else
local ctn = 0
for player_name,reason in pairs(reports) do
local success,err = pcall(count_callback,player_name,reason)
if success and err then
if err == true then err = 1 end
ctn = ctn+err
end
end
return ctn
end
end
return Reports

View File

@@ -1,221 +0,0 @@
local Game = require 'utils.game'
local Global = require 'utils.global'
local Event = require 'utils.event'
local config = require 'config.warnings'
local format_chat_player_name = ext_require('expcore.common','format_chat_player_name')
require 'utils.table'
local Warnings = {
user_warnings={},
user_temp_warnings={},
events = {
on_player_warned = script.generate_event_name(),
on_player_warning_removed = script.generate_event_name(),
on_temp_warning_added = script.generate_event_name(),
on_temp_warning_removed = script.generate_event_name(),
}
}
Global.register({
user_warnings = Warnings.user_warnings,
user_temp_warnings = Warnings.user_temp_warnings
},function(tbl)
Warnings.user_warnings = tbl.user_warnings
Warnings.user_temp_warnings = tbl.user_temp_warnings
end)
local function event_emit(event,player,by_player_name)
local warnings = Warnings.user_warnings[player.name] or {}
local temp_warnings = Warnings.user_temp_warnings[player.name] or {}
script.raise_event(event,{
name=event,
tick=game.tick,
player_index=player.index,
by_player_name=by_player_name,
warning_count=#warnings,
temp_warning_count=#temp_warnings
})
end
--- Adds X number (default 1) of warnings to a player from the given player
-- @tparam LuaPlayer player the player to add the warning to
-- @tparam[opt='<server>'] string by_player_name the name of the player doing the action
-- @tparam[opt=1] number count the number of warnings to add
-- @treturn number the new number of warnings
function Warnings.add_warnings(player,by_player_name,count)
player = Game.get_player_from_any(player)
if not player then return end
count = count or 1
by_player_name = by_player_name or '<server>'
local warnings = Warnings.user_warnings[player.name]
if not warnings then
Warnings.user_warnings[player.name] = {}
warnings = Warnings.user_warnings[player.name]
end
for _=1,count do
table.insert(warnings,by_player_name)
event_emit(Warnings.events.on_player_warned,player,by_player_name)
end
return #warnings
end
--- Removes X number (default 1) of warnings from a player, removes in order fifo
-- @tparam LuaPlayer player the player to remove the warnings from
-- @tparam[opt='<server>'] string by_playey_name the name of the player doing the action
-- @tparam[opt=1] number count the number of warnings to remove (if greater than current warning count then all are removed)
-- @treturn number the new number of warnings
function Warnings.remove_warnings(player,by_player_name,count)
player = Game.get_player_from_any(player)
if not player then return end
count = count or 1
by_player_name = by_player_name or '<server>'
local warnings = Warnings.user_warnings[player.name]
if not warnings then return end
for _=1,count do
if #warnings == 0 then break end
table.remove(warnings,1)
event_emit(Warnings.events.on_player_warning_removed,player,by_player_name)
end
if #warnings == 0 then
Warnings.user_warnings[player.name] = nil
return 0
end
return #warnings
end
--- Clears all warnings from a player, emits event multiple times as if remove_warnings was used
-- @tparam LuaPlayer player the player to clear the warnings of
-- @tparam[oot='<server>'] string by_player_name the name of the player who is doing the action
-- @treturn boolean true if the warnings were cleared, nil if error
function Warnings.clear_warnings(player,by_player_name)
player = Game.get_player_from_any(player)
if not player then return end
local warnings = Warnings.user_warnings[player.name]
if not warnings then return end
by_player_name = by_player_name or '<server>'
for _=1,#warnings do
event_emit(Warnings.events.on_player_warning_removed,player,by_player_name)
end
Warnings.user_warnings[player.name] = {}
return true
end
--- Gets the number of warnings that a player has, raw table will contain the names of who gave warnings
-- @tparam LuaPlayer player the player to get the warnings of
-- @tparam[opt=false] table table raw_table when true will return a which contains who gave warnings (the stored in global)
-- @treturn number the number of warnings a player has, a table if raw_table is true
function Warnings.get_warnings(player,raw_table)
player = Game.get_player_from_any(player)
if not player then return end
local warnings = Warnings.user_warnings[player.name] or {}
if raw_table then
return warnings
else
return #warnings
end
end
--- Adds a temp warning to a player that will timeout after some time, used for script given warnings (ie silent to outside players as a buffer)
-- @tparam LuaPlayer player the player to give the warnings to
-- @tparam[opt=1] number count the number of warnings to give to the player
-- @treturn number the new number of warnings
function Warnings.add_temp_warnings(player,count)
player = Game.get_player_from_any(player)
if not player then return end
count = count or 1
local warnings = Warnings.user_temp_warnings[player.name]
if not warnings then
Warnings.user_temp_warnings[player.name] = {}
warnings = Warnings.user_temp_warnings[player.name]
end
for _=1,count do
table.insert(warnings,game.tick)
event_emit(Warnings.events.on_temp_warning_added,player,'<server>')
end
return #warnings
end
-- temp warnings cant be removed on demand only after X amount of time
local temp_warning_cool_down = config.temp_warning_cool_down*3600
Event.on_nth_tick(temp_warning_cool_down/4,function()
local check_time = game.tick-temp_warning_cool_down
for player_name,temp_warnings in pairs(Warnings.user_temp_warnings) do
local player = Game.get_player_from_any(player)
for index,time in pairs(temp_warnings) do
if time <= check_time then
table.remove(temp_warnings,index)
player.print{'warnings.script-warning-removed',#temp_warnings,config.temp_warning_limit}
event_emit(Warnings.events.on_temp_warning_removed,player,'<server>')
end
end
if #temp_warnings == 0 then
Warnings.user_temp_warnings[player_name] = nil
end
end
end)
--- Clears all temp warnings from a player, emits events as if the warnings had been removed due to time
-- @tparam LuaPlayer player the player to clear the warnings of
-- @tparam[opt='<server>'] string by_player_name the name of the player doing the action
-- @treturn boolean true if the warnings were cleared, nil for error
function Warnings.clear_temp_warnings(player,by_player_name)
player = Game.get_player_from_any(player)
if not player then return end
local warnings = Warnings.user_temp_warnings[player.name]
if not warnings then return end
by_player_name = by_player_name or '<server>'
for _=1,#warnings do
event_emit(Warnings.events.on_temp_warning_removed,player,by_player_name)
end
Warnings.user_temp_warnings[player.name] = {}
return true
end
--- Gets the number of temp warnings, raw table is a table of when temp warnings were given
-- @tparam LuaPlayer player the player to get the warnings of
-- @tparam[opt=false] table raw_table if true will return a of ticks when warnings were added (the global table)
-- @treturn number the number of warnings which the player has, a table if raw_table is true
function Warnings.get_temp_warnings(player,raw_table)
player = Game.get_player_from_any(player)
if not player then return end
local warnings = Warnings.user_temp_warnings[player.name] or {}
if raw_table then
return warnings
else
return #warnings
end
end
-- when a player gets a warning the actions in config are ran
Event.add(Warnings.events.on_player_warned,function(event)
local action = config.actions[event.warning_count]
if not action then return end
local player = Game.get_player_by_index(event.player_index)
if type(action) == 'function' then
-- player: player who got the warnings,by_player_name: player who gave the last warning,number_of_warnings: the current number of warnings
local success,err = pcall(action,player,event.by_player_name,event.warning_count)
if not success then error(err) end
elseif type(action) == 'table' then
-- {locale,by_player_name,number_of_warning,...}
local current_action = table.deep_copy(action)
table.insert(current_action,2,event.by_player_name)
table.insert(current_action,3,event.warning_count)
player.print(current_action)
elseif type(action) == 'string' then
player.print(action)
end
end)
-- when a player gets a tempo warnings it is checked that it is not above the max
Event.add(Warnings.events.on_temp_warning_added,function(event)
local player = Game.get_player_by_index(event.player_index)
if event.temp_warning_count > config.temp_warning_limit then
Warnings.add_warnings(event.player_index,event.by_player_name)
local player_name_color = format_chat_player_name(player)
game.print{'warnings.script-warning-limit',player_name_color}
else
player.print{'warnings.script-warning',event.temp_warning_count,config.temp_warning_limit}
end
end)
return Warnings

View File

@@ -1,5 +1,5 @@
local Commands = require 'expcore.commands'
local JailControl = require 'modules.addons.jail-control'
local Jail = require 'modules.control.jail'
local format_chat_player_name = ext_require('expcore.common','format_chat_player_name')
require 'config.expcore-commands.parse_roles'
@@ -11,7 +11,7 @@ Commands.new_command('jail','Puts a player into jail and removes all other roles
reason = reason or 'Non Given.'
local action_player_name_color = format_chat_player_name(action_player)
local by_player_name_color = format_chat_player_name(player)
if JailControl.jail_player(action_player,player.name) then
if Jail.jail_player(action_player,player.name,reason) then
game.print{'expcom-jail.give',action_player_name_color,by_player_name_color,reason}
else
return Commands.error{'expcom-jail.already-jailed',action_player_name_color}
@@ -25,7 +25,7 @@ Commands.new_command('unjail','Removes a player from jail.')
:register(function(player,action_player,raw)
local action_player_name_color = format_chat_player_name(action_player)
local by_player_name_color = format_chat_player_name(player)
if JailControl.unjail_player(action_player,player.name) then
if Jail.unjail_player(action_player,player.name) then
game.print{'expcom-jail.remove',action_player_name_color,by_player_name_color}
else
return Commands.error{'expcom-jail.not-jailed',action_player_name_color}
@@ -39,7 +39,7 @@ Commands.new_command('temp-ban','Temp bans a player until the next reset; this r
:register(function(player,action_player,reason,raw)
local action_player_name_color = format_chat_player_name(action_player)
local by_player_name_color = format_chat_player_name(player)
if JailControl.temp_ban_player(action_player,player.name,reason) then
if Jail.temp_ban_player(action_player,player.name,reason) then
game.print{'expcom-jail.temp-ban',action_player_name_color,by_player_name_color,reason}
else
return Commands.error{'expcom-jail.already-banned',action_player_name_color}
@@ -53,7 +53,7 @@ Commands.new_command('clear-temp-ban','Removes temp ban from a player; this will
:register(function(player,action_player,raw)
local action_player_name_color = format_chat_player_name(action_player)
local by_player_name_color = format_chat_player_name(player)
if JailControl.clear_temp_ban_player(action_player,player.name) then
if Jail.untemp_ban_player(action_player,player.name) then
game.print{'expcom-jail.temp-ban-clear',action_player_name_color,by_player_name_color}
else
return Commands.error{'expcom-jail.not-temp-banned',action_player_name_color}

View File

@@ -1,6 +1,6 @@
local Roles = require 'expcore.roles'
local Commands = require 'expcore.commands'
local ReportsControl = require 'modules.addons.reports-control'
local Reports = require 'modules.control.reports'
local format_chat_player_name = ext_require('expcore.common','format_chat_player_name')
require 'config.expcore-commands.parse_general'
@@ -20,7 +20,7 @@ end)
:register(function(player,action_player,reason,raw)
local action_player_name_color = format_chat_player_name(action_player)
local by_player_name_color = format_chat_player_name(player)
if ReportsControl.report_player(action_player,reason,player.name) then
if Reports.report_player(action_player,player.name,reason) then
game.print{'expcom-report.non-admin',action_player_name_color,reason}
Roles.print_to_roles_higher('Trainee',{'expcom-report.admin',action_player_name_color,by_player_name_color,reason})
else
@@ -33,7 +33,7 @@ Commands.new_command('get-reports','Gets a list of all reports that a player has
:add_alias('reports','list-reports')
:register(function(player,action_player,raw)
if action_player then
local reports = ReportsControl.get_player_reports(action_player)
local reports = Reports.get_reports(action_player)
local action_player_name_color = format_chat_player_name(action_player)
Commands.print{'expcom-report.player-report-title',action_player_name_color}
for player_name,reason in pairs(reports) do
@@ -41,11 +41,11 @@ Commands.new_command('get-reports','Gets a list of all reports that a player has
Commands.print{'expcom-report.list',by_player_name_color,reason}
end
else
local user_reports = ReportsControl.user_reports
local user_reports = Reports.user_reports
Commands.print{'expcom-report.player-count-title'}
for player_name,reports in pairs(user_reports) do
local player_name_color = format_chat_player_name(player_name)
local report_count = ReportsControl.count_player_reports(player_name)
local report_count = Reports.count_reports(player_name)
Commands.print{'expcom-report.list',player_name_color,report_count}
end
end
@@ -56,11 +56,11 @@ Commands.new_command('clear-reports','Clears all reports from a player or just t
:add_param('from-player',true,'player')
:register(function(player,action_player,from_player,raw)
if from_player then
if not ReportsControl.remove_player_report(action_player,from_player.name) then
if not Reports.remove_report(action_player,from_player.name,player.name) then
return Commands.error{'expcom-report.not-reported'}
end
else
if not ReportsControl.clear_player_reports(action_player) then
if not Reports.remove_all(action_player,player.name) then
return Commands.error{'expcom-report.not-reported'}
end
end

View File

@@ -1,5 +1,5 @@
local Commands = require 'expcore.commands'
local WarningsControl = require 'modules.addons.warnings-control'
local Warnings = require 'modules.control.warnings'
local format_chat_player_name = ext_require('expcore.common','format_chat_player_name')
local config = require 'config.warnings'
require 'config.expcore-commands.parse_roles'
@@ -10,7 +10,7 @@ Commands.new_command('give-warning','Gives a warning to a player; may lead to au
:add_alias('warn')
:enable_auto_concat()
:register(function(player,action_player,reason,raw)
WarningsControl.add_warnings(action_player,player.name)
Warnings.add_warning(action_player,player.name,reason)
local action_player_name_color = format_chat_player_name(action_player)
local by_player_name_color = format_chat_player_name(player)
game.print{'expcom-warnings.received',action_player_name_color,by_player_name_color,reason}
@@ -21,18 +21,18 @@ Commands.new_command('get-warnings','Gets the number of warnings a player has. I
:add_alias('warnings','list-warnings')
:register(function(player,action_player,raw)
if action_player then
local warnings = WarningsControl.get_warnings(action_player)
local script_warnings = WarningsControl.get_temp_warnings(action_player)
local warnings = Warnings.get_warnings(action_player)
local script_warnings = Warnings.get_script_warnings(action_player)
local action_player_name_color = format_chat_player_name(action_player)
Commands.print{'expcom-warnings.player',action_player_name_color,warnings,script_warnings,config.temp_warning_limit}
else
local rtn = {}
local user_warnings = WarningsControl.user_warnings
local user_temp_warnings = WarningsControl.user_temp_warnings
local user_warnings = Warnings.user_warnings
local user_script_warnings = Warnings.user_script_warnings
for player_name,warnings in pairs(user_warnings) do
rtn[player_name] = {#warnings,0}
end
for player_name,warnings in pairs(user_temp_warnings) do
for player_name,warnings in pairs(user_script_warnings) do
if not rtn[player_name] then
rtn[player_name] = {0,0}
end
@@ -49,8 +49,8 @@ end)
Commands.new_command('clear-warnings','Clears all warnings (and script warnings) from a player')
:add_param('player',false,'player')
:register(function(player,action_player,raw)
WarningsControl.clear_warnings(action_player,player.name)
WarningsControl.clear_temp_warnings(action_player,player.name)
Warnings.clear_warnings(action_player,player.name)
Warnings.clear_script_warnings(action_player,player.name)
local action_player_name_color = format_chat_player_name(action_player)
local by_player_name_color = format_chat_player_name(player)
game.print{'expcom-warnings.cleared',action_player_name_color,by_player_name_color}

220
modules/control/jail.lua Normal file
View File

@@ -0,0 +1,220 @@
--[[-- Control Module - Jail
- Adds a way to jail players and temp ban players.
@control Jail
@alias Jail
@usage
-- import the module from the control modules
local Jail = require 'modules.control.jail'
-- This will move 'MrBiter' to the jail role and remove all other roles from them
-- the player name and reason are only so they can be included in the event for user feedback
Jail.jail_player('MrBiter','Cooldude2606','Likes biters too much')
-- This will give 'MrBiter' all his roles back and remove him from jail
-- again as above the player name is only used in the event for user feedback
Jail.unjail_player('MrBiter','Cooldude2606')
-- Temp ban works the same as jail but will store the reason and move the players items to spawn
-- this is meant to be used as a more permiment jail but not as strong as a ban
Jail.temp_ban_player('MrBiter','Cooldude2606','Likes biters too much')
]]
--- Allows moving players into the jail role
-- @dep expcore.roles
local Roles = require 'expcore.roles'
--- Allows accessing a player from any value
-- @dep utils.game
local Game = require 'utils.game'
--- Allows storing data in the global table
-- @dep utils.global
local Global = require 'utils.global'
--- Use of move_items to clear inventroies
-- @dep expcore.common
local move_items = ext_require('expcore.common','move_items')
local valid_player = Game.get_player_from_any
local assign_roles = Roles.assign_player
local unassign_roles = Roles.unassign_player
local has_role = Roles.player_has_role
local get_roles = Roles.get_player_roles
local Jail = {
old_roles = {},
temp_bans = {},
events = {
--- When a player is assigned to jail
-- @event on_player_jailed
-- @tparam number player_index the index of the player who was jailed
-- @tparam string by_player_name the name of the player who jailed the other player
-- @tparam string reason the reason that the player was jailed
on_player_jailed=script.generate_event_name(),
--- When a player is unassigned from jail
-- @event on_player_unjailed
-- @tparam number player_index the index of the player who was unjailed
-- @tparam string by_player_name the name of the player who unjailed the other player
on_player_unjailed=script.generate_event_name(),
--- When a player is temp banned
-- @event on_player_temp_banned
-- @tparam number player_index the index of the player who was temp banned
-- @tparam string by_player_name the name of the player who temp banned the other player
-- @tparam string reason the reason that the player was temp banned
on_player_temp_banned=script.generate_event_name(),
--- When a temp ban is removed from a player
-- @event on_player_untemp_banned
-- @tparam number player_index the index of the player who was untemp banned
-- @tparam string by_player_name the name of the player who untemp banned the other player
on_player_untemp_banned=script.generate_event_name()
}
}
local old_roles = Jail.old_roles
local temp_bans = Jail.temp_bans
Global.register({
old_roles = old_roles,
temp_bans = temp_bans
},function(tbl)
old_roles = tbl.old_roles
temp_bans = tbl.temp_bans
end)
--- Used to emit the jail related events
-- @tparam number event the name of the event that will be emited
-- @tparam LuaPlayer player the player who is being acted on
-- @tparam string by_player_name the player who is doing the action
-- @tparam string reason the reason for the action (jail and tempban only)
local function event_emit(event,player,by_player_name,reason)
script.raise_event(event,{
name=event,
tick=game.tick,
player_index=player.index,
by_player_name=by_player_name,
reason=reason
})
end
--- Jail.
-- Functions related to jail
-- @section jail-functions
--- Checks if the player is currently in jail
-- @tparam LuaPlayer player the player to check if they are in jail
-- @treturn boolean whether the player is currently in jail
function Jail.is_jailed(player)
return has_role(player,'Jail')
end
--- Moves a player to jail and removes all other roles
-- @tparam LuaPlayer player the player who will be jailed
-- @tparam string by_player_name the name of the player who is doing the jailing
-- @tparam[opt='Non given.'] string reason the reason that the player is being jailed
-- @treturn boolean wheather the user was jailed successfully
function Jail.jail_player(player,by_player_name,reason)
player = valid_player(player)
if not player then return end
if not by_player_name then return end
reason = reason or 'Non given.'
if has_role(player,'Jail') then return end
local roles = get_roles(player)
old_roles[player.name] = roles
assign_roles(player,'Jail',by_player_name,true)
unassign_roles(player,old_roles,by_player_name,true)
event_emit(Jail.events.on_player_jailed,player,by_player_name,reason)
return true
end
--- Moves a player out of jail and restores all roles previously removed
-- @tparam LuaPlayer player the player that will be unjailed
-- @tparam string by_player_name the name of the player that is doing the unjail
-- @treturn boolean whether the player was unjailed successfully
function Jail.unjail_player(player,by_player_name)
player = valid_player(player)
if not player then return end
if not by_player_name then return end
if not has_role(player,'Jail') then return end
local roles = old_roles[player.name] or {}
assign_roles(player,roles,by_player_name,true)
unassign_roles(player,'Jail',by_player_name,true)
event_emit(Jail.events.on_player_unjailed,player,by_player_name)
return true
end
--- Temp ban.
-- Functions related to temp ban
-- @section temp-ban-functions
--- Checks if a player is temp banned
-- @tparam LuaPlayer player the player to check if they are temp banned
-- @treturn boolean whether the player is temp banned
function Jail.is_temp_banned(player)
player = valid_player(player)
if not player then return end
return temp_bans[player.name] ~= nil
end
--- Temp bans a player by moving them to jail, clearing all other roles, storing the reason, and moving their items to spawn
-- @tparam LuaPlayer player the player that will be temp banned
-- @tparam string by_player_name the name of the player who is doing the temp ban
-- @tparam[opt='Non given.'] string reason the reason that the player is being temp banned
-- @treturn boolean whether the player was successfully temp banned
function Jail.temp_ban_player(player,by_player_name,reason)
player = valid_player(player)
if not player then return end
if not by_player_name then return end
reason = reason or 'Non given.'
if temp_bans[player.name] then return end
temp_bans[player.name] = {reason,by_player_name}
if not has_role(player,'Jail') then
local roles = get_roles(player)
old_roles[player.name] = roles
assign_roles(player,'Jail',by_player_name,true)
unassign_roles(player,roles,by_player_name,true)
end
local inv = player.get_main_inventory()
move_items(inv.get_contents())
inv.clear()
event_emit(Jail.events.on_player_temp_banned,player,by_player_name,reason)
return true
end
--- Rrmoves a player from temp ban by clearing the stored reason, removing them from jail, and restoring previous roles
-- @tparam LuaPlayer player the player who is being removed from temp ban
-- @tparam string by_player_name the name of the player who is doing the untemp ban
-- @treturn boolean whether the player was successfully removed
function Jail.untemp_ban_player(player,by_player_name)
player = valid_player(player)
if not player then return end
if not by_player_name then return end
if not temp_bans[player.name] then return end
temp_bans[player.name] = nil
if has_role(player,'Jail') then
local roles = old_roles[player.name]
assign_roles(player,roles,by_player_name,true)
unassign_roles(player,'Jail',by_player_name,true)
end
event_emit(Jail.events.on_player_untemp_banned,player,by_player_name)
return true
end
return Jail

View File

@@ -0,0 +1,237 @@
--[[-- Control Module - Production
- Common functions used to track production of items
@control Production
@alias Production
@usage
-- import the module from the control modules
local Production = require 'modules.control.production'
-- This will return the less precise index from the one given
-- this means that one_second will return one_minute or ten_hours will return fifty_hours
-- the other precision work like wise
Production.precision_up(defines.flow_precision_index.one_second)
-- The get production function is used to get production, consumion and net
-- it may be used for any item and with any precision level, use total for total
Production.get_production(game.forces.player,'iron-plate',defines.flow_precision_index.one_minute)
-- The fluctuations works by compearing recent production with the average over time
-- again any precision may be used, apart from one_thousand_hours as there would be no valid average
Production.get_fluctuations(game.forces.player,'iron-plate',defines.flow_precision_index.one_minute)
-- ETA is calculated based on what function you use but all share a similar method
-- for production eta it will take current production average given by the precision
-- and work out how many ticks it will require to make the required amount (1000 by default)
Production.get_production_eta(game.forces.player,'iron-plate',defines.flow_precision_index.one_minute,250000)
-- Both get_color and format_number are helper functions to help format production stats
-- get_color will return green,orange,red,or grey based on the active_value
-- the passive_value is used when active_value is 0 and can only return orange,red,or grey
Production.get_color(clamp,active_value,passive_value)
]]
--- Provides colors for Production.get_color
-- @dep resources.color_presets
local Colors = require 'resources.color_presets'
--- Provides format_number function to add surfixs
-- @dep util
local format_number = ext_require('util','format_number')
local precision_index = defines.flow_precision_index
local Production = {}
--- Precision.
-- Functions which are used to do basic things
-- @section precision
--- Gets the next lesser precision index value, eg 1 second -> 1 minute
-- @tparam defines.flow_precision_index precision
-- @treturn[1] defines.flow_precision_index the next precision value
-- @treturn[1] number the multiplicive difference between the values
function Production.precision_up(precision)
if precision == precision_index.one_second then return precision_index.one_minute,60
elseif precision == precision_index.one_minute then return precision_index.ten_minutes,10
elseif precision == precision_index.ten_minutes then return precision_index.one_hour,6
elseif precision == precision_index.one_hour then return precision_index.ten_hours,10
elseif precision == precision_index.ten_hours then return precision_index.fifty_hours,5
elseif precision == precision_index.fifty_hours then return precision_index.two_hundred_fifty_hours,5
elseif precision == precision_index.two_hundred_fifty_hours then return precision_index.one_thousand_hours,4
end
end
--- Gets the next greater precision index value, eg 1 minute -> 1 second
-- @tparam defines.flow_precision_index precision
-- @treturn[1] defines.flow_precision_index the next precision value
-- @treturn[1] number the multiplicive difference between the values
function Production.precision_down(precision)
if precision == precision_index.one_minute then return precision_index.one_second,60
elseif precision == precision_index.ten_minutes then return precision_index.one_minute,10
elseif precision == precision_index.one_hour then return precision_index.ten_minutes,6
elseif precision == precision_index.ten_hours then return precision_index.one_hour,10
elseif precision == precision_index.fifty_hours then return precision_index.ten_hours,5
elseif precision == precision_index.two_hundred_fifty_hours then return precision_index.fifty_hours,5
elseif precision == precision_index.one_thousand_hours then return precision_index.two_hundred_fifty_hours,4
end
end
--- Gets the number of tick that precision is given over, eg 1 minute -> 60 ticks
-- @tparam defines.flow_precision_index precision
-- @treturn number the number of ticks in this time
function Production.precision_ticks(precision)
if precision == precision_index.one_second then return 60
elseif precision == precision_index.one_minute then return 3600
elseif precision == precision_index.ten_minutes then return 36000
elseif precision == precision_index.one_hour then return 216000
elseif precision == precision_index.ten_hours then return 2160000
elseif precision == precision_index.fifty_hours then return 10800000
elseif precision == precision_index.two_hundred_fifty_hours then return 54000000
elseif precision == precision_index.one_thousand_hours then return 216000000
end
end
--- Statistics.
-- Functions used to get information about production
-- @section stats
--- Returns the production data for the whole game time
-- @tparam LuaForce force the force to get the data for
-- @tparam string item_name the name of the item that you want the data about
-- @treturn table contains total made, used and net
function Production.get_production_total(force,item_name)
local stats = force.item_production_statistics
local made = stats.get_input_count(item_name) or 0
local used = stats.get_output_count(item_name) or 0
return {
made=made,
used=used,
net=made-used
}
end
--- Returns the production data for the given precision game time
-- @tparam LuaForce force the force to get the data for
-- @tparam string item_name the name of the item that you want the data about
-- @tparam defines.flow_precision_index precision the precision that you want the data given to
-- @treturn table contains made, used and net
function Production.get_production(force,item_name,precision)
local stats = force.item_production_statistics.get_flow_count
local made = stats{name=item_name,input=true,precision_index=precision} or 0
local used = stats{name=item_name,input=false,precision_index=precision} or 0
return {
made=made,
used=used,
net=made-used
}
end
--- Returns the current fluctuation from the average
-- @tparam LuaForce force the force to get the data for
-- @tparam string item_name the name of the item that you want the data about
-- @tparam defines.flow_precision_index precision the precision that you want the data given to
-- @treturn table contains made, used and net
function Production.get_fluctuations(force,item_name,precision)
local percision_up = Production.precision_up(precision)
local current = Production.get_production(force,item_name,precision)
local previous = Production.get_production(force,item_name,percision_up)
return {
made=(current.made/previous.made)-1,
used=(current.used/previous.used)-1,
net=(current.net/previous.net)-1,
}
end
--- Returns the amount of ticks required to produce a certain amount
-- @tparam LuaForce force the force to get the data for
-- @tparam string item_name the name of the item that you want the data about
-- @tparam defines.flow_precision_index precision the precision that you want the data given to
-- @tparam[opt=1000] number required the number of items that are required to be made
-- @treturn number the number of ticks required to produce this ammount of items
function Production.get_production_eta(force,item_name,precision,required)
required = required or 1000
local ticks = Production.precision_ticks(precision)
local production = Production.get_production(force,item_name,precision)
return production.made == 0 and -1 or ticks*required/production.made
end
--- Returns the amount of ticks required to consume a certain amount
-- @tparam LuaForce force the force to get the data for
-- @tparam string item_name the name of the item that you want the data about
-- @tparam defines.flow_precision_index precision the precision that you want the data given to
-- @tparam[opt=1000] number required the number of items that are required to be consumed
-- @treturn number the number of ticks required to consume this ammount of items
function Production.get_consumsion_eta(force,item_name,precision,required)
required = required or 1000
local ticks = Production.precision_ticks(precision)
local production = Production.get_production(force,item_name,precision)
return production.used == 0 and -1 or ticks*required/production.used
end
--- Returns the amount of ticks required to produce but not consume a certain amount
-- @tparam LuaForce force the force to get the data for
-- @tparam string item_name the name of the item that you want the data about
-- @tparam defines.flow_precision_index precision the precision that you want the data given to
-- @tparam[opt=1000] number required the number of items that are required to be made but not used
-- @treturn number the number of ticks required to produce, but not use, this ammount of items
function Production.get_net_eta(force,item_name,precision,required)
required = required or 1000
local ticks = Production.precision_ticks(precision)
local production = Production.get_production(force,item_name,precision)
return production.net == 0 and -1 or ticks*required/production.net
end
--- Formating.
-- Functions used to format production values
-- @section formating
--- Returns a color value bassed on the value that was given
-- @tparam number clamp value which seperates the different colours
-- @tparam number active_value first value tested, tested against clamp
-- @tparam number passive_value second value tested, tested against 0
-- @treturn table contains r,g,b keys
function Production.get_color(clamp,active_value,passive_value)
if active_value > clamp then
return Colors.light_green
elseif active_value < -clamp then
return Colors.indian_red
elseif active_value ~= 0 then
return Colors.orange
elseif passive_value and passive_value > 0 then
return Colors.orange
elseif passive_value and passive_value ~= 0 then
return Colors.indian_red
else
return Colors.grey
end
end
--- Returns three parts used to format a number
-- @tparam number value the value to format
-- @treturn[1] string the sign for the number
-- @treturn[1] string the surfix for any unit used
function Production.format_number(value)
local rtn = format_number(math.round(value,1),true)
local surfix = rtn:sub(-1)
if value > 0 then
rtn = '+'..rtn
elseif value == 0 and rtn:sub(1,1) == '-' then
rtn = rtn:sub(2)
end
if not tonumber(surfix) then
return surfix,rtn:sub(1,-2)
else
return '',rtn
end
end
return Production

219
modules/control/reports.lua Normal file
View File

@@ -0,0 +1,219 @@
--[[-- Control Module - Reports
- Adds a way to report players and store report messages.
@control Reports
@alias Reports
@usage
-- import the module from the control modules
local Reports = require 'modules.control.reports'
-- This will place a report on "MrBiter" (must be a valid player) the report will have been made
-- by "Cooldude2606" (must be the player name) with the reason 'Liking biters too much' this can be
-- seen by using Reports.get_report.
Reports.report_player('MrBiter','Cooldude2606','Liking biters too much') -- true
-- The other get methods can be used to get all the reports on a player or to test if a player is reported.
Reports.get_report('MrBiter','Cooldude2606') -- 'Liking biters too much'
-- This will remove the warning on 'MrBiter' (must be a valid player) which was made by 'Cooldude2606'.
Reports.remove_report('MrBiter','Cooldude2606') -- true
-- This will remove all the report that have been made against 'MrBiter'. Note that the remove event will
-- be triggered once per report issused.
Reports.remove_all('MrBiter') -- true
]]
--- Allows getting player from any value
-- @dep utils.game
local Game = require 'utils.game'
--- Allows storing of data in global table
-- @dep utils.global
local Global = require 'utils.global'
local valid_player = Game.get_player_from_any
local Reports = {
user_reports={}, -- stores all user reports, global table
events = {
--- When a player is reported
-- @event on_player_reported
-- @tparam number player_index the player index of the player who got reported
-- @tparam string by_player_name the name of the player who made the report
-- @tparam string reason the reason given for the report
on_player_reported = script.generate_event_name(),
--- When a report is removed from a player
-- @event on_report_removed
-- @tparam number player_index the player index of the player who has the report removed
-- @tparam string reported_by_name the name of the player who made the removed report
-- @tparam string removed_by_name the name of the player who removed the report
on_report_removed = script.generate_event_name()
}
}
local user_reports = Reports.user_reports
Global.register(user_reports,function(tbl)
user_reports = tbl
end)
--- Getters.
-- Functions used to get information from reports
-- @section get-functions
--- Gets a list of all reports that a player has against them
-- @tparam LuaPlayer player the player to get the report for
-- @treturn table a list of all reports, key is by player name, value is reason
function Reports.get_reports(player)
player = valid_player(player)
if not player then return end
return user_reports[player.name] or {}
end
--- Gets a single report against a player given the name of the player who made the report
-- @tparam LuaPlayer player the player to get the report for
-- @tparam string by_player_name the name of the player who made the report
-- @treturn ?string|nil string is the reason that the player was reported, if the player is not reported
function Reports.get_report(player,by_player_name)
player = valid_player(player)
if not player then return end
if not by_player_name then return end
local reports = user_reports[player.name]
return reports and reports[by_player_name]
end
--- Checks if a player is reported, option to get if reported by a certain player
-- @tparam LuaPlayer player the player to check if reported
-- @tparam[opt] string by_player_name when given will check if reported by this player
-- @treturn boolean if the player has been reported
function Reports.is_reported(player,by_player_name)
player = valid_player(player)
if not player then return end
local reports = user_reports[player.name] or {}
if by_player_name then
return reports[by_player_name] ~= nil
else
return table_size(reports) > 0
end
end
--- Counts the number of reports that a player has aganist them
-- @tparam LuaPlayer player the player to count the reports for
-- @tparam[opt] function custom_count when given this function will be used to count the reports
-- @treturn number the number of reports that the user has
function Reports.count_reports(player,custom_count)
player = valid_player(player)
if not player then return end
local reports = user_reports[player.name] or {}
if custom_count then
local ctn = 0
for by_player_name,reason in pairs(reports) do
ctn = ctn + custom_count(player,by_player_name,reason)
end
return ctn
else
return table_size(reports)
end
end
--- Setters.
-- Functions used to get information from reports
-- @section set-functions
--- Adds a report to a player, each player can only report another player once
-- @tparam LuaPlayer player the player to add the report to
-- @tparam string by_player_name the name of the player that is making the report
-- @tparam[opt='Non given.'] string reason the reason that the player is being reported
-- @treturn boolean whether the report was added successfully
function Reports.report_player(player,by_player_name,reason)
player = valid_player(player)
if not player then return end
local player_name = player.name
reason = reason or 'Non given.'
local reports = user_reports[player_name]
if not reports then
reports = {}
user_reports[player_name] = reports
end
if reports[by_player_name] then
return false
else
reports[by_player_name] = reason
end
script.raise_event(Reports.events.on_player_reported,{
name = Reports.events.on_player_reported,
tick = game.tick,
player_index = player.index,
by_player_name = by_player_name,
reason = reason
})
return true
end
--- Used to emit the report removed event, own function due to repeated use in Report.remove_all
-- @tparam LuaPlayer player the player who is having the report removed from them
-- @tparam string reported_by_name the player who had the report
-- @tparam string removed_by_name the player who is clearing the report
local function report_removed_event(player,reported_by_name,removed_by_name)
script.raise_event(Reports.events.on_report_removed,{
name = Reports.events.on_report_removed,
tick = game.tick,
player_index = player.index,
reported_by_name = reported_by_name,
removed_by_name = removed_by_name
})
end
--- Removes a report from a player
-- @tparam LuaPlayer player the player to remove the report from
-- @tparam string reported_by_name the name of the player that made the report
-- @treturn boolean whether the report was removed successfully
function Reports.remove_report(player,reported_by_name,removed_by_name)
player = valid_player(player)
if not player then return end
local reports = user_reports[player.name]
if not reports then
return false
end
local reason = reports[reported_by_name]
if not reason then
return false
end
report_removed_event(player,reported_by_name,removed_by_name)
reports[reported_by_name] = nil
return true
end
--- Removes all reports from a player
-- @tparam LuaPlayer player the player to remove the reports from
-- @treturn boolean whether the reports were removed successfully
function Reports.remove_all(player,removed_by_name)
player = valid_player(player)
if not player then return end
local reports = user_reports[player.name]
if not reports then
return false
end
for reported_by_name,_ in pairs(reports) do
report_removed_event(player,reported_by_name,removed_by_name)
end
user_reports[player.name] = nil
return true
end
return Reports

219
modules/control/rockets.lua Normal file
View File

@@ -0,0 +1,219 @@
--[[-- Control Module - Rockets
- Stores rocket stats for each force.
@control Rockets
@alias Rockets
@usage
-- import the module from the control modules
local Rockets = require 'modules.control.rockets'
-- Some basic information is stored for each silo that has been built
-- the data includes: the tick it was built, the rockets launched from it and more
Rockets.get_silo_data(rocket_silo_entity)
-- Some information is also stored for each force
Rockets.get_stats('player')
-- You can get the rocket data for all silos for a force by using get_silos
Rockets.get_silos('player')
-- You can get the launch time for a rocket, meaning what game tick the 50th rocket was launched
Rockets.get_rocket_time('player',50)
-- The rolling average will work out the time to launch one rocket based on the last X rockets
Rockets.get_rolling_average('player',10)
]]
--- Allows registering event handlers
-- @dep utils.event
local Event = require 'utils.event'
--- Allows storing in the global table
-- @dep utils.global
local Global = require 'utils.global'
--- Contains the config for this module
-- @dep config.rockets
local config = require 'config.rockets'
local largest_rolling_avg = 0
for _,avg_over in pairs(config.stats.rolling_avg) do
if avg_over > largest_rolling_avg then
largest_rolling_avg = avg_over
end
end
local Rockets = {
times = {},
stats = {},
silos = {}
}
local rocket_times = Rockets.times
local rocket_stats = Rockets.stats
local rocket_silos = Rockets.silos
Global.register({
rocket_times = rocket_times,
rocket_stats = rocket_stats,
rocket_silos = rocket_silos
},function(tbl)
rocket_times = tbl.rocket_times
rocket_stats = tbl.rocket_stats
rocket_silos = tbl.rocket_silos
end)
--- Gets the silo data for a given silo entity
-- @tparam LuaEntity silo the rocket silo entity
-- @treturn table the data table for this silo, contains rockets launch, silo status, and its force
function Rockets.get_silo_data(silo)
local position = silo.position
local silo_name = math.floor(position.x)..':'..math.floor(position.y)
return rocket_silos[silo_name]
end
--- Gets the silo data for a given silo entity
-- @tparam string silo_name the silo name that is stored in its data
-- @treturn table the data table for this silo, contains rockets launch, silo status, and its force
function Rockets.get_silo_data_by_name(silo_name)
return rocket_silos[silo_name]
end
--- Gets the silo entity from its silo name, reverse to get_silo_data
-- @tparam string silo_name the silo name that is stored in its data
-- @treturn LuaEntity the rocket silo entity
function Rockets.get_silo_entity(silo_name)
local data = rocket_silos[silo_name]
return data.entity
end
--- Gets the rocket stats for a force
-- @tparam string force_name the name of the force to get the stats for
-- @treturn table the table of stats for the force
function Rockets.get_stats(force_name)
return rocket_stats[force_name] or {}
end
--- Gets all the rocket silos that belong to a force
-- @tparam string force_name the name of the force to get the silos for
-- @treturn table an array of silo data that all belong to this force
function Rockets.get_silos(force_name)
local rtn = {}
for _,silo_data in pairs(rocket_silos) do
if silo_data.force == force_name then
table.insert(rtn,silo_data)
end
end
return rtn
end
--- Gets the launch time of a given rocket, due to cleaning not all counts are valid
-- @tparam string force_name the name of the force to get the count for
-- @tparam number rocket_number the number of the rocket to get the launch time for
-- @treturn number the game tick that the rocket was lanuched on
function Rockets.get_rocket_time(force_name,rocket_number)
return rocket_times[force_name] and rocket_times[force_name][rocket_number] or nil
end
--- Gets the number of rockets that a force has launched
-- @tparam string force_name the name of the force to get the count for
-- @treturn number the number of rockets that the force has launched
function Rockets.get_rocket_count(force_name)
local force = game.forces[force_name]
return force.rockets_launched
end
--- Gets the total number of rockets launched by all forces
-- @treturn number the total number of rockets launched this game
function Rockets.get_game_rocket_count()
local rtn = 0
for _,force in pairs(game.forces) do
rtn = rtn + force.rockets_launched
end
return rtn
end
--- Gets the rolling average time to launch a rocket
-- @tparam string force_name the name of the force to get the average for
-- @tparam number count the distance to get the rolling average over
-- @treturn number the number of ticks required to launch one rocket
function Rockets.get_rolling_average(force_name,count)
local force = game.forces[force_name]
local rocket_count = force.rockets_launched
local start_rocket_time = 0
if count < rocket_count then
start_rocket_time = rocket_times[force_name][rocket_count-count+1]
rocket_count = count
end
return rocket_count > 0 and math.floor((game.tick-start_rocket_time)/rocket_count) or 0
end
--- Event used to update the stats and the hui when a rocket is launched
Event.add(defines.events.on_rocket_launched,function(event)
local entity = event.rocket_silo
local silo_data = Rockets.get_silo_data(entity)
local force = event.rocket_silo.force
local force_name = force.name
local rockets_launched = force.rockets_launched
--- Handles updates to the rocket stats
local stats = rocket_stats[force_name]
if not stats then
rocket_stats[force_name] = {}
stats = rocket_stats[force_name]
end
if rockets_launched == 1 then
stats.first_launch = event.tick
stats.fastest_launch = event.tick
elseif event.tick-stats.last_launch < stats.fastest_launch then
stats.fastest_launch = event.tick-stats.last_launch
end
stats.last_launch = event.tick
--- Appends the new rocket into the array
if not rocket_times[force_name] then
rocket_times[force_name] = {}
end
rocket_times[force_name][rockets_launched] = event.tick
local remove_rocket = rockets_launched-largest_rolling_avg
if remove_rocket > 0 and not table.contains(config.milestones,remove_rocket) then
rocket_times[force_name][remove_rocket] = nil
end
--- Adds this 1 to the launch count for this silo
silo_data.launched = silo_data.launched+1
end)
--- When a launch is reiggered it will await reset
Event.add(defines.events.on_rocket_launch_ordered,function(event)
local entity = event.rocket_silo
local silo_data = Rockets.get_silo_data(entity)
silo_data.awaiting_reset = true
end)
--- Adds a silo to the list when it is built
local function on_built(event)
local entity = event.created_entity
if entity.valid and entity.name == 'rocket-silo' then
local force = entity.force
local force_name = force.name
local position = entity.position
local silo_name = math.floor(position.x)..':'..math.floor(position.y)
rocket_silos[silo_name] = {
name=silo_name,
force=force_name,
entity=entity,
launched=0,
awaiting_reset=false,
built=game.tick
}
end
end
Event.add(defines.events.on_built_entity,on_built)
Event.add(defines.events.on_robot_built_entity,on_built)
return Rockets

180
modules/control/tasks.lua Normal file
View File

@@ -0,0 +1,180 @@
--[[-- Control Module - Tasks
- Stores tasks for each force.
@control Tasks
@alias Tasks
@usage
-- import the module from the control modules
local Tasks = require 'modules.control.tasks'
-- To create a new task all you need is the name of the force you want to add the task to
-- you can give a place to add it but this is optional
Tasks.new_task('player')
-- You can then update this task to what ever value that you want
-- the task id is returned by new_task, or within an update handler
-- if a player name is not given that it will assume '<server>'
Tasks.update_task(task_id,'My number one task!','Cooldude2606')
-- You can then remove the task and all data linked with it
Tasks.remove_task(task_id)
-- set_editing and is_editing may be used to block other or provide warnings
-- none of this is enforced by this module and so you must do so in your own module
Tasks.set_editing(task_id,'Cooldude2606',true)
]]
--- Allows storing of task ids
-- @dep expcore.store
local Store = require 'expcore.store'
--- Allows storing in the global table
-- @dep utils.global
local Global = require 'utils.global'
--- Allows non conflicting task ids
-- @dep utils.token
local Token = require 'utils.token'
local Tasks = {
store = 'gui.left.task-list.tasks',
handlers = {},
details = {},
forces = {}
}
local task_details = Tasks.details
local force_tasks = Tasks.forces
Global.register({
task_details=task_details,
force_tasks=force_tasks
},function(tbl)
task_details = tbl.task_details
force_tasks = tbl.force_tasks
end)
local task_store = Tasks.store
Store.register(task_store,function(value,task_id)
local details = task_details[task_id]
local force = game.forces[details.force]
for _,handler in pairs(Tasks.handlers) do
handler(force,task_id)
end
end)
--- Setters.
-- functions used to created and alter tasks
-- @section setters
--- Adds a new handler for when a task is updated
-- @tparam function callback the callback which is ran when a task is updated
-- @treturn boolean true if the callback was added
function Tasks.add_handler(callback)
if type(callback) == 'function' then
table.insert(Tasks.handlers,callback)
return true
end
return false
end
--- Adds a new task for a force, with option to place it in a certain order
-- @tparam string force_name the name of the force to add the task for
-- @tparam[opt] number task_number the order place to add the task to, adds to end if omited
-- @tparam[opt] string player_name when given this player will be added to the editing list
-- @treturn string the uid of the task which was created
function Tasks.new_task(force_name,task_number,player_name)
local task_id = tostring(Token.uid())
local tasks = force_tasks[force_name]
if not tasks then
force_tasks[force_name] = {}
tasks = force_tasks[force_name]
end
if task_number then
table.insert(tasks,task_number,task_id)
else
table.insert(tasks,task_id)
end
task_details[task_id] = {
task_id=task_id,
force=force_name,
last_edit_player=player_name or '<server>',
last_edit_time=game.tick,
editing={}
}
if player_name then
task_details[task_id].editing[player_name] = true
end
Store.set(task_store,task_id,'New Task')
return task_id
end
--- Removes a task and all data linked with it
-- @tparam string task_id the uid of the task which you want to remove
function Tasks.remove_task(task_id)
local details = task_details[task_id]
local force = details.force
Store.clear(task_store,task_id)
task_details[task_id] = nil
table.remove_element(force_tasks[force],task_id)
end
--- Updates a task message
-- @tparam string task_id the uid of the task that you want to update
-- @tparam string task the message that you want to change the task to
-- @tparam[opt='server'] string player_name the name of the player who made the edit
function Tasks.update_task(task_id,task,player_name)
local details = task_details[task_id]
details.last_edit_player = player_name or '<server>'
details.last_edit_time = game.tick
Store.set(task_store,task_id,task)
end
--- Sets a player to be editing this task, used with is_editing
-- @tparam string task_id the uid of the task that you want to editing for
-- @tparam string player_name the name of the player you want to set editing for
-- @tparam[opt] boolean state the new state to set editing to
function Tasks.set_editing(task_id,player_name,state)
local details = task_details[task_id]
details.editing[player_name] = state
end
--- Getters.
-- function used to get information about tasks
-- @section getters
--- Gets the task stored at this id
-- @tparam string task_id the uid of the task you want to get
-- @treturn string the task message that was stored here
function Tasks.get_task(task_id)
return Store.get(task_store,task_id)
end
--- Gets the task details stored at this id
-- @tparam string task_id the uid of the task you want to get
-- @treturn table the task details that was stored here
function Tasks.get_details(task_id)
return task_details[task_id]
end
--- Gets the task ids for a force
-- @tparam string force_name the name of the force that you want the ids for
-- @treturn table an array of all the task ids
function Tasks.get_force_tasks(force_name)
return force_tasks[force_name] or {}
end
--- Gets if a player is currently editing this task
-- @tparam string task_id the uid of the task you want to check
-- @tparam string player_name the name of the player that you want to check
-- @treturn boolean weather the player is currently editing this task
function Tasks.is_editing(task_id,player_name)
local details = task_details[task_id]
return details.editing[player_name]
end
return Tasks

View File

@@ -0,0 +1,320 @@
--[[-- Control Module - Warnings
- Adds a way to give and remove warnings to players.
@control Warnings
@alias Warnings
@usage
-- import the module from the control modules
local Warnings = require 'modules.control.warnings'
-- This will add a warning to the player
Warnings.add_warning('MrBiter','Cooldude2606','Killed too many biters')
-- This will remove a warning from a player, second name is just who is doing the action
Warnings.remove_warning('MrBiter','Cooldude2606')
-- Script warning as similar to normal warning but are designed to have no effect for a short amount of time
-- this is so it can be used for greifer protection without being too agressive
Warnings.add_script_warning('MrBiter','Killed too many biters')
-- Both normal and script warnings can also be cleared, this will remove all warnings
Warnings.clear_warnings('MrBiter','Cooldude2606')
]]
--- Allows registering of custom events
-- @dep utils.event
local Event = require 'utils.event'
--- Allows getting player from any value
-- @dep utils.game
local Game = require 'utils.game'
--- Allows storing in the global table
-- @dep utils.global
local Global = require 'utils.global'
--- Config file for this module
-- @dep config.warnings
local config = require 'config.warnings'
local valid_player = Game.get_player_from_any
local Warnings = {
user_warnings={},
user_script_warnings={},
events = {
--- When a warning is added to a player
-- @event on_warning_added
-- @tparam number player_index the index of the player who recived the warning
-- @tparam string by_player_name the name of the player who gave the warning
-- @tparam string reason the reason that the player was given a warning
-- @tparam number warning_count the new number of warnings that the player has
on_warning_added = script.generate_event_name(),
--- When a warning is removed from a player
-- @event on_warning_removed
-- @tparam number player_index the index of the player who is having the warning removed
-- @tparam string warning_by_name the name of the player who gave the warning
-- @tparam string removed_by_name the name of the player who is removing the warning
-- @tparam number warning_count the new number of warnings that the player has
on_warning_removed = script.generate_event_name(),
--- When a warning is added to a player, by the script
-- @event on_script_warning_added
-- @tparam number player_index the index of the player who recived the warning
-- @tparam string reason the reason that the player was given a warning
-- @tparam number warning_count the new number of warnings that the player has
on_script_warning_added = script.generate_event_name(),
--- When a warning is remnoved from a player, by the script
-- @event on_script_warning_removed
-- @tparam number player_index the index of the player who is having the warning removed
-- @tparam number warning_count the new number of warnings that the player has
on_script_warning_removed = script.generate_event_name(),
}
}
local user_warnings = Warnings.user_warnings
local user_script_warnings = Warnings.user_script_warnings
Global.register({
user_warnings = user_warnings,
user_script_warnings = user_script_warnings
},function(tbl)
user_warnings = tbl.user_warnings
user_script_warnings = tbl.user_script_warnings
end)
--- Gets an array of warnings that the player has, always returns a list even if emtpy
-- @tparam LuaPlayer player the player to get the warning for
-- @treturn table an array of all the warnings on this player, contains tick, by_player_name and reason
function Warnings.get_warnings(player)
return user_warnings[player.name] or {}
end
--- Gets the number of warnings that a player has on them
-- @tparam LuaPlayer player the player to count the warnings for
-- @treturn number the number of warnings that the player has
function Warnings.count_warnings(player)
local warnings = user_warnings[player.name] or {}
return #warnings
end
--- Adds a warning to a player, when a warning is added a set action is done based on the number of warnings and the config file
-- @tparam LuaPlayer player the player to add a warning to
-- @tparam string by_player_name the name of the player who is doing the action
-- @tparam[opt='Non given.'] string reason the reason that the player is being warned
-- @treturn number the number of warnings that the player has
function Warnings.add_warning(player,by_player_name,reason)
player = valid_player(player)
if not player then return end
if not by_player_name then return end
reason = reason or 'Non given.'
local warnings = user_warnings[player.name]
if not warnings then
warnings = {}
user_warnings[player.name] = warnings
end
table.insert(warnings,{
tick = game.tick,
by_player_name = by_player_name,
reason = reason
})
local warning_count = #warnings
script.raise_event(Warnings.on_warning_added,{
name = Warnings.on_warning_added,
tick = game.tick,
player_index = player.index,
warning_count = warning_count,
by_player_name = by_player_name,
reason = reason
})
local action = config.actions[#warnings]
if action then
local _type = type(action)
if _type == 'function' then
action(player,by_player_name,warning_count)
elseif _type == 'table' then
local current = table.deepcopy(action)
table.insert(current,2,by_player_name)
table.insert(current,3,warning_count)
player.print(current)
elseif type(action) == 'string' then
player.print(action)
end
end
return warning_count
end
--- Event trigger for removing a waring due to it being looped in clear warnings
-- @tparam LuaPlayer player the player who is having a warning removed
-- @tparam string warning_by_name the name of the player who made the warning
-- @tparam string removed_by_name the name of the player who is doing the action
-- @tparam number warning_count the number of warnings that the player how has
local function warning_removed_event(player,warning_by_name,removed_by_name,warning_count)
script.raise_event(Warnings.on_warning_removed,{
name = Warnings.on_warning_removed,
tick = game.tick,
player_index = player.index,
warning_count = warning_count,
warning_by_name = warning_by_name,
removed_by_name = removed_by_name
})
end
--- Removes a warning from a player, always removes the earlyist warning, fifo
-- @tparam LuaPlayer player the player to remove a warning from
-- @tparam string by_player_name the name of the player who is doing the action
-- @treturn number the number of warnings that the player has
function Warnings.remove_warning(player,by_player_name)
player = valid_player(player)
if not player then return end
if not by_player_name then return end
local warnings = user_warnings[player.name]
if not warnings then return end
local warning = table.remove(warnings,1)
warning_removed_event(player,warning.by_player_name,by_player_name,#warnings)
return #warnings
end
--- Removes all warnings from a player, will trigger remove event for each warning
-- @tparam LuaPlayer player the player to clear the warnings from
-- @tparam string by_player_name the name of the player who is doing the action
-- @treturn boolean true when warnings were cleared succesfully
function Warnings.clear_warnings(player,by_player_name)
player = valid_player(player)
if not player then return end
if not by_player_name then return end
local warnings = user_warnings[player.name]
if not warnings then return end
local warning_count = #warnings
for n,warning in pairs(warnings) do
warning_removed_event(player,warning.by_player_name,by_player_name,warning_count-n)
end
user_warnings[player.name] = nil
return true
end
--- Gets an array of all the script warnings that a player has
-- @tparam LuaPlayer player the player to get the script warnings of
-- @treturn table a table of all the script warnings a player has, contains tick and reason
function Warnings.get_script_warnings(player)
return user_script_warnings[player.name] or {}
end
--- Gets the number of script warnings that a player has on them
-- @tparam LuaPlayer player the player to count the script warnings of
-- @treturn number the number of script warnings that the player has
function Warnings.count_script_warnings(player)
local warnings = user_script_warnings[player.name] or {}
return #warnings
end
--- Adds a script warning to a player, this may add a full warning if max script warnings is met
-- @tparam LuaPlayer player the player to add a script warning to
-- @tparam[opt='Non given.'] string reason the reason that the player is being warned
-- @treturn number the number of script warnings that the player has
function Warnings.add_script_warning(player,reason)
player = valid_player(player)
if not player then return end
reason = reason or 'Non given.'
local warnings = user_script_warnings[player.name]
if not warnings then
warnings = {}
user_script_warnings[player.name] = warnings
end
table.insert(warnings,{
tick = game.tick,
reason = reason
})
local warning_count = #warnings
script.raise_event(Warnings.on_script_warning_added,{
name = Warnings.on_script_warning_added,
tick = game.tick,
player_index = player.index,
warning_count = warning_count,
reason = reason
})
if warning_count > config.script_warning_limit then
Warnings.add_warning(player,'<server>',reason)
end
return warning_count
end
--- Script warning removed event tigger due to it being looped in clear script warnings
-- @tparam LuaPlayer player the player who is having a script warning removed
-- @tparam number warning_count the number of warning that the player has
local function script_warning_removed_event(player,warning_count)
script.raise_event(Warnings.on_script_warning_removed,{
name = Warnings.on_script_warning_removed,
tick = game.tick,
player_index = player.index,
warning_count = warning_count
})
end
--- Removes a script warning from a player
-- @tparam LuaPlayer player the player to remove a script warning from
-- @treturn number the number of script warnings that the player has
function Warnings.remove_script_warning(player)
player = valid_player(player)
if not player then return end
local warnings = user_script_warnings[player.name]
if not warnings then return end
table.remove(warnings,1)
script_warning_removed_event(player)
return #warnings
end
--- Removes all script warnings from a player, emits event for each warning removed
-- @tparam LuaPlayer player the player to clear the script warnings from
function Warnings.clear_script_warnings(player)
player = valid_player(player)
if not player then return end
local warnings = user_script_warnings[player.name]
if not warnings then return end
local warning_count = #warnings
for n,_ in pairs(warnings) do
script_warning_removed_event(player,warning_count-n)
end
user_script_warnings[player.name] = nil
return true
end
-- script warnings are removed after a certain amount of time to make them even more lienient
local script_warning_cool_down = config.script_warning_cool_down*3600
Event.on_nth_tick(script_warning_cool_down/4,function()
local cutoff = game.tick - script_warning_cool_down
for player_name,script_warnings in pairs(user_script_warnings) do
if #script_warnings > 0 then
for _,warning in pairs(script_warnings) do
if warning.tick < cutoff then
Warnings.remove_script_warning(player_name)
end
end
end
end
end)
return Warnings

366
modules/control/warps.lua Normal file
View File

@@ -0,0 +1,366 @@
--[[-- Control Module - Warps
- Stores warps for each force.
@control Warps
@alias Warps
@usage
-- import the module from the control modules
local Warps = require 'modules.control.warps'
-- Adding a warp require a force, surface and postion, and the option to set this as the spawn
-- this function will also create the warp area unless set other wise
Warps.new_warp('player',surface,{x=0,y=0})
-- You can then update the warp information, name and icon, with the update function
Warps.update_warp(warp_id,'Best Warp','iron-plate')
-- Removeing a warp will restore the land that as under it, and remove any data linked with it
Warps.remove_warp(warp_id)
-- You can get the deatils for a warp which include last edit and postion
Warps.get_details(warp_id)
-- You can teleport a player to a warp, note that there is no limit on this action
Warps.teleport_player(warp_id,player)
]]
--- Allows storing of warp ids
-- @dep expcore.store
local Store = require 'expcore.store'
--- Allows storing of warp details
-- @dep utils.global
local Global = require 'utils.global'
--- Allows non conflicting warp ids
-- @dep utils.token
local Token = require 'utils.token'
--- Config for the warps
-- @dep expcore.store
local config = require 'config.warps'
--- Access to table_values and table_keysort
-- @dep expcore.common
local table_values,table_keysort = ext_require('expcore.common','table_values','table_keysort')
local Warps = {
store = {
names = 'gui.left.warps.names',
icons = 'gui.left.warps.tags'
},
details = {},
forces = {},
handlers = {}
}
local warp_details = Warps.details
local force_warps = Warps.forces
Global.register({
warp_details=warp_details,
force_warps=force_warps
},function(tbl)
force_warps = tbl.force_warps
warp_details = tbl.warp_details
end)
local warp_names = Warps.store.names
Store.register(warp_names,function(value,warp_id)
local details = warp_details[warp_id]
local force_name = details.force
local force = game.forces[force_name]
local warps = force_warps[force_name]
local spawn_id = warps.spawn
local names = {}
for _,next_warp_id in pairs(warps) do
local warp_name = Store.get(warp_names,next_warp_id)
if next_warp_id ~= spawn_id then
names[warp_name..next_warp_id] = next_warp_id
end
end
force_warps[force_name] = table_values(table_keysort(names))
table.insert(force_warps[force.name],1,spawn_id)
force_warps[force_name].spawn = spawn_id
for _,handler in pairs(Warps.handlers) do
handler(force,warp_id)
end
end)
local warp_icons = Warps.store.icons
Store.register(warp_icons,function(value,warp_id)
if value then
Warps.make_chart_tag(warp_id)
else
local warp = warp_details[warp_id]
if warp.tag and warp.tag.valid then warp.tag.destroy() end
end
end)
--- Generators.
-- functions used to create and alter warps with in the map
-- @section generators
--- Adds or updates the chart tag for a warp
-- @tparam string warp_id the uid of the warp you want to make the chart tag for
-- @treturn boolean true if a new tag was made, false if it was updated
function Warps.make_chart_tag(warp_id)
local warp = warp_details[warp_id]
local name = Store.get(warp_names,warp_id)
local icon = Store.get(warp_icons,warp_id)
if warp.tag and warp.tag.valid then
warp.tag.text = 'Warp: '..name
warp.tag.icon = {type='item',name=icon}
return false
end
local force = game.forces[warp.force]
local surface = warp.surface
local position = warp.position
local tag = force.add_chart_tag(surface,{
position={position.x+0.5,position.y+0.5},
text='Warp: '..name,
icon={type='item',name=icon}
})
warp.tag = tag
return true
end
--- Adds a new warp to a force and makes the in game warp area
-- @tparam string force_name the name of the force to add a new warp for
-- @tparam LuaSurface surface the surface to add the warp to
-- @tparam Position postion the postion to have the warp go to
-- @tparam[opt='server'] string player_name the name of the player who added this warp
-- @tparam[opt='New warp'] string warp_name the name of the warp that will be made
-- @tparam[opt=false] boolean block_generation when true a in game area will not be made
-- @tparam[opt=false] boolean set_spawn when true this warp will become the spawn for the force
function Warps.new_warp(force_name,surface,position,player_name,warp_name,block_generation,set_spawn)
local warp_id = tostring(Token.uid())
warp_name = warp_name or 'New warp'
if not force_warps[force_name] then
force_warps[force_name] = {}
end
table.insert(force_warps[force_name],warp_id)
warp_details[warp_id] = {
warp_id = warp_id,
force = force_name,
position = {
x=math.floor(position.x),
y=math.floor(position.y)
},
surface = surface,
last_edit_player=player_name or '<server>',
last_edit_time=game.tick,
editing={}
}
local warp = warp_details[warp_id]
if player_name then
warp.editing[player_name] = true
end
if set_spawn then
force_warps[force_name].spawn = warp_id
game.forces[force_name].set_spawn_position(position,surface)
end
Store.set(warp_names,warp_id,warp_name)
Store.set(warp_icons,warp_id,config.default_icon)
if block_generation then return warp_id end
local posx = position.x
local posy = position.y
local radius = config.activation_range
local radius2 = radius^2
local old_tile = surface.get_tile(position).name
warp.old_tile = old_tile
local base_tile = config.base_tile
local base_tiles = {}
-- this makes a base plate to make the warp point
for x = -radius, radius do
local x2 = x^2
for y = -radius, radius do
local y2 = y^2
if x2+y2 < radius2 then
table.insert(base_tiles,{name=base_tile,position={x+posx,y+posy}})
end
end
end
surface.set_tiles(base_tiles)
-- this adds the tile pattern
local tiles = {}
for _,pos in pairs(config.tiles) do
table.insert(tiles,{name=base_tile,position={pos[1]+posx,pos[2]+posy}})
end
surface.set_tiles(tiles)
-- this adds the enitites
for _,entity in pairs(config.entities) do
entity = surface.create_entity{
name=entity[1],
position={entity[2]+posx,entity[3]+posy},
force='neutral'
}
entity.destructible = false
entity.health = 0
entity.minable = false
entity.rotatable = false
end
return warp_id
end
--- Removes a warp and clears the area where it was added
-- @tparam string warp_id the uid of the warp that you want to remove
function Warps.remove_warp(warp_id)
local force_name = warp_details[warp_id].force
local warps = force_warps[force_name]
local key = table.index_of(warps,warp_id)
warps[key] = nil
Store.clear(warp_names,warp_id)
Store.clear(warp_icons,warp_id)
local warp = warp_details[warp_id]
local position = warp.position
local surface = warp.surface
local radius = config.activation_range
local radius2 = radius^2
local base_tile = warp.old_tile
local tiles = {}
-- clears the area where the warp was
for x = -radius, radius do
local x2 = x^2
for y = -radius, radius do
local y2 = y^2
if x2+y2 < radius2 then
table.insert(tiles,{name=base_tile,position={x+position.x,y+position.y}})
end
end
end
surface.set_tiles(tiles)
-- removes all entites (in the area) on the neutral force
local entities = surface.find_entities_filtered{
force='neutral',
area={
{position.x-radius,position.y-radius},
{position.x+radius,position.y+radius}
}
}
for _,entity in pairs(entities) do if entity.name ~= 'player' then entity.destroy() end end
warp_details[warp_id] = nil
end
--- Setters.
-- functions used to created and alter warps
-- @section setters
--- Adds a new handler for when a warp is updated
-- @tparam function callback the callback which is ran when a warp is updated
-- @treturn boolean true if the callback was added
function Warps.add_handler(callback)
if type(callback) == 'function' then
table.insert(Warps.handlers,callback)
return true
end
return false
end
--- Sets a player to be editing this warp, used with is_editing
-- @tparam string warp_id the uid of the warp that you want to editing for
-- @tparam string player_name the name of the player you want to set editing for
-- @tparam[opt] boolean state the new state to set editing to
function Warps.set_editing(warp_id,player_name,state)
local details = warp_details[warp_id]
details.editing[player_name] = state
end
--- Updates a warp to a differecnt name and icon, both must be given
-- @tparam string warp_id the uid of the warp that you want to update
-- @tparam string name the name that you want the warp to have
-- @tparam string icon the new icon that you want the warp to have
-- @tparam[opt='server'] string player_name the name of the player that is updating the warp
function Warps.update_warp(warp_id,name,icon,player_name)
local warp = warp_details[warp_id]
warp.last_edit_player = player_name or '<server>'
warp.last_edit_time = game.tick
Store.set(warp_icons,warp_id,icon)
Store.set(warp_names,warp_id,name)
end
--- Getters.
-- function used to get information about warps
-- @section getters
--- Gets the name of a warp
-- @tparam string warp_id the uid of the warp you want to get
-- @treturn string the warp name that was stored here
function Warps.get_warp_name(warp_id)
return Store.get(warp_names,warp_id)
end
--- Gets the icon of a warp
-- @tparam string warp_id the uid of the warp you want to get
-- @treturn string the warp icon that was stored here
function Warps.get_warp_icon(warp_id)
return Store.get(warp_icons,warp_id) or config.default_icon
end
--- Gets the task details stored at this id
-- @tparam string warp_id the uid of the warp you want to get
-- @treturn table the warp details that was stored here
function Warps.get_details(warp_id)
return warp_details[warp_id]
end
--- Gets all warps for a force
-- @tparam string force_name the name of the force to get the warps for
-- @treturn table an array of warp ids that belong to this force, spawn key is included
function Warps.get_warps(force_name)
return force_warps[force_name] or {}
end
--- Gets all warps from all forces
-- @treturn table array of all warp details
function Warps.get_all_warps()
return warp_details
end
--- Gets if a player is currently editing this warp
-- @tparam string warp_id the uid of the warp you want to check
-- @tparam string player_name the name of the player that you want to check
-- @treturn boolean weather the player is currently editing this warp
function Warps.is_editing(warp_id,player_name)
local details = warp_details[warp_id]
return details.editing[player_name]
end
--- Teleports a player to a warp point
-- @tparam string warp_id the uid of the warp to send the player to
-- @tparam LuaPlayer player the player to teleport to the warp
function Warps.teleport_player(warp_id,player)
local warp = warp_details[warp_id]
local surface = warp.surface
local position = {
x=warp.position.x+0.5,
y=warp.position.y+0.5
}
local goto_position = surface.find_non_colliding_position('character',position,32,1)
if player.driving then player.driving = false end
player.teleport(goto_position,surface)
end
return Warps

View File

@@ -3,36 +3,9 @@ local Gui = require 'expcore.gui'
local Roles = require 'expcore.roles'
local Event = require 'utils.event'
local config = require 'config.rockets'
local Global = require 'utils.global'
local format_time = ext_require('expcore.common','format_time')
local Colors = require 'resources.color_presets'
local largest_rolling_avg = 0
for _,avg_over in pairs(config.stats.rolling_avg) do
if avg_over > largest_rolling_avg then
largest_rolling_avg = avg_over
end
end
local rocket_times = {}
local rocket_stats = {}
local rocket_silos = {}
Global.register({
rocket_times = rocket_times,
rocket_stats = rocket_stats,
rocket_silos = rocket_silos
},function(tbl)
rocket_times = tbl.rocket_times
rocket_stats = tbl.rocket_stats
rocket_silos = tbl.rocket_silos
end)
--- Gets the name used to reference the the rocket silo
local function get_silo_name(entity)
local position = entity.position
return math.floor(position.x)..':'..math.floor(position.y)
end
local Rockets = require 'modules.control.rockets'
--- Gets if a player is allowed to use the action buttons
local function player_allowed(player,action)
@@ -54,11 +27,9 @@ end
--- Used on the name label to allow zoom to map
local zoom_to_map_name = Gui.uid_name()
Gui.on_click(zoom_to_map_name,function(event)
local force = event.player.force
local rocket_silo_name = event.element.parent.caption
local rocket_silo_data = rocket_silos[force.name][rocket_silo_name]
local position = rocket_silo_data.entity.position
event.player.zoom_to_world(position,2)
local rocket_silo = Rockets.get_silo_entity(rocket_silo_name)
event.player.zoom_to_world(rocket_silo.position,2)
end)
--- Used to launch the rocket, when it is ready
@@ -75,11 +46,10 @@ end)
style.height = 16
end)
:on_click(function(player,element)
local force = player.force
local rocket_silo_name = element.parent.name:sub(8)
local rocket_silo_data = rocket_silos[force.name][rocket_silo_name]
if rocket_silo_data.entity.launch_rocket() then
rocket_silo_data.awaiting_reset = true
local silo_data = Rockets.get_silo_data_by_name(rocket_silo_name)
if silo_data.entity.launch_rocket() then
silo_data.awaiting_reset = true
element.enabled = false
local progress_label = element.parent.parent[rocket_silo_name].label
progress_label.caption = {'rocket-info.progress-launched'}
@@ -103,18 +73,16 @@ end)
style.height = 16
end)
:on_click(function(player,element)
local force = player.force
local rocket_silo_name = element.parent.name:sub(8)
local rocket_silo_data = rocket_silos[force.name][rocket_silo_name]
local active = rocket_silo_data.entity.auto_launch -- need to test for auto launch
if active then
local rocket_silo = Rockets.get_silo_entity(rocket_silo_name)
if rocket_silo.auto_launch then
element.sprite = 'utility/play'
element.tooltip = {'rocket-info.toggle-rocket-tooltip'}
rocket_silo_data.entity.auto_launch = false
rocket_silo.auto_launch = false
else
element.sprite = 'utility/stop'
element.tooltip = {'rocket-info.toggle-rocket-tooltip-disabled'}
rocket_silo_data.entity.auto_launch = true
rocket_silo.auto_launch = true
end
end)
@@ -263,28 +231,25 @@ end
local function generate_stats(player,frame)
if not config.stats.show_stats then return end
local element = frame.container.stats.table
local force_rockets = player.force.rockets_launched
local force_name = player.force.name
local force_rockets = Rockets.get_rocket_count(force_name)
local stats = Rockets.get_stats(force_name)
if config.stats.show_first_rocket then
create_label_value_pair_time(element,'first-launch',rocket_stats.first_launch or 0)
create_label_value_pair_time(element,'first-launch',stats.first_launch or 0)
end
if config.stats.show_last_rocket then
create_label_value_pair_time(element,'last-launch',rocket_stats.last_launch or 0)
create_label_value_pair_time(element,'last-launch',stats.last_launch or 0)
end
if config.stats.show_fastest_rocket then
create_label_value_pair_time(element,'fastest-launch',rocket_stats.fastest_launch or 0,true)
create_label_value_pair_time(element,'fastest-launch',stats.fastest_launch or 0,true)
end
if config.stats.show_total_rockets then
local total_rockets = 1
if force_rockets > 0 then
total_rockets = 0
for _,force in pairs(game.forces) do
total_rockets = total_rockets + force.rockets_launched
end
end
local total_rockets = Rockets.get_game_rocket_count()
total_rockets = total_rockets == 0 and 1 or total_rockets
local percentage = math.round(force_rockets/total_rockets,3)*100
create_label_value_pair(element,'total-rockets',force_rockets,{'rocket-info.value-tooltip-total-rockets',percentage})
end
@@ -295,14 +260,7 @@ local function generate_stats(player,frame)
end
for _,avg_over in pairs(config.stats.rolling_avg) do
local rocket_count = avg_over
local first_rocket = 0
if avg_over < force_rockets then
first_rocket = rocket_times[player.force.name][force_rockets-avg_over+1]
else
rocket_count = force_rockets
end
local avg = rocket_count > 0 and math.floor((game.tick-first_rocket)/rocket_count) or 0
local avg = Rockets.get_rolling_average(force_name,avg_over)
create_label_value_pair_time(element,'avg-launch-n',avg,true,avg_over)
end
@@ -312,11 +270,12 @@ end
local function generate_milestones(player,frame)
if not config.milestones.show_milestones then return end
local element = frame.container.milestones.table
local force_rockets = player.force.rockets_launched
local force_name = player.force.name
local force_rockets = Rockets.get_rocket_count(force_name)
for _,milestone in ipairs(config.milestones) do
if milestone <= force_rockets then
local time = rocket_times[player.force.name][milestone]
local time = Rockets.get_rocket_time(force_name,milestone)
create_label_value_pair_time(element,'milestone-n',time,false,milestone)
else
create_label_value_pair_time(element,'milestone-n',0,false,milestone)
@@ -325,11 +284,12 @@ local function generate_milestones(player,frame)
end
end
--- Creates the different buttons used with the rocket silos
local function generate_progress_buttons(player,element,rocket_silo_data)
local silo_name = rocket_silo_data.name
local status = rocket_silo_data.entity.status == defines.entity_status.waiting_to_launch_rocket
local active = rocket_silo_data.entity.auto_launch
--- Creats the different buttons used with the rocket silos
local function generate_progress_buttons(player,element,silo_data)
local silo_name = silo_data.name
local rocket_silo = silo_data.entity
local status = rocket_silo.status == defines.entity_status.waiting_to_launch_rocket
local active = rocket_silo.auto_launch
if player_allowed(player,'toggle_active') then
local button_element = element['toggle-'..silo_name]
@@ -358,7 +318,7 @@ local function generate_progress_buttons(player,element,rocket_silo_data)
button_element = launch_rocket(element,silo_name)
end
if rocket_silo_data.awaiting_reset then
if silo_data.awaiting_reset then
button_element.enabled = false
else
button_element.enabled = status
@@ -383,32 +343,33 @@ local function generate_progress(player,frame)
local element = frame.container.progress.table
local force = player.force
local force_name = force.name
local force_silo_data = rocket_silos[force_name]
local force_silos = Rockets.get_silos(force_name)
if not force_silo_data or table.size(force_silo_data) == 0 then
if not force_silos or table.size(force_silos) == 0 then
element.parent.no_silos.visible = true
else
element.parent.no_silos.visible = false
for silo_name,rocket_silo_data in pairs(force_silo_data) do
if not rocket_silo_data.entity or not rocket_silo_data.entity.valid then
force_silo_data[silo_name] = nil
Gui.destroy_if_valid(element['toggle-'..silo_name])
Gui.destroy_if_valid(element['launch-'..silo_name])
Gui.destroy_if_valid(element['label-x-'..silo_name])
Gui.destroy_if_valid(element['label-y-'..silo_name])
Gui.destroy_if_valid(element[silo_name])
for _,silo_data in pairs(force_silos) do
local silo_name = silo_data.name
if not silo_data.entity or not silo_data.entity.valid then
force_silos[silo_name] = nil
Gui.destory_if_valid(element['toggle-'..silo_name])
Gui.destory_if_valid(element['launch-'..silo_name])
Gui.destory_if_valid(element['label-x-'..silo_name])
Gui.destory_if_valid(element['label-y-'..silo_name])
Gui.destory_if_valid(element[silo_name])
elseif not element[silo_name] then
local entity = rocket_silo_data.entity
local entity = silo_data.entity
local progress = entity.rocket_parts
local pos = {
x=entity.position.x,
y=entity.position.y
}
generate_progress_buttons(player,element,rocket_silo_data)
generate_progress_buttons(player,element,silo_data)
--- Creates two flows and two labels for the X and Y position
local name = config.progress.allow_zoom_to_map and zoom_to_map_name or nil
@@ -445,30 +406,30 @@ local function generate_progress(player,frame)
type='label',
name='label',
caption={'rocket-info.progress-caption',progress},
tooltip={'rocket-info.progress-tooltip',rocket_silo_data.launched or 0}
tooltip={'rocket-info.progress-tooltip',silo_data.launched or 0}
}
else
local entity = rocket_silo_data.entity
local entity = silo_data.entity
local progress = entity.rocket_parts
local status = entity.status == 21
local label = element[silo_name].label
label.caption = {'rocket-info.progress-caption',progress}
label.tooltip = {'rocket-info.progress-tooltip',rocket_silo_data.launched or 0}
label.tooltip = {'rocket-info.progress-tooltip',silo_data.launched or 0}
if status and rocket_silo_data.awaiting_reset then
if status and silo_data.awaiting_reset then
label.caption = {'rocket-info.progress-launched'}
label.style.font_color = Colors.green
elseif status then
label.caption = {'rocket-info.progress-caption',100}
label.style.font_color = Colors.cyan
else
rocket_silo_data.awaiting_reset = false
silo_data.awaiting_reset = false
label.style.font_color = Colors.white
end
generate_progress_buttons(player,element,rocket_silo_data)
generate_progress_buttons(player,element,silo_data)
end
end
@@ -501,44 +462,11 @@ end)
--- Event used to update the stats and the hui when a rocket is launched
Event.add(defines.events.on_rocket_launched,function(event)
local entity = event.rocket_silo
local silo_name = get_silo_name(entity)
local force = event.rocket_silo.force
local force_name = force.name
local force_silo_data = rocket_silos[force_name]
local rockets_launched = force.rockets_launched
local first_rocket = rockets_launched == 1
--- Handles updates to the rocket stats
if not rocket_stats[force_name] then
rocket_stats[force_name] = {}
end
if first_rocket then
rocket_stats.first_launch = event.tick
rocket_stats.fastest_launch = event.tick
elseif event.tick-rocket_stats.last_launch < rocket_stats.fastest_launch then
rocket_stats.fastest_launch = event.tick-rocket_stats.last_launch
end
rocket_stats.last_launch = event.tick
--- Appends the new rocket into the array
if not rocket_times[force_name] then
rocket_times[force_name] = {}
end
rocket_times[force_name][rockets_launched] = event.tick
local remove_rocket = rockets_launched-largest_rolling_avg
if remove_rocket > 0 and not table.contains(config.milestones,remove_rocket) then
rocket_times[force_name][remove_rocket] = nil
end
--- Adds this 1 to the launch count for this silo
force_silo_data[silo_name].launched = force_silo_data[silo_name].launched+1
--- Updates all the gui's (and toolbar since the button may now be visible)
--- Updates all the guis (and toolbar since the button may now be visible)
for _,player in pairs(force.players) do
rocket_info:update(player)
if first_rocket then
@@ -548,34 +476,11 @@ Event.add(defines.events.on_rocket_launched,function(event)
end
end)
--- When a launch is triggered it will await reset
Event.add(defines.events.on_rocket_launch_ordered,function(event)
local entity = event.rocket_silo
local silo_name = get_silo_name(entity)
local force = event.rocket_silo.force
local force_name = force.name
local force_silo_data = rocket_silos[force_name]
force_silo_data[silo_name].awaiting_reset = true
end)
--- Adds a silo to the list when it is built
local function on_built(event)
local entity = event.created_entity
if entity.valid and entity.name == 'rocket-silo' then
local force = entity.force
local force_name = force.name
local silo_name = get_silo_name(entity)
if not rocket_silos[force_name] then
rocket_silos[force_name] = {}
end
rocket_silos[force_name][silo_name] = {
name=silo_name,
entity=entity,
launched=0,
awaiting_reset=false
}
for _,player in pairs(force.players) do
local frame = rocket_info:get_frame(player)
@@ -590,8 +495,8 @@ Event.add(defines.events.on_robot_built_entity,on_built)
--- Optimised update for only the build progress
Event.on_nth_tick(150,function()
for _,force in pairs(game.forces) do
local silos = rocket_silos[force.name]
if silos then
local silos = Rockets.get_silos(force.name)
if #silos > 0 then
for _,player in pairs(force.connected_players) do
local frame = rocket_info:get_frame(player)
generate_progress(player,frame)

View File

@@ -1,53 +1,13 @@
--- Adds a science info gui that shows production usage and net for the different science packs as well as an eta
local Gui = require 'expcore.gui'
local Event = require 'utils.event'
local Colors = require 'resources.color_presets'
local format_time = ext_require('expcore.common','format_time')
local format_number = ext_require('util','format_number')
local config = require 'config.science'
local Production = require 'modules.control.production'
local null_time_short = {'science-info.eta-time',format_time(0,{hours=true,minutes=true,seconds=true,time=true,null=true})}
local null_time_long = format_time(0,{hours=true,minutes=true,seconds=true,long=true,null=true})
--- Gets the production stats for a certain science pack
local function get_production_stats(player,science_pack)
local force = player.force
local stats = force.item_production_statistics
local total_made = stats.get_input_count(science_pack)
local total_used = stats.get_output_count(science_pack)
local minute_made = stats.get_flow_count{
name=science_pack,
input=true,
precision_index=defines.flow_precision_index.one_minute,
}
local minute_used = stats.get_flow_count{
name=science_pack,
input=false,
precision_index=defines.flow_precision_index.one_minute,
}
return {
total_made=total_made,
total_used=total_used,
total_net=total_made-total_used,
minute_made=minute_made,
minute_used=minute_used,
minute_net=minute_made-minute_used
}
end
--- Gets the font colour for a certain level of production
local function get_font_colour(value,secondary)
if value > config.required_for_green then
return Colors.light_green
elseif value < config.required_for_red then
return Colors.indian_red
elseif secondary and secondary > 0 or not secondary and value ~= 0 then
return Colors.orange
else
return Colors.grey
end
end
--[[ Generates the main structure for the gui
element
> container
@@ -60,7 +20,7 @@ end
>>> eta
>>>> label
]]
local function generate_container(player,element)
local function generate_container(element)
Gui.set_padding(element,1,2,2,2)
element.style.minimal_width = 200
@@ -137,21 +97,8 @@ end
> spm-"name"
]]
local function add_data_label(element,name,value,secondary,tooltip)
local data_colour = get_font_colour(value,secondary)
local caption = format_number(math.round(value,1),true)
local surfix = caption:sub(-1)
if not tonumber(surfix) then
caption = caption:sub(1,-2)
else
surfix = ''
end
if value > 0 then
caption = '+'..caption
elseif value == 0 and caption:sub(1,1) == '-' then
caption = caption:sub(2)
end
local data_colour = Production.get_color(config.color_clamp, value, secondary)
local surfix,caption = Production.format_number(value)
if element[name] then
local data = element[name].label
@@ -197,16 +144,18 @@ end
> net-"science_pack" (add_data_label)
]]
local function generate_science_pack(player,element,science_pack)
local stats = get_production_stats(player,science_pack)
if stats.total_made > 0 then
local total = Production.get_production_total(player.force, science_pack)
local minute = Production.get_production(player.force, science_pack, defines.flow_precision_index.one_minute)
if total.made > 0 then
element.parent.non_made.visible = false
local icon_style = 'quick_bar_slot_button'
if stats.minute_net > config.required_for_green then
local flux = Production.get_fluctuations(player.force, science_pack, defines.flow_precision_index.one_minute)
if flux.net > -config.color_flux/2 then
icon_style = 'green_slot_button'
elseif stats.minute_net < config.required_for_red then
elseif flux.net < -config.color_flux then
icon_style = 'red_slot_button'
elseif stats.minute_made > 0 then
elseif minute.made > 0 then
icon_style = 'selected_slot_button'
end
@@ -257,9 +206,9 @@ local function generate_science_pack(player,element,science_pack)
Gui.set_padding(delta_table)
end
add_data_label(delta.table,'pos-'..science_pack,stats.minute_made,nil,{'science-info.pos-tooltip',stats.total_made})
add_data_label(delta.table,'neg-'..science_pack,-stats.minute_used,nil,{'science-info.neg-tooltip',stats.total_used})
add_data_label(element,'net-'..science_pack,stats.minute_net,stats.minute_made+stats.minute_used,{'science-info.net-tooltip',stats.total_net})
add_data_label(delta.table,'pos-'..science_pack,minute.made,nil,{'science-info.pos-tooltip',total.made})
add_data_label(delta.table,'neg-'..science_pack,-minute.used,nil,{'science-info.neg-tooltip',total.used})
add_data_label(element,'net-'..science_pack,minute.net,minute.made+minute.used,{'science-info.net-tooltip',total.net})
end
end
@@ -281,18 +230,9 @@ local function update_eta(player,element)
for _,ingredient in pairs(research.research_unit_ingredients) do
local pack_name = ingredient.name
local required = ingredient.amount * remaining
local consumed = stats.get_flow_count{
name=pack_name,
input=false,
precision_index=defines.flow_precision_index.one_minute,
}
if consumed == 0 then
limit = -1
break
end
local minutes = required / consumed
if not limit or limit < minutes then
limit = minutes
local time = Production.get_consumsion_eta(force, pack_name, defines.flow_precision_index.one_minute, required)
if not limit or limit < time then
limit = time
end
end
@@ -301,9 +241,8 @@ local function update_eta(player,element)
element.tooltip = null_time_long
else
local ticks = limit*3600
element.caption = {'science-info.eta-time',format_time(ticks,{hours=true,minutes=true,seconds=true,time=true})}
element.tooltip = format_time(ticks,{hours=true,minutes=true,seconds=true,long=true})
element.caption = {'science-info.eta-time',format_time(limit,{hours=true,minutes=true,seconds=true,time=true})}
element.tooltip = format_time(limit,{hours=true,minutes=true,seconds=true,long=true})
end
end
@@ -316,7 +255,7 @@ Gui.new_left_frame('gui/science-info')
:set_direction('vertical')
:set_tooltip{'science-info.main-tooltip'}
:on_creation(function(player,element)
local table, eta = generate_container(player,element)
local table, eta = generate_container(element)
for _,science_pack in ipairs(config) do
generate_science_pack(player,table,science_pack)

View File

@@ -1,61 +1,15 @@
--- Adds a task list to the game which players can add remove and edit items on
local Gui = require 'expcore.gui'
local Store = require 'expcore.store'
local Global = require 'utils.global'
local Event = require 'utils.event'
local Roles = require 'expcore.roles'
local Token = require 'utils.token'
local config = require 'config.tasks'
local format_time,table_keys = ext_require('expcore.common','format_time','table_keys')
local task_store = 'gui.left.task-list.tasks'
local task_details = {}
local force_tasks = {}
Global.register({
task_details=task_details,
force_tasks=force_tasks
},function(tbl)
task_details = tbl.task_details
force_tasks = tbl.force_tasks
end)
--- Adds a new task for this force with this players name attached
local function add_task(player,task_number)
local task_id = tostring(Token.uid())
if not force_tasks[player.force.name] then
force_tasks[player.force.name] = {}
end
if task_number then
table.insert(force_tasks[player.force.name],task_number,task_id)
else
table.insert(force_tasks[player.force.name],task_id)
end
task_details[task_id] = {
task_id=task_id,
force=player.force.name,
last_edit_player=player.name,
last_edit_time=game.tick,
editing={[player.name]=true}
}
Store.set(task_store,task_id,'New task')
end
--- Removes all references to a task
local function remove_task(task_id)
local force_name = task_details[task_id].force
Store.clear(task_store,task_id)
task_details[task_id] = nil
table.remove_element(force_tasks[force_name],task_id)
end
local Tasks = require 'modules.control.tasks'
--- If a player is allowed to use the edit buttons
local function player_allowed_edit(player,task_id)
if task_id then
local details = task_details[task_id]
local details = Tasks.get_details(task_id)
if config.user_can_edit_own_tasks and details.last_edit_player == player.name then
return true
end
@@ -88,7 +42,7 @@ Gui.new_button()
style.width = 20
end)
:on_click(function(player,element)
add_task(player)
Tasks.new_task(player.force.name,nil,player.name)
end)
--- Used to save changes to a task
@@ -104,11 +58,8 @@ end)
:on_click(function(player,element)
local task_id = element.parent.name
local task = element.parent.task.text
local details = task_details[task_id]
details.editing[player.name] = nil
details.last_edit_player = player.name
details.last_edit_time = game.tick
Store.set(task_store,task_id,task)
Tasks.set_editing(task_id,player.name)
Tasks.update_task(task_id,task,player.name)
end)
--- Used to cancel any changes you made to a task
@@ -124,8 +75,7 @@ Gui.new_button()
end)
:on_click(function(player,element)
local task_id = element.parent.name
local details = task_details[task_id]
details.editing[player.name] = nil
Tasks.set_editing(task_id,player.name)
generate_task(player,element.parent.parent,task_id)
end)
@@ -141,7 +91,7 @@ Gui.new_button()
end)
:on_click(function(player,element)
local task_id = element.parent.name
remove_task(task_id)
Tasks.remove_task(task_id)
update_all()
end)
@@ -157,8 +107,7 @@ Gui.new_button()
end)
:on_click(function(player,element)
local task_id = element.parent.name
local details = task_details[task_id]
details.editing[player.name] = true
Tasks.set_editing(task_id,player.name,true)
generate_task(player,element.parent.parent.parent,task_id)
end)
@@ -175,12 +124,12 @@ end)
>> discard_task
]]
function generate_task(player,element,task_id)
local task = Store.get(task_store,task_id)
local details = task_details[task_id]
local editing = details.editing[player.name]
local task = Tasks.get_task(task_id)
local editing = Tasks.is_editing(task_id,player.name)
local details = Tasks.get_details(task_id)
local last_edit_player = details.last_edit_player
local last_edit_time = details.last_edit_time
local tasks = force_tasks[player.force.name]
local tasks = Tasks.get_force_tasks(player.force.name)
local task_number = table.index_of(tasks, task_id)
if not task then
@@ -351,18 +300,16 @@ Gui.new_left_frame('gui/task-list')
:set_open_by_default()
:on_creation(function(player,element)
local data_table = generate_container(player,element)
local force_name = player.force.name
local tasks = Tasks.get_force_tasks(player.force.name)
local tasks = force_tasks[force_name] or {}
for _,task_id in pairs(tasks) do
generate_task(player,data_table,task_id)
end
end)
:on_update(function(player,element)
local data_table = element.container.scroll.table
local force_name = player.force.name
local tasks = Tasks.get_force_tasks(player.force.name)
local tasks = force_tasks[force_name] or {}
for _,task_id in pairs(tasks) do
generate_task(player,data_table,task_id)
end
@@ -370,11 +317,8 @@ end)
update_all = task_list 'update_all'
--- When a new task is added it will update the task list for everyone on that force
Store.register(task_store,function(value,task_id)
local details = task_details[task_id]
local force = game.forces[details.force]
--- When a new task is added it will udpate the task list for everyone on that force
Tasks.add_handler(function(force,task_id)
for _,player in pairs(force.players) do
local frame = task_list:get_frame(player)
local element = frame.container.scroll.table

View File

@@ -4,34 +4,25 @@ local Global = require 'utils.global'
local Event = require 'utils.event'
local Game = require 'utils.game'
local Roles = require 'expcore.roles'
local Token = require 'utils.token'
local Colors = require 'resources.color_presets'
local config = require 'config.warps'
local format_time,table_keys,table_values,table_keysort = ext_require('expcore.common','format_time','table_keys','table_values','table_keysort')
local format_time,table_keys = ext_require('expcore.common','format_time','table_keys')
local Warps = require 'modules.control.warps'
local warp_list
local warp_name_store = 'gui.left.warps.names'
local warp_icon_store = 'gui.left.warps.tags'
local warp_player_in_range_store = 'gui.left.warps.in_range'
local warp_list
local warp_details = {}
local force_warps = {}
local keep_open = {}
Global.register({
warp_details=warp_details,
force_warps=force_warps,
keep_open=keep_open
},function(tbl)
force_warps = tbl.force_warps
warp_details = tbl.warp_details
keep_open = tbl.keep_open
Global.register(keep_open,function(tbl)
keep_open = tbl
end)
--- Returns if a player is allowed to edit the given warp
local function player_allowed_edit(player,warp_id)
if warp_id then
local details = warp_details[warp_id]
if not details.editing then
local details = Warps.get_details(warp_id)
local warps = Warps.get_warps(player.force.name)
if warps.spawn == warp_id then
return false
end
if config.user_can_edit_own_warps and details.last_edit_player == player.name then
@@ -54,196 +45,11 @@ local function player_allowed_edit(player,warp_id)
return true
end
--- Makes a map marker for this warp; updates it if already present
local function make_warp_tag(warp_id)
local warp = warp_details[warp_id]
if not warp then return end
local icon = Store.get(warp_icon_store,warp_id)
local name = Store.get(warp_name_store,warp_id)
if warp.tag and warp.tag.valid then
warp.tag.text = 'Warp: '..name
warp.tag.icon = {type='item',name=icon}
return
end
local force = game.forces[warp.force]
local surface = warp.surface
local position = warp.position
local tag = force.add_chart_tag(surface,{
position={position.x+0.5,position.y+0.5},
text='Warp: '..name,
icon={type='item',name=icon}
})
warp.tag = tag
end
-- This creates the area for the warp; this is not required but helps players know where the warps are
local function make_warp_area(warp_id)
local warp = warp_details[warp_id]
if not warp then return end
local position = warp.position
local px = position.x
local py = position.y
local surface = warp.surface
local radius = config.activation_range
local radius2 = radius^2
local old_tile = surface.get_tile(position).name
warp.old_tile = old_tile
local base_tile = config.base_tile
local base_tiles = {}
-- this makes a base plate to make the warp point
for x = -radius, radius do
local x2 = x^2
for y = -radius, radius do
local y2 = y^2
if x2+y2 < radius2 then
table.insert(base_tiles,{name=base_tile,position={x+px,y+py}})
end
end
end
surface.set_tiles(base_tiles)
-- this adds the tile pattern
local tiles = {}
for _,pos in pairs(config.tiles) do
table.insert(tiles,{name=base_tile,position={pos[1]+px,pos[2]+py}})
end
surface.set_tiles(tiles)
-- this adds the entities
for _,entity in pairs(config.entities) do
entity = surface.create_entity{
name=entity[1],
position={entity[2]+px,entity[3]+py},
force='neutral'
}
entity.destructible = false
entity.health = 0
entity.minable = false
entity.rotatable = false
end
end
--- This removes the warp area, also restores the old tile
local function clear_warp_area(warp_id)
local warp = warp_details[warp_id]
if not warp then return end
local position = warp.position
local surface = warp.surface
local radius = config.activation_range
local radius2 = radius^2
local base_tile = warp.old_tile
local tiles = {}
-- clears the area where the warp was
for x = -radius, radius do
local x2 = x^2
for y = -radius, radius do
local y2 = y^2
if x2+y2 < radius2 then
table.insert(tiles,{name=base_tile,position={x+position.x,y+position.y}})
end
end
end
surface.set_tiles(tiles)
-- removes all entities (in the area) on the neutral force
local entities = surface.find_entities_filtered{
force='neutral',
area={
{position.x-radius,position.y-radius},
{position.x+radius,position.y+radius}
}
}
for _,entity in pairs(entities) do if entity.name ~= 'player' then entity.destroy() end end
if warp.tag and warp.tag.valid then warp.tag.destroy() end
end
--- Special case for the warps; adds the spawn warp which cant be removed
local function add_spawn(player)
local warp_id = tostring(Token.uid())
local force = player.force
local force_name = force.name
local surface = player.surface
local spawn = force.get_spawn_position(surface)
if not force_warps[force_name] then
force_warps[force_name] = {}
end
table.insert(force_warps[force_name],warp_id)
warp_details[warp_id] = {
warp_id = warp_id,
force = force.name,
position = {
x=math.floor(spawn.x),
y=math.floor(spawn.y)
},
surface = surface,
last_edit_player='System',
last_edit_time=game.tick,
editing=false
}
Store.set(warp_name_store,warp_id,'Spawn')
Store.set(warp_icon_store,warp_id,config.default_icon)
end
--- General case for the warps; will make a new warp and set the player to be editing it
local function add_warp(player)
local warp_id = tostring(Token.uid())
local force_name = player.force.name
if not force_warps[force_name] then
add_spawn(player)
end
table.insert(force_warps[force_name],warp_id)
local position = player.position
warp_details[warp_id] = {
warp_id = warp_id,
force = force_name,
position = {
x=math.floor(position.x),
y=math.floor(position.y)
},
surface = player.surface,
last_edit_player=player.name,
last_edit_time=game.tick,
editing={[player.name]=true}
}
Store.set(warp_name_store,warp_id,'New warp')
Store.set(warp_icon_store,warp_id,config.default_icon)
make_warp_area(warp_id)
end
--- Removes all references to a warp
local function remove_warp(warp_id)
local force_name = warp_details[warp_id].force
local key = table.index_of(force_warps[force_name],warp_id)
force_warps[force_name][key] = nil
Store.clear(warp_name_store,warp_id)
Store.clear(warp_icon_store,warp_id)
warp_details[warp_id] = nil
end
--- Used on the name label to allow zoom to map
local zoom_to_map_name = Gui.uid_name()
Gui.on_click(zoom_to_map_name,function(event)
local warp_id = event.element.parent.name
local warp = warp_details[warp_id]
local warp = Warps.get_details(warp_id)
local position = warp.position
event.player.zoom_to_world(position,1.5)
end)
@@ -276,18 +82,9 @@ Gui.new_button()
end)
:on_click(function(player,element)
local warp_id = element.parent.caption
local warp = warp_details[warp_id]
local surface = warp.surface
local position = {
x=warp.position.x+0.5,
y=warp.position.y+0.5
}
Warps.teleport_player(warp_id,player)
local goto_position = surface.find_non_colliding_position('character',position,32,1)
if player.driving then player.driving = false end
player.teleport(goto_position,surface)
if config.bypass_warp_limits_permission and not Roles.player_allowed(player,config.bypass_warp_limits_permission) then
if config.bypass_warp_limits_permision and not Roles.player_allowed(player,config.bypass_warp_limits_permision) then
warp_timer:set_store(player.name,0)
-- this is to force an update of the buttons
local in_range = Store.get(warp_player_in_range_store,player.name)
@@ -311,18 +108,17 @@ end)
local py = position.y
local dist2 = config.minimum_distance^2
local warps = Store.get_children(warp_name_store)
for _,warp_id in pairs(warps) do
local warp = warp_details[warp_id]
local warps = Warps.get_all_warps()
for warp_id,warp in pairs(warps) do
local pos = warp.position
if (px-pos.x)^2+(py-pos.y)^2 < dist2 then
local warp_name = Store.get(warp_name_store,warp_id)
if (posx-pos.x)^2+(posy-pos.y)^2 < dist2 then
local warp_name = Warps.get_warp_name(warp_id)
player.print{'warp-list.too-close',warp_name}
return
end
end
add_warp(player)
Warps.new_warp(player.force.name,player.surface,position,player.name)
end)
--- Confirms the edit to name or icon of the warp
@@ -339,12 +135,8 @@ end)
local warp_id = element.parent.name
local warp_name = element.parent.warp.text
local warp_icon = element.parent.parent['icon-'..warp_id].icon.elem_value
local warp = warp_details[warp_id]
warp.editing[player.name] = nil
warp.last_edit_player = player.name
warp.last_edit_time = game.tick
Store.set(warp_name_store,warp_id,warp_name)
Store.set(warp_icon_store,warp_id,warp_icon)
Warps.set_editing(warp_id,player.name)
Warps.update_warp(warp_id,warp_name,warp_icon,player.name)
end)
--- Cancels the editing changes of the selected warp name or icon
@@ -360,8 +152,7 @@ Gui.new_button()
end)
:on_click(function(player,element)
local warp_id = element.parent.name
local details = warp_details[warp_id]
details.editing[player.name] = nil
Warps.set_editing(warp_id,player.name)
generate_warp(player,element.parent.parent,warp_id)
end)
@@ -377,7 +168,7 @@ Gui.new_button()
end)
:on_click(function(player,element)
local warp_id = element.parent.name
remove_warp(warp_id)
Warps.remove_warp(warp_id)
end)
--- Opens edit mode for the warp
@@ -392,8 +183,7 @@ Gui.new_button()
end)
:on_click(function(player,element)
local warp_id = element.parent.name
local details = warp_details[warp_id]
details.editing[player.name] = true
Warps.set_editing(warp_id,player.name,true)
generate_warp(player,element.parent.parent.parent,warp_id)
end)
@@ -411,11 +201,11 @@ end)
>>> discard_warp
]]
function generate_warp(player,element,warp_id)
local warp_name = Store.get(warp_name_store,warp_id)
local warp_icon = Store.get(warp_icon_store,warp_id) or config.default_icon
local warp = warp_details[warp_id]
local warp_name = Warps.get_warp_name(warp_id)
local warp_icon = Warps.get_warp_icon(warp_id)
local warp = Warps.get_details(warp_id)
local editing = warp.editing and warp.editing[player.name]
local editing = Warps.is_editing(warp_id,player.name)
local last_edit_player = warp.last_edit_player
local last_edit_time = warp.last_edit_time
local position = warp.position
@@ -608,22 +398,23 @@ Gui.new_left_frame('gui/warp-list')
:set_direction('vertical')
:on_creation(function(player,element)
local data_table = generate_container(player,element)
local force_name = player.force.name
local warps = Warps.get_warps(player.force.name)
local warps = force_warps[force_name] or {}
for _,warp_id in pairs(warps) do
generate_warp(player,data_table,warp_id)
for key,warp_id in pairs(warps) do
if key ~= 'spawn' then
generate_warp(player,data_table,warp_id)
end
end
end)
:on_update(function(player,element)
local data_table = element.container.scroll.table
local force_name = player.force.name
local warps = Warps.get_warps(player.force.name)
data_table.clear()
local warps = force_warps[force_name] or {}
for _,warp_id in pairs(warps) do
generate_warp(player,data_table,warp_id)
for key,warp_id in pairs(warps) do
if key ~= 'spawn' then
generate_warp(player,data_table,warp_id)
end
end
end)
:on_player_toggle(function(player,element,visible)
@@ -631,47 +422,12 @@ end)
end)
--- When the name of a warp is updated this is triggered
Store.register(warp_name_store,function(value,warp_id)
local warp = warp_details[warp_id]
local force = game.forces[warp.force]
local names = {}
local spawn_id
for _,_warp_id in pairs(force_warps[force.name]) do
local name = Store.get(warp_name_store,_warp_id)
if not warp_details[_warp_id].editing then
spawn_id = _warp_id
else
names[name.._warp_id] = _warp_id
end
end
force_warps[force.name] = table_values(table_keysort(names))
table.insert(force_warps[force.name],1,spawn_id)
Warps.add_handler(function(force,warp_id)
for _,player in pairs(force.players) do
warp_list:update(player)
end
end)
--- When the icon is updated this is called
Store.register(warp_icon_store,function(value,warp_id)
local warp = warp_details[warp_id]
local force = game.forces[warp.force]
for _,player in pairs(force.players) do
local frame = warp_list:get_frame(player)
local element = frame.container.scroll.table
generate_warp(player,element,warp_id)
end
if value then
make_warp_tag(warp_id)
else
clear_warp_area(warp_id)
end
end)
--- When the player leaves or enters range of a warp this is triggered
Store.register(warp_player_in_range_store,function(value,player_name)
local player = game.players[player_name]
@@ -689,17 +445,16 @@ Store.register(warp_player_in_range_store,function(value,player_name)
return
end
if force_warps[force.name] then
for _,warp_id in pairs(force_warps[force.name]) do
local element = table_area['icon-'..warp_id][goto_warp.name]
if element and element.valid then
element.enabled = state
if state then
local position = warp_details[warp_id].position
element.tooltip = {'warp-list.goto-tooltip',position.x,position.y}
else
element.tooltip = {'warp-list.goto-disabled'}
end
local warps = Warps.get_warps(force.name)
for _,warp_id in pairs(warps) do
local element = table_area['icon-'..warp_id][goto_warp.name]
if element and element.valid then
element.enabled = state
if state then
local position = Warps.get_details(warp_id).position
element.tooltip = {'warp-list.goto-tooltip',position.x,position.y}
else
element.tooltip = {'warp-list.goto-disabled'}
end
end
end
@@ -717,15 +472,15 @@ Event.on_nth_tick(math.floor(60/config.update_smoothing),function()
for _,player in pairs(game.connected_players) do
local was_in_range = Store.get(warp_player_in_range_store,player.name)
local force = player.force
local warps = force_warps[force.name]
local warps = Warps.get_warps(force.name)
if warps then
if #warps > 0 then
local surface = player.surface.index
local pos = player.position
local px,py = pos.x,pos.y
for _,warp_id in pairs(warps) do
local warp = warp_details[warp_id]
local warp_pos = warp.position
local warp = Warps.get_details(warp_id)
local wpos = warp.position
if warp.surface.index == surface then
local dx,dy = px-warp_pos.x,py-warp_pos.y
if not warp.editing and (dx*dx)+(dy*dy) < rs2 or (dx*dx)+(dy*dy) < r2 then
@@ -749,7 +504,6 @@ end)
--- When a player is created it will set them being in range to false to stop warping on join
Event.add(defines.events.on_player_created,function(event)
local player = Game.get_player_by_index(event.player_index)
local force_name = player.force.name
local allowed = config.bypass_warp_limits_permission and Roles.player_allowed(player,config.bypass_warp_limits_permission) or false
Store.set(warp_player_in_range_store,player.name,allowed)
@@ -757,24 +511,22 @@ Event.add(defines.events.on_player_created,function(event)
warp_timer:set_store(player.name,1)
end
if not force_warps[force_name] then
add_spawn(player)
end
local force = player.force
local spawn_position = force.get_spawn_position(player.surface)
Warps.new_warp(force.name,player.surface,spawn_position,nil,'Spawn',true,true)
end)
local function maintain_tag(event)
local tag = event.tag
local force = event.force
local warps = force_warps[force.name]
if warps then
for _,warp_id in pairs(warps) do
local warp = warp_details[warp_id]
if not warp.tag or not warp.tag.valid or warp.tag == tag then
if event.name == defines.events.on_chart_tag_removed then
warp.tag = nil
end
make_warp_tag(warp_id)
local warps = Warps.get_warps(force.name)
for _,warp_id in pairs(warps) do
local warp = Warps.get_warps(force.name)
if not warp.tag or not warp.tag.valid or warp.tag == tag then
if event.name == defines.events.on_chart_tag_removed then
warp.tag = nil
end
Warps.make_chart_tag(warp_id)
end
end
end