mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-27 11:35:22 +09:00
Merge branch 'dev' into feature/entity-alert
This commit is contained in:
66
modules/addons/afk-kick.lua
Normal file
66
modules/addons/afk-kick.lua
Normal file
@@ -0,0 +1,66 @@
|
||||
--- Kicks players when all players on the server are afk
|
||||
-- @addon afk-kick
|
||||
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local Global = require 'utils.global' --- @dep utils.global
|
||||
local config = require 'config.afk_kick' --- @dep config.afk_kick
|
||||
local Async = require 'expcore.async' --- @dep expcore.async
|
||||
|
||||
--- Optional roles require
|
||||
local Roles
|
||||
if config.active_role then
|
||||
Roles = require 'expcore.roles'
|
||||
end
|
||||
|
||||
--- Globals
|
||||
local primitives = { last_active = 0 }
|
||||
Global.register(primitives, function(tbl)
|
||||
primitives = tbl
|
||||
end)
|
||||
|
||||
--- Kicks an afk player, used to add a delay so the gui has time to appear
|
||||
local kick_player =
|
||||
Async.register(function(player)
|
||||
if game.tick - primitives.last_active < config.kick_time then return end -- Safety Catch
|
||||
game.kick_player(player, 'AFK while no active players on the server')
|
||||
end)
|
||||
|
||||
--- Check for an active player every update_time number of ticks
|
||||
Event.on_nth_tick(config.update_time, function()
|
||||
-- Check for active players
|
||||
for _, player in ipairs(game.connected_players) do
|
||||
if player.afk_time < config.afk_time
|
||||
or config.admin_as_active and config.player.admin
|
||||
or config.trust_as_active and player.online_time > config.trust_time
|
||||
or config.active_role and Roles.player_has_role(player, config.active_role) then
|
||||
-- Active player was found
|
||||
primitives.last_active = game.tick
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- No active player was found, check if players should be kicked
|
||||
if game.tick - primitives.last_active < config.kick_time then return end
|
||||
|
||||
-- Kick time exceeded, kick all players
|
||||
for _, player in ipairs(game.connected_players) do
|
||||
-- Add a frame to say why the player was kicked
|
||||
local res = player.display_resolution
|
||||
local uis = player.display_scale
|
||||
player.gui.screen.add{
|
||||
type = 'frame',
|
||||
name = 'afk-kick',
|
||||
caption = {'afk-kick.message'},
|
||||
}.location = { x=res.width*(0.5 - 0.11*uis), y=res.height*(0.5 - 0.14*uis) }
|
||||
|
||||
-- Kick the player, some delay needed because network delay
|
||||
Async.wait(10, kick_player, player)
|
||||
end
|
||||
end)
|
||||
|
||||
--- Remove the screen gui if it is present
|
||||
Event.add(defines.events.on_player_joined_game, function(event)
|
||||
local player = game.get_player(event.player_index)
|
||||
local frame = player.gui.screen["afk-kick"]
|
||||
if frame and frame.valid then frame.destroy() end
|
||||
end)
|
||||
@@ -59,7 +59,7 @@ local function emit_event(args)
|
||||
}
|
||||
|
||||
local new_value, inline = value:gsub('<inline>', '', 1)
|
||||
if inline then
|
||||
if inline > 0 then
|
||||
field.value = new_value
|
||||
field.inline = true
|
||||
end
|
||||
@@ -102,6 +102,7 @@ if config.player_reports then
|
||||
color=Colors.yellow,
|
||||
['Player']='<inline>'..player_name,
|
||||
['By']='<inline>'..by_player_name,
|
||||
['Report Count']='<inline>'..Reports.count_reports(player_name),
|
||||
['Reason']=event.reason
|
||||
}
|
||||
end)
|
||||
@@ -114,7 +115,7 @@ if config.player_reports then
|
||||
color=Colors.green,
|
||||
['Player']='<inline>'..player_name,
|
||||
['By']='<inline>'..event.removed_by_name,
|
||||
['Amount']='<inline>'..event.batch_count
|
||||
['Report Count']='<inline>'..event.batch_count
|
||||
}
|
||||
end)
|
||||
end
|
||||
@@ -124,12 +125,14 @@ if config.player_warnings then
|
||||
local Warnings = require 'modules.control.warnings' --- @dep modules.control.warnings
|
||||
Event.add(Warnings.events.on_warning_added, function(event)
|
||||
local player_name, by_player_name = get_player_name(event)
|
||||
local player = game.get_player(player_name)
|
||||
emit_event{
|
||||
title='Warning',
|
||||
description='A player has been given a warning',
|
||||
color=Colors.yellow,
|
||||
['Player']='<inline>'..player_name,
|
||||
['By']='<inline>'..by_player_name,
|
||||
['Warning Count']='<inline>'..Warnings.count_warnings(player),
|
||||
['Reason']=event.reason
|
||||
}
|
||||
end)
|
||||
@@ -142,7 +145,7 @@ if config.player_warnings then
|
||||
color=Colors.green,
|
||||
['Player']='<inline>'..player_name,
|
||||
['By']='<inline>'..event.removed_by_name,
|
||||
['Amount']='<inline>'..event.batch_count
|
||||
['Warning Count']='<inline>'..event.batch_count
|
||||
}
|
||||
end)
|
||||
end
|
||||
|
||||
25
modules/addons/report-jail.lua
Normal file
25
modules/addons/report-jail.lua
Normal file
@@ -0,0 +1,25 @@
|
||||
--- When a player is reported, the player is automatically jailed if the combined playtime of the reporters exceeds the reported player
|
||||
-- @addon report-jail
|
||||
|
||||
local Event = require 'utils.event' ---@dep utils.event
|
||||
local Jail = require 'modules.control.jail' ---@dep modules.control.jail
|
||||
local Reports = require 'modules.control.reports' --- @dep modules.control.reports
|
||||
local format_chat_player_name = _C.format_chat_player_name --- @dep expcore.common
|
||||
|
||||
--- Returns the playtime of the reporter. Used when calculating the total playtime of all reporters
|
||||
local function reporter_playtime(_, by_player_name, _)
|
||||
local player = game.get_player(by_player_name)
|
||||
if player == nil then return 0 end
|
||||
return player.online_time
|
||||
end
|
||||
|
||||
--- Tests the combined playtime of all reporters against the reported player
|
||||
Event.add(Reports.events.on_player_reported, function(event)
|
||||
local player = game.get_player(event.player_index)
|
||||
local total_playtime = Reports.count_reports(player, reporter_playtime)
|
||||
if total_playtime < player.online_time*1.5 then return end
|
||||
-- Combined playtime is greater than 150% of the reported's playtime
|
||||
local player_name_color = format_chat_player_name(player)
|
||||
Jail.jail_player(player, '<reports>', 'Reported by too many players, please wait for a moderator.')
|
||||
game.print{'report-jail.jail', player_name_color}
|
||||
end)
|
||||
@@ -4,16 +4,23 @@
|
||||
local Global = require 'utils.global' --- @dep utils.global
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local config = require 'config.spawn_area' --- @dep config.spawn_area
|
||||
local tiles = config.tiles
|
||||
local entities = config.entities
|
||||
local belts = config.afk_belts.locations
|
||||
local turrets = config.infinite_ammo_turrets.locations
|
||||
|
||||
local turrets = config.turrets.locations
|
||||
Global.register(turrets, function(tbl)
|
||||
turrets = tbl
|
||||
end)
|
||||
|
||||
-- returns the Spawn force or creates it
|
||||
-- Apply an offset to a LuaPosition
|
||||
local function apply_offset(position, offset)
|
||||
return { x = position.x + (offset.x or offset[1]), y = position.y + (offset.y or offset[2]) }
|
||||
end
|
||||
|
||||
-- Apply the offset to the turrets default position
|
||||
for _, turret in ipairs(turrets) do
|
||||
turret.position = apply_offset(turret.position, config.turrets.offset)
|
||||
end
|
||||
|
||||
-- Get or create the force used for entities in spawn
|
||||
local function get_spawn_force()
|
||||
local force = game.forces['Spawn']
|
||||
if force and force.valid then return force end
|
||||
@@ -23,7 +30,7 @@ local function get_spawn_force()
|
||||
return force
|
||||
end
|
||||
|
||||
-- protects and entity so players cant do anything to it
|
||||
-- Protects an entity and sets its force to the spawn force
|
||||
local function protect_entity(entity, set_force)
|
||||
if entity and entity.valid then
|
||||
entity.destructible = false
|
||||
@@ -35,113 +42,133 @@ local function protect_entity(entity, set_force)
|
||||
end
|
||||
end
|
||||
|
||||
-- handles the infinite ammo turrets
|
||||
-- Will spawn all infinite ammo turrets and keep them refilled
|
||||
local function spawn_turrets()
|
||||
if config.infinite_ammo_turrets.enabled then
|
||||
for _, turret_pos in pairs(turrets) do
|
||||
local surface = game.surfaces[turret_pos.surface]
|
||||
local pos = turret_pos.position
|
||||
local turret = surface.find_entity('gun-turret', pos)
|
||||
-- Makes a new turret if it is not found
|
||||
if not turret or not turret.valid then
|
||||
turret = surface.create_entity{name='gun-turret', position=pos, force='Spawn'}
|
||||
protect_entity(turret, true)
|
||||
end
|
||||
-- adds ammo to the turret
|
||||
local inv = turret.get_inventory(defines.inventory.turret_ammo)
|
||||
if inv.can_insert{name=config.infinite_ammo_turrets.ammo_type, count=10} then
|
||||
inv.insert{name=config.infinite_ammo_turrets.ammo_type, count=10}
|
||||
end
|
||||
for _, turret_pos in pairs(turrets) do
|
||||
local surface = game.surfaces[turret_pos.surface]
|
||||
local pos = turret_pos.position
|
||||
local turret = surface.find_entity('gun-turret', pos)
|
||||
|
||||
-- Makes a new turret if it is not found
|
||||
if not turret or not turret.valid then
|
||||
turret = surface.create_entity{name='gun-turret', position=pos, force='Spawn'}
|
||||
protect_entity(turret, true)
|
||||
end
|
||||
|
||||
-- Adds ammo to the turret
|
||||
local inv = turret.get_inventory(defines.inventory.turret_ammo)
|
||||
if inv.can_insert{name=config.turrets.ammo_type, count=10} then
|
||||
inv.insert{name=config.turrets.ammo_type, count=10}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- makes a 2x2 afk belt where set in config
|
||||
-- Makes a 2x2 afk belt at the locations in the config
|
||||
local function spawn_belts(surface, position)
|
||||
position = apply_offset(position, config.afk_belts.offset)
|
||||
local belt_type = config.afk_belts.belt_type
|
||||
local belt_details = {{-0.5, -0.5, 2}, {0.5, -0.5, 4}, {-0.5, 0.5, 0}, {0.5, 0.5, 6}} -- x, y,dir
|
||||
for _, belt_set in pairs(belts) do
|
||||
local o = position
|
||||
local p = belt_set
|
||||
for _, belt_set in pairs(config.afk_belts.locations) do
|
||||
local set_position = apply_offset(position, belt_set)
|
||||
for _, belt in pairs(belt_details) do
|
||||
local pos = {x=o.x+p.x+belt[1], y=o.y+p.y+belt[2]}
|
||||
local belt_entity = surface.create_entity{name='transport-belt', position=pos, force='neutral', direction=belt[3]}
|
||||
protect_entity(belt_entity)
|
||||
local pos = apply_offset(set_position, belt)
|
||||
local belt_entity = surface.create_entity{name=belt_type, position=pos, force='neutral', direction=belt[3]}
|
||||
if config.afk_belts.protected then protect_entity(belt_entity) end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- generates an area with no water and removes entities in the decon area
|
||||
local function spawn_base(surface, position)
|
||||
local dr = config.corrections.deconstruction_radius
|
||||
local dr2 = dr^2
|
||||
local dtile = config.corrections.deconstruction_tile
|
||||
local pr = config.corrections.pattern_radius
|
||||
local pr2 = pr^2
|
||||
local ptile = surface.get_tile(position).name
|
||||
if ptile == 'deepwater' or ptile == 'water' then ptile = 'grass-1' end
|
||||
-- Generates extra tiles in a set pattern as defined in the config
|
||||
local function spawn_pattern(surface, position)
|
||||
position = apply_offset(position, config.pattern.offset)
|
||||
local tiles_to_make = {}
|
||||
for x = -pr, pr do -- loop over x
|
||||
local x2 = x^2
|
||||
for y = -pr, pr do -- loop over y
|
||||
local y2 = y^2
|
||||
local prod = x2+y2
|
||||
local p = {x=position.x+x, y=position.y+y}
|
||||
if prod < dr2 then
|
||||
-- if it is inside the decon radius
|
||||
table.insert(tiles_to_make, {name=dtile, position=p})
|
||||
local entities_to_remove = surface.find_entities_filtered{area={{p.x-1, p.y-1}, {p.x, p.y}}}
|
||||
for _, entity in pairs(entities_to_remove) do
|
||||
if entity.name ~= 'character' then entity.destroy() end
|
||||
end
|
||||
elseif prod < pr2 then
|
||||
-- if it is inside the pattern radius
|
||||
table.insert(tiles_to_make, {name=ptile, position=p})
|
||||
local pattern_tile = config.pattern.pattern_tile
|
||||
for _, tile in pairs(config.pattern.locations) do
|
||||
table.insert(tiles_to_make, {name=pattern_tile, position=apply_offset(position, tile)})
|
||||
end
|
||||
surface.set_tiles(tiles_to_make)
|
||||
end
|
||||
|
||||
-- Generates extra water as defined in the config
|
||||
local function spawn_water(surface, position)
|
||||
position = apply_offset(position, config.water.offset)
|
||||
local tiles_to_make = {}
|
||||
local water_tile = config.water.water_tile
|
||||
for _, tile in pairs(config.water.locations) do
|
||||
table.insert(tiles_to_make, {name=water_tile, position=apply_offset(position, tile)})
|
||||
end
|
||||
surface.set_tiles(tiles_to_make)
|
||||
end
|
||||
|
||||
-- Generates the entities that are in the config
|
||||
local function spawn_entities(surface, position)
|
||||
position = apply_offset(position, config.entities.offset)
|
||||
for _, entity in pairs(config.entities.locations) do
|
||||
local pos = apply_offset(position, { x=entity[2], y=entity[3] })
|
||||
entity = surface.create_entity{name=entity[1], position=pos, force='neutral'}
|
||||
if config.entities.protected then protect_entity(entity) end
|
||||
entity.operable = config.entities.operable
|
||||
end
|
||||
end
|
||||
|
||||
-- Generates an area with no water or entities, no water area is larger
|
||||
local function spawn_area(surface, position)
|
||||
local dr = config.spawn_area.deconstruction_radius
|
||||
local dr2 = dr^2
|
||||
local decon_tile = config.spawn_area.deconstruction_tile
|
||||
|
||||
local fr = config.spawn_area.landfill_radius
|
||||
local fr2 = fr^2
|
||||
local fill_tile = surface.get_tile(position).name
|
||||
|
||||
-- Make sure a non water tile is used for each tile
|
||||
if surface.get_tile(position).collides_with('player-layer') then fill_tile = 'landfill' end
|
||||
if decon_tile == nil then decon_tile = fill_tile end
|
||||
|
||||
local tiles_to_make = {}
|
||||
for x = -fr, fr do -- loop over x
|
||||
local x2 = (x+0.5)^2
|
||||
for y = -fr, fr do -- loop over y
|
||||
local y2 = (y+0.5)^2
|
||||
local dst = x2+y2
|
||||
local pos = {x=position.x+x, y=position.y+y}
|
||||
if dst < dr2 then
|
||||
-- If it is inside the decon radius always set the tile
|
||||
table.insert(tiles_to_make, {name=decon_tile, position=pos})
|
||||
elseif dst < fr2 and surface.get_tile(pos).collides_with('player-layer') then
|
||||
-- If it is inside the fill radius only set the tile if it is water
|
||||
table.insert(tiles_to_make, {name=fill_tile, position=pos})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove entities then set the tiles
|
||||
local entities_to_remove = surface.find_entities_filtered{position=position, radius=dr, name='character', invert=true}
|
||||
for _, entity in pairs(entities_to_remove) do entity.destroy() end
|
||||
surface.set_tiles(tiles_to_make)
|
||||
end
|
||||
|
||||
-- generates the pattern that is in the config
|
||||
local function spawn_pattern(surface, position)
|
||||
local tiles_to_make = {}
|
||||
local ptile = config.corrections.pattern_tile
|
||||
local o = config.corrections.offset
|
||||
local p = {x=position.x+o.x, y=position.y+o.y}
|
||||
for _, tile in pairs(tiles) do
|
||||
table.insert(tiles_to_make, {name=ptile, position={tile[1]+p.x, tile[2]+p.y}})
|
||||
end
|
||||
surface.set_tiles(tiles_to_make)
|
||||
-- Only add a event handler if the turrets are enabled
|
||||
if config.turrets.enabled then
|
||||
Event.on_nth_tick(config.turrets.refill_time, function()
|
||||
if game.tick < 10 then return end
|
||||
spawn_turrets()
|
||||
end)
|
||||
end
|
||||
|
||||
-- generates the entities that are in the config
|
||||
local function spawn_entities(surface, position)
|
||||
local o = config.corrections.offset
|
||||
local p = {x=position.x+o.x, y=position.y+o.y}
|
||||
for _, entity in pairs(entities) do
|
||||
entity = surface.create_entity{name=entity[1], position={entity[2]+p.x, entity[3]+p.y}, force='neutral'}
|
||||
protect_entity(entity)
|
||||
entity.operable = true
|
||||
end
|
||||
end
|
||||
|
||||
local refill_time = 60*60*5 -- 5 minutes
|
||||
Event.on_nth_tick(refill_time, function()
|
||||
if game.tick < 10 then return end
|
||||
spawn_turrets()
|
||||
end)
|
||||
|
||||
-- When the first player joins create the spawn area
|
||||
Event.add(defines.events.on_player_created, function(event)
|
||||
if event.player_index ~= 1 then return end
|
||||
local player = game.players[event.player_index]
|
||||
local p = {x=0, y=0}
|
||||
local s = player.surface
|
||||
spawn_base(s, p)
|
||||
spawn_pattern(s, p)
|
||||
get_spawn_force()
|
||||
spawn_entities(s, p)
|
||||
spawn_belts(s, p)
|
||||
spawn_turrets()
|
||||
spawn_area(s, p)
|
||||
if config.pattern.enabled then spawn_pattern(s, p) end
|
||||
if config.water.enabled then spawn_water(s, p) end
|
||||
if config.afk_belts.enabled then spawn_belts(s, p) end
|
||||
if config.turrets.enabled then spawn_turrets() end
|
||||
if config.entities.enabled then spawn_entities(s, p) end
|
||||
player.teleport(p, s)
|
||||
end)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user