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-03 01:29:20 +02:00
|
|
|
Can also set a keep_alive_callback function to process information about the entity about to be destroyed
|
|
|
|
for example, checking for resources underneath the entity or checking the pollution in the entity's chunk.
|
2019-02-01 23:46:35 +02:00
|
|
|
|
2019-02-03 01:29:20 +02:00
|
|
|
Example of keep_alive_callback function to check if there are resources beneath:
|
|
|
|
function keep_alive_callback (entity)
|
|
|
|
local count = entity.surface.count_entities_filtered {area = area, type = 'resource', limit = 1}
|
2019-02-01 23:46:35 +02:00
|
|
|
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
|
2019-02-03 01:45:04 +02:00
|
|
|
raise_event(Public.events.on_pre_restricted_entity_destroyed, event)
|
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
|