2019-02-01 23:46:35 +02:00
--[[
Regulates the placement of entities and their ghosts
Can be called through public function to provide lists of allowed or banned entities .
2019-02-02 20:33:30 +02:00
Can also set a keep_alive_callback function to check what is beneath the entity , for example for checking for ores or certain tiles .
2019-02-01 23:46:35 +02:00
2019-02-02 20:33:30 +02:00
Example of keep_alive_callback function to check if there are ores beneath :
function keep_alive_callback ( surface , area )
2019-02-01 23:46:35 +02:00
local count = surface.count_entities_filtered { area = area , type = ' resource ' , limit = 1 }
if count == 0 then
return true
end
end
2019-02-02 20:33:30 +02:00
Allowed entities : are exempt from the keep_alive_callback check and are never destroyed .
2019-02-01 23:46:35 +02:00
Banned entities : are always destroyed .
2019-02-02 20:33:30 +02:00
Maps can hook the on_pre_restricted_entity_destroyed and on_restricted_entity_destroyed events .
2019-02-01 23:46:35 +02:00
] ]
local Event = require ' utils.event '
local Game = require ' utils.game '
local Global = require ' utils.global '
local Token = require ' utils.token '
local table = require ' utils.table '
-- Localized functions
local raise_event = script.raise_event
2019-02-02 20:33:30 +02:00
local deep_copy = table.deep_copy
2019-02-01 23:46:35 +02:00
local Public = {
events = {
--[[
2019-02-02 20:33:30 +02:00
on_pre_restricted_entity_destroyed
Called before an entity is destroyed by this script
2019-02-01 23:46:35 +02:00
Contains
name :: defines . events : Identifier of the event
tick :: uint : Tick the event was generated .
created_entity :: LuaEntity
player_index :: uint
2019-02-02 00:21:42 +02:00
player :: LuaPlayer
2019-02-01 23:46:35 +02:00
stack :: LuaItemStack
ghost :: boolean indicating if the entity was a ghost
] ]
2019-02-02 20:33:30 +02:00
on_pre_restricted_entity_destroyed = script.generate_event_name ( ) ,
--[[
on_restricted_entity_destroyed
Called when an entity is destroyed by this script
Contains
name :: defines . events : Identifier of the event
tick :: uint : Tick the event was generated .
player_index :: uint
player :: LuaPlayer
ghost :: boolean indicating if the entity was a ghost
item_returned :: boolean indicating if the item was returned by this module
] ]
2019-02-01 23:46:35 +02:00
on_restricted_entity_destroyed = script.generate_event_name ( )
}
}
-- Global-registered locals
2019-02-02 20:33:30 +02:00
local allowed_entities = { }
local banned_entities = { }
2019-02-01 23:46:35 +02:00
local primitives = {
event = nil ,
allowed_ents = nil ,
banned_ents = nil ,
2019-02-02 20:33:30 +02:00
keep_alive_callback = nil
2019-02-01 23:46:35 +02:00
}
Global.register (
{
2019-02-02 20:33:30 +02:00
allowed_entities = allowed_entities ,
banned_entities = banned_entities ,
2019-02-01 23:46:35 +02:00
primitives = primitives
} ,
function ( tbl )
2019-02-02 20:33:30 +02:00
allowed_entities = tbl.allowed_entities
banned_entities = tbl.banned_entities
2019-02-01 23:46:35 +02:00
primitives = tbl.primitives
end
)
-- Local functions
--- Token for on_built callback, checks if an entity should be destroyed.
local on_built_token =
Token.register (
function ( event )
local entity = event.created_entity
if not entity or not entity.valid then
return
end
local name = entity.name
if name == ' tile-ghost ' then
return
end
local ghost = false
if name == ' entity-ghost ' then
name = entity.ghost_name
ghost = true
end
2019-02-02 20:33:30 +02:00
if primitives.allowed_ents and allowed_entities [ name ] then
2019-02-01 23:46:35 +02:00
return
end
2019-02-02 20:33:30 +02:00
-- Takes the keep_alive_callback function (if provided) and runs it with the entity as an argument
-- If true is returned, we exit. If false, we destroy the entity and return the itemstack to the player (if possible)
local keep_alive_callback = primitives.keep_alive_callback
if not banned_entities [ name ] and keep_alive_callback and keep_alive_callback ( entity ) then
2019-02-01 23:46:35 +02:00
return
end
2019-02-02 20:33:30 +02:00
local p = Game.get_player_by_index ( event.player_index )
if not p or not p.valid then
2019-02-01 23:46:35 +02:00
return
end
2019-02-02 20:33:30 +02:00
event.ghost = ghost
event.player = p
raise_event ( Public.events . on_pre_restricted_entity_destroyed , deep_copy ( event ) ) -- use deepcopy so that any potential writes to `event` aren't passed backwards
2019-02-01 23:46:35 +02:00
2019-02-02 20:33:30 +02:00
-- Need to revalidate the entity since we sent it via the event
if entity.valid then
entity.destroy ( )
2019-02-01 23:46:35 +02:00
end
2019-02-02 20:33:30 +02:00
-- Need to revalidate the stack since we sent it via the event
local stack = event.stack
2019-02-01 23:46:35 +02:00
event.item_returned = false
2019-02-02 20:33:30 +02:00
if not ghost and stack.valid then
p.insert ( stack )
2019-02-01 23:46:35 +02:00
event.item_returned = true
end
2019-02-02 20:33:30 +02:00
event.stack = nil
event.created_entity = nil
2019-02-01 23:46:35 +02:00
raise_event ( Public.events . on_restricted_entity_destroyed , event )
end
)
--- Adds the event hook for on_built_entity
local function add_event ( )
if not primitives.event then
Event.add_removable ( defines.events . on_built_entity , on_built_token )
primitives.event = true
end
end
--- Removes the event hook for on_built_entity
local function remove_event ( )
if primitives.event then
Event.remove_removable ( defines.events . on_built_entity , on_built_token )
primitives.event = nil
end
end
-- Public functions
2019-02-02 20:33:30 +02:00
--- Sets the function to be used for keep_alive_callback
-- @param keep_alive_callback <function>
function Public . set_keep_alive_callback ( keep_alive_callback )
primitives.keep_alive_callback = keep_alive_callback
2019-02-01 23:46:35 +02:00
end
--- Adds to the list of allowed entities
-- @param ents <table> array of entity strings
function Public . add_allowed ( ents )
primitives.allowed_ents = true
for _ , v in pairs ( ents ) do
2019-02-02 20:33:30 +02:00
allowed_entities [ v ] = true
2019-02-01 23:46:35 +02:00
end
if not primitives.event then
add_event ( )
end
end
--- Removes from the list of allowed entities
-- @param ents <table> array of entity strings
function Public . remove_allowed ( ents )
for _ , v in pairs ( ents ) do
2019-02-02 20:33:30 +02:00
allowed_entities [ v ] = nil
2019-02-01 23:46:35 +02:00
end
2019-02-02 20:33:30 +02:00
if table.size ( allowed_entities ) == 0 then
2019-02-01 23:46:35 +02:00
primitives.allowed_ents = nil
if primitives.event and not primitives.banned_ents then
remove_event ( )
end
end
end
--- Resets the list of banned entities
function Public . reset_allowed ( )
2019-02-02 20:33:30 +02:00
table.clear_table ( allowed_entities )
2019-02-01 23:46:35 +02:00
primitives.allowed_ents = nil
if primitives.event and not primitives.banned_ents then
remove_event ( )
end
end
--- Adds to the list of banned entities
-- @param ents <table> array of entity strings
function Public . add_banned ( ents )
primitives.banned_ents = true
for _ , v in pairs ( ents ) do
2019-02-02 20:33:30 +02:00
banned_entities [ v ] = true
2019-02-01 23:46:35 +02:00
end
if not primitives.event then
add_event ( )
end
end
--- Removes from the list of banned entities
-- @param ents <table> array of entity strings
function Public . remove_banned ( ents )
for _ , v in pairs ( ents ) do
2019-02-02 20:33:30 +02:00
banned_entities [ v ] = nil
2019-02-01 23:46:35 +02:00
end
2019-02-02 20:33:30 +02:00
if table.size ( banned_entities ) == 0 then
2019-02-01 23:46:35 +02:00
primitives.banned_ents = nil
if primitives.event and not primitives.allowed_ents then
remove_event ( )
end
end
end
--- Resets the list of banned entities
function Public . reset_banned ( )
primitives.banned_ents = nil
2019-02-02 20:33:30 +02:00
table.clear_table ( banned_entities )
2019-02-01 23:46:35 +02:00
if primitives.event and not primitives.allowed_ents then
remove_event ( )
end
end
return Public