1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-08 00:39:30 +02:00
ComfyFactorio/modules/scrap_towny_ffa/building.lua
2021-03-24 20:14:55 +01:00

302 lines
8.5 KiB
Lua

--luacheck: ignore
local Public = {}
local Table = require 'modules.scrap_towny_ffa.table'
local town_radius = 27
local connection_radius = 7
local neutral_whitelist = {
['wooden-chest'] = true,
['iron-chest'] = true,
['steel-chest'] = true,
['raw-fish'] = true
}
local entity_type_whitelist = {
['accumulator'] = true,
['ammo-turret'] = true,
['arithmetic-combinator'] = true,
['artillery-turret'] = true,
['assembling-machine'] = true,
['boiler'] = true,
['constant-combinator'] = true,
['container'] = true,
['curved-rail'] = true,
['decider-combinator'] = true,
['electric-pole'] = true,
['electric-turret'] = true,
['fluid-turret'] = true,
['furnace'] = true,
['gate'] = true,
['generator'] = true,
['heat-interface'] = true,
['heat-pipe'] = true,
['infinity-container'] = true,
['infinity-pipe'] = true,
['inserter'] = true,
['lab'] = true,
['lamp'] = true,
['land-mine'] = true,
['loader'] = true,
['logistic-container'] = true,
['market'] = true,
['mining-drill'] = true,
['offshore-pump'] = true,
['pipe'] = true,
['pipe-to-ground'] = true,
['programmable-speaker'] = true,
['pump'] = true,
['radar'] = true,
['rail-chain-signal'] = true,
['rail-signal'] = true,
['reactor'] = true,
['roboport'] = true,
['rocket-silo'] = true,
['solar-panel'] = true,
['splitter'] = true,
['storage-tank'] = true,
['straight-rail'] = true,
['train-stop'] = true,
['transport-belt'] = true,
['underground-belt'] = true,
['wall'] = true
}
local function isolated(surface, force, position)
local position_x = position.x
local position_y = position.y
local area = {{position_x - connection_radius, position_y - connection_radius}, {position_x + connection_radius, position_y + connection_radius}}
local count = 0
for _, e in pairs(surface.find_entities_filtered({area = area, force = force.name})) do
if entity_type_whitelist[e.type] then
count = count + 1
if count > 1 then
return false
end -- are there more than one team entities in the area?
end
end
return true
end
local function refund_item(event, item_name)
if item_name == 'blueprint' then
return
end
if event.player_index then
game.players[event.player_index].insert({name = item_name, count = 1})
return
end
if event.robot then
local inventory = event.robot.get_inventory(defines.inventory.robot_cargo)
inventory.insert({name = item_name, count = 1})
return
end
end
local function error_floaty(surface, position, msg)
surface.create_entity(
{
name = 'flying-text',
position = position,
text = msg,
color = {r = 0.77, g = 0.0, b = 0.0}
}
)
end
local function in_range(pos1, pos2, radius)
if pos1 == nil then
return false
end
if pos2 == nil then
return false
end
if radius < 1 then
return true
end
local dx = pos1.x - pos2.x
local dy = pos1.y - pos2.y
if dx ^ 2 + dy ^ 2 < radius ^ 2 then
return true
end
return false
end
-- is the position near a town?
function Public.near_town(position, surface, radius)
local ffatable = Table.get_table()
for _, town_center in pairs(ffatable.town_centers) do
if town_center ~= nil then
local market = town_center.market
if in_range(position, market.position, radius) and market.surface == surface then
return true
end
end
end
return false
end
local function in_town(force, position)
local ffatable = Table.get_table()
local town_center = ffatable.town_centers[force.name]
if town_center ~= nil then
local center = town_center.market.position
if position.x >= center.x - town_radius and position.x <= center.x + town_radius then
if position.y >= center.y - town_radius and position.y <= center.y + town_radius then
return true
end
end
end
return false
end
local function prevent_isolation_entity(event, player)
local p = player or nil
local entity = event.created_entity
local position = entity.position
if not entity.valid then
return
end
local entity_name = entity.name
local item = event.item
if item == nil then
return
end
local item_name = item.name
local force = entity.force
if force == game.forces.player then
return
end
if force == game.forces['rogue'] then
return
end
local surface = entity.surface
local error = false
if not in_town(force, position) and isolated(surface, force, position) then
error = true
entity.destroy()
if entity_name ~= 'entity-ghost' and entity_name ~= 'tile-ghost' then
refund_item(event, item_name)
end
--return true
end
if error == true then
if p ~= nil then
p.play_sound({path = 'utility/cannot_build', position = p.position, volume_modifier = 0.75})
end
error_floaty(surface, position, 'Building is not connected to town!')
end
end
local function prevent_isolation_tile(event, player)
local p = player or nil
local tile = event.tile
if not tile.valid then
return
end
local tile_name = tile.name
local surface = game.surfaces[event.surface_index]
local tiles = event.tiles
local force
if event.player_index then
force = game.players[event.player_index].force
else
force = event.robot.force
end
local error = false
local position
for _, t in pairs(tiles) do
local old_tile = t.old_tile
position = t.position
if not in_town(force, position) and isolated(surface, force, position) then
error = true
surface.set_tiles({{name = old_tile.name, position = position}}, true)
if tile_name ~= 'tile-ghost' then
if tile_name == 'stone-path' then
tile_name = 'stone-brick'
end
refund_item(event, tile_name)
end
end
end
if error == true then
if p ~= nil then
p.play_sound({path = 'utility/cannot_build', position = p.position, volume_modifier = 0.75})
end
error_floaty(surface, position, 'Tile is not connected to town!')
end
end
local function restrictions(event, player)
local p = player or nil
local entity = event.created_entity
if not entity.valid then
return
end
local entity_name = entity.name
local surface = entity.surface
local position = entity.position
local error = false
if entity.force == game.forces['player'] or entity.force == game.forces['rogue'] then
if Public.near_town(position, surface, 32) then
error = true
entity.destroy()
if entity_name ~= 'entity-ghost' then
refund_item(event, event.stack.name)
end
else
entity.force = game.forces['neutral']
end
return
end
if error == true then
if p ~= nil then
p.play_sound({path = 'utility/cannot_build', position = p.position, volume_modifier = 0.75})
end
error_floaty(surface, position, "Can't build near town!")
end
if not neutral_whitelist[entity.type] then
return
end
entity.force = game.forces['neutral']
end
-- called when a player places an item, or a ghost
local function on_built_entity(event)
local player = game.players[event.player_index]
if prevent_isolation_entity(event, player) then
return
end
restrictions(event, player)
end
local function on_robot_built_entity(event)
if prevent_isolation_entity(event) then
return
end
restrictions(event)
end
-- called when a player places landfill
local function on_player_built_tile(event)
local player = game.players[event.player_index]
prevent_isolation_tile(event, player)
end
local function on_robot_built_tile(event)
prevent_isolation_tile(event)
end
local Event = require 'utils.event'
Event.add(defines.events.on_built_entity, on_built_entity)
Event.add(defines.events.on_player_built_tile, on_player_built_tile)
Event.add(defines.events.on_robot_built_entity, on_robot_built_entity)
Event.add(defines.events.on_robot_built_tile, on_robot_built_tile)
return Public