mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-24 03:47:58 +02:00
269 lines
7.4 KiB
Lua
269 lines
7.4 KiB
Lua
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 |