1
0
mirror of https://github.com/Refactorio/RedMew.git synced 2025-03-17 21:08:08 +02:00

Merge pull request #991 from SimonFlapse/concrete_jungle

Concrete Jungle - the map is complete, only remaining things to do are are 
- migrate description to wiki
- add cutscene 
- bring into regular map rotation (this is an interesting map that we should run more often)
This commit is contained in:
theorangeangle 2020-05-10 16:23:52 -05:00 committed by GitHub
commit f474b562af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 675 additions and 38 deletions

View File

@ -169,7 +169,7 @@ global.config = {
-- prints messages when the player joins -- prints messages when the player joins
join_messages = { join_messages = {
'Welcome to this map created by the RedMew team. You can join our discord at: redmew.com/discord', 'Welcome to this map created by the RedMew team. You can join our discord at: redmew.com/discord',
'Click the question mark in the top left corner for server information and map details.' 'Click the infomation icon in the top left corner for server information and map details.'
}, },
cutscene = false, cutscene = false,
-- format is a table: {{message, weight}, {message, weight}}, where a higher weight has more chance to be shown -- format is a table: {{message, weight}, {message, weight}}, where a higher weight has more chance to be shown

View File

@ -154,3 +154,18 @@ switch_msg=Go ahead and pick a quadrant you'd like to help out!
force_sync_research=New research complete: force_sync_research=New research complete:
train_notice1=## - Your items have been returned to __1__ at: train_notice1=## - Your items have been returned to __1__ at:
# locale linked to concrete jungle
[concrete_jungle]
welcome_popup_title=Welcome to Concrete jungle
welcome_popup_player_name=Hello __1__
welcome_popup_line_1=Most items can't be placed on the ground!
welcome_popup_line_2=Place stone brick, concrete or reinforced concrete on the ground,\nbefore placing items and machines!
welcome_popup_line_3=More information can be found in the __1__ tab\nin __3__ __2__
blueprint=blueprint
blueprint_not_enough_ground_support=Some parts of this __1__ cannot be placed here, they need better ground support!
entity_not_enough_ground_support=__1__ requires at least: __2__
anti_grief_kick_reason=Spilling too many items on the ground
anti_grief_jail_reason=You have spilled too many items on the ground, contact an admin

Binary file not shown.

After

Width:  |  Height:  |  Size: 967 KiB

View File

@ -0,0 +1,503 @@
local floor = math.floor
local RestrictEntities = require 'map_gen.shared.entity_placement_restriction'
local Event = require 'utils.event'
local b = require 'map_gen.shared.builders'
local Token = require 'utils.token'
local Color = require 'resources.color_presets'
local Retailer = require 'features.retailer'
local Task = require 'utils.task'
local Popup = require 'features.gui.popup'
local Global = require 'utils.global'
local Report = require 'features.report'
local Rank = require 'features.rank_system'
local Ranks = require 'resources.ranks'
local redmew_config = global.config
-- Needed because refined hazard concrete is needed and must not be changed by this module
redmew_config.paint.enabled = false
local concrete_unlocker = true -- Set to false to disable early unlocking of concrete
local market_remove_concrete =
Token.register(
function()
Retailer.remove_item('fish_market', 'refined-hazard-concrete')
end
)
local function on_init() --Out comment stuff you don't want to enable
game.difficulty_settings.technology_price_multiplier = 4
--game.forces.player.technologies.logistics.researched = true
game.forces.player.technologies.automation.researched = true
Task.set_timeout_in_ticks(100, market_remove_concrete)
end
if concrete_unlocker then
Event.add(
defines.events.on_research_finished,
function(event)
local p_force = game.forces.player
local r = event.research
if r.name == 'advanced-material-processing' then
p_force.recipes['concrete'].enabled = true
end
end
)
end
local times_spilled = {}
Global.register(
{
times_spilled = times_spilled
},
function(tbl)
times_spilled = tbl.times_spilled
end
)
local ScenarioInfo = require 'features.gui.info'
ScenarioInfo.set_map_name('Concrete Jungle')
ScenarioInfo.set_map_description([[
Extensive underground mining has resulted in brittle soil.
New regulations requires that heavy objects are placed
on top of proper materials, to support the ground!
]])
-- Tiers of tiles definition (tier 0 is default)
local tile_tiers = {
['stone-path'] = 1,
['concrete'] = 2,
['refined-concrete'] = 3,
['hazard-concrete-right'] = 2,
['hazard-concrete-left'] = 2,
['refined-hazard-concrete-right'] = 3,
['refined-hazard-concrete-left'] = 3
}
local tier_0 = {
'transport-belt',
'fast-transport-belt',
'express-transport-belt',
'underground-belt',
'fast-underground-belt',
'express-underground-belt',
'small-electric-pole',
'burner-mining-drill',
'pumpjack',
'car',
'tank',
'pipe',
'pipe-to-ground',
'offshore-pump',
'locomotive',
'cargo-wagon',
'fluid-wagon',
'artillery-wagon'
}
--- Items explicitly allowed everywhere (tier 0 and up)
--- The RestrictEntities module auto skips all checks for these entities
--- They do not trigger set_keep_alive_callback or the on_pre_restricted_entity_destroyed event
RestrictEntities.add_allowed(tier_0)
-- Items only allowed on tiles of tier 2 or higher (tier 1 is the default)
local entity_tiers = {
-- Tier 2
['oil-refinery'] = 2,
['chemical-plant'] = 2,
['storage-tank'] = 2,
['rail'] = 2,
['straight-rail'] = 2,
['curved-rail'] = 2,
['train-stop'] = 2,
['solar-panel'] = 2,
['flamethrower-turret'] = 2,
['assembling-machine-2'] = 2,
['steel-furnace'] = 2,
['fast-inserter'] = 2,
['filter-inserter'] = 2,
['accumulator'] = 2,
['big-electric-pole'] = 2,
-- Tier 3
['rocket-silo'] = 3,
['nuclear-reactor'] = 3,
['centrifuge'] = 3,
['heat-exchanger'] = 3,
['heat-pipe'] = 3,
['steam-turbine'] = 3,
['artillery-turret'] = 3,
['roboport'] = 3,
['beacon'] = 3,
['assembling-machine-3'] = 3,
['electric-furnace'] = 3,
['substation'] = 3,
['laser-turret'] = 3,
['stack-inserter'] = 3,
['stack-filter-inserter'] = 3,
['logistic-chest-active-provider'] = 3,
['logistic-chest-passive-provider'] = 3,
['logistic-chest-buffer'] = 3,
['logistic-chest-storage'] = 3,
['logistic-chest-requester'] = 3
}
--Creates rich text icons of the tiered entities
local tier_0_items = ''
local tier_0_counter = 0
for _, v in pairs(tier_0) do
tier_0_items = tier_0_items .. ' [entity=' .. v .. ']'
tier_0_counter = tier_0_counter + 1
if tier_0_counter > 10 then
tier_0_counter = 0
tier_0_items = tier_0_items .. '\n'
end
end
local tier_2_items = ''
local tier_3_items = ''
local tier_2_counter = 0
local tier_3_counter = 0
for k, v in pairs(entity_tiers) do
if not (k == 'rail') then
if (v == 3) then
tier_3_items = tier_3_items .. ' [entity=' .. k .. ']'
tier_3_counter = tier_3_counter + 1
elseif (v == 2) then
tier_2_items = tier_2_items .. ' [entity=' .. k .. ']'
tier_2_counter = tier_2_counter + 1
end
if tier_3_counter > 14 then
tier_3_counter = 0
tier_3_items = tier_3_items .. '\n'
elseif tier_2_counter > 14 then
tier_2_counter = 0
tier_2_items = tier_2_items .. '\n'
end
end
end
local tile_tiers_entities = '[font=default-bold]You may only build the factory on:[/font]\n'
local tile_tiers_entities_counter = 0
for k, _ in pairs(tile_tiers) do
tile_tiers_entities = tile_tiers_entities .. ' [tile=' .. k .. '] ' .. k
tile_tiers_entities_counter = tile_tiers_entities_counter + 1
if tile_tiers_entities_counter == 3 or tile_tiers_entities_counter == 5 then
--tile_tiers_entities_counter = 0
tile_tiers_entities = tile_tiers_entities .. '\n'
end
end
ScenarioInfo.add_map_extra_info(
tile_tiers_entities ..
[[
[font=default-bold]Exceptions:[/font]
]] ..
tier_0_items ..
[[
Stone bricks provide ground support for most buildings/entities,
but some require better ground support!
[font=default-bold]Ground support minimum concrete:[/font]
]] ..
tier_2_items .. [[
[font=default-bold]Ground support minimum refined concrete:[/font]
]] .. tier_3_items .. [[
Due to security measures you can not remove ground support nor downgrade it!
]]
)
RestrictEntities.set_tile_bp()
RestrictEntities.enable_spill()
--- The logic for checking that there are the correct ground support under the entity's position
RestrictEntities.set_keep_alive_callback(
Token.register(
function(entity)
if not (entity and entity.valid) then
return false
end
local get_tile = entity.surface.get_tile
local area = entity.bounding_box
local left_top = area.left_top
local right_bottom = area.right_bottom
local name = entity.name
if name == 'entity-ghost' then
name = entity.ghost_name
end
local entity_tier = entity_tiers[name] or 1
for x = floor(left_top.x), floor(right_bottom.x) do
for y = floor(left_top.y), floor(right_bottom.y) do
local tile_name = get_tile(x, y).name
local tile_tier = tile_tiers[tile_name] or 0
if entity_tier > tile_tier then
return false
end
end
end
return true
end
)
)
--- Anti griefing
local anti_grief_tries = 3 -- Change this number to change how many 'shots' a player has got
local forgiveness_time = 432000 -- Time before previous offences are forgiven, in ticks (60 ticks/sec)
local anti_grief_kick_tries = math.ceil(anti_grief_tries / 2) -- Tries before kick warning
RestrictEntities.set_anti_grief_callback(
Token.register(
function(_, player)
Popup.player(player, [[
Look out!
You are trying to replace entities which have items inside!
This is causing the items to spill out on the ground.
Please be careful!
]], nil, nil, 'entity_placement_restriction_inventory_warning')
if not (Rank.equal_or_greater_than(player.name, Ranks.auto_trusted)) then
local player_stat = times_spilled[player.index]
local number_of_spilled = player_stat and player_stat.count or 0
local last_offence = player_stat and player_stat.tick or 0
local time_since_last_offence = game.tick - last_offence
if (last_offence > 0 and time_since_last_offence >= forgiveness_time) then
number_of_spilled = 0
end
if number_of_spilled >= anti_grief_tries then
Report.jail(player, nil)
player.print({'', '[color=yellow]', {'concrete_jungle.anti_grief_jail_reason'}, '[/color]'})
Report.report(nil, player, 'Spilling too many items on the ground')
times_spilled[player.index] = nil
return
elseif number_of_spilled == anti_grief_kick_tries then
game.kick_player(player, {'concrete_jungle.anti_grief_kick_reason'})
end
times_spilled[player.index] = {count = number_of_spilled + 1, tick = game.tick}
end
end
)
)
local function print_floating_text(player, entity, text, color)
color = color or Color.white
local surface = player.surface
local position = entity.position
return surface.create_entity {
name = 'tutorial-flying-text',
color = color,
text = text,
position = position,
render_player_index = player.index
}
end
--- Warning for players when their entities are destroyed (needs to be pre because of the stack)
local function on_destroy(event)
local p = game.get_player(event.player_index)
local stack = event.stack
local entity = event.created_entity
local name
if stack.valid_for_read then
name = stack.name
else
name = entity.name
end
if p and p.valid then
if not (name == 'blueprint' or name == 'blueprint-book') then
if name == 'entity-ghost' then
name = entity.ghost_name
end
local tier = {'item-name.stone-path'}
if (entity_tiers[name] == 2) then
tier = {'item-name.concrete'}
elseif (entity_tiers[name] == 3) then
tier = {'item-name.refined-concrete'}
end
local text = {'concrete_jungle.entity_not_enough_ground_support', '[item=' .. name .. ']', tier}
print_floating_text(p, entity, text)
else
p.print({'', '[color=yellow]', {'concrete_jungle.blueprint_not_enough_ground_support', {'', '[/color][color=red]', {'concrete_jungle.blueprint'}, '[/color][color=yellow]'}}, '[/color]'})
end
end
end
local function remove_tile_from_player(name, player)
if name == 'stone-path' then
name = 'stone-brick'
elseif name == 'hazard-concrete-left' or name == 'hazard-concrete-right' then
name = 'hazard-concrete'
elseif name == 'refined-hazard-concrete-left' or name == 'refined-hazard-concrete-right' then
name = 'refined-hazard-concrete'
end
player.remove_item({name = name})
end
local function player_mined_tile(event)
local player_index = event.player_index
local surface = game.surfaces[event.surface_index]
local oldTiles = event.tiles
local tiles = {}
local player = game.get_player(player_index)
player.clean_cursor()
for _, oldTile in pairs(oldTiles) do
local name = oldTile.old_tile.name
table.insert(tiles, {name = name, position = oldTile.position})
remove_tile_from_player(name, player)
end
surface.set_tiles(tiles, true)
end
local function marked_for_deconstruction(event)
local entity = event.entity
if entity.name == 'deconstructible-tile-proxy' then
if entity and entity.valid then
entity.destroy()
end
end
end
local function player_built_tile(event)
local newTile = event.tile
local tier = tile_tiers[newTile.name]
if (tier) then
local tiles = {}
local oldTiles = event.tiles
local index = event.player_index
local robot = event.robot
local player
if index then
player = game.get_player(index)
else
player = robot
end
local surface = game.surfaces[event.surface_index]
for _, oldTile in pairs(oldTiles) do
local name = oldTile.old_tile.name
local tile_tier = tile_tiers[name] or 0
if (tile_tier ~= 0 and tile_tier > tier) then
local newName = newTile.name
local position = oldTile.position
table.insert(tiles, {name = name, position = position})
remove_tile_from_player(name, player)
if newName == 'stone-path' then
newName = 'stone-brick'
elseif newName == 'hazard-concrete-left' or name == 'hazard-concrete-right' then
newName = 'hazard-concrete'
elseif newName == 'refined-hazard-concrete-left' or name == 'refined-hazard-concrete-right' then
newName = 'refined-hazard-concrete'
end
local item = {name = newName}
if player.can_insert(item) then
player.insert(item)
else
player.surface.spill_item_stack(position, item, true, player.force, false)
end
end
end
surface.set_tiles(tiles, true)
end
end
local first_time =
Token.register(
function(params)
local p = game.get_player(params.event.player_index)
Popup.player(
p,
{
'',
'[color=yellow]',
{'concrete_jungle.welcome_popup_player_name', p.name},
'[/color]\n\n',
{'concrete_jungle.welcome_popup_line_1'},
'\n\n',
{'concrete_jungle.welcome_popup_line_2'},
'\n\n',
{'concrete_jungle.welcome_popup_line_3', '[color=red]Map Info[/color]', '[color=red]Redmew Info[/color]', '[virtual-signal=signal-info]'}
},
{'concrete_jungle.welcome_popup_title'},
nil,
'concrete_jungle_intro'
)
end
)
Event.add(RestrictEntities.events.on_pre_restricted_entity_destroyed, on_destroy)
Event.add(defines.events.on_player_mined_tile, player_mined_tile)
Event.add(defines.events.on_marked_for_deconstruction, marked_for_deconstruction)
Event.add(defines.events.on_player_built_tile, player_built_tile)
Event.add(defines.events.on_robot_built_tile, player_built_tile)
Event.add(
defines.events.on_player_created,
function(event)
Task.set_timeout_in_ticks(900, first_time, {event = event})
end
)
Event.on_init(on_init)
--- Creating the starting circle (Map_gen)
local circle = b.circle(6)
local square = b.rectangle(3, 3)
local concrete_square = b.change_tile(square, true, 'hazard-concrete-left')
local stone_circle = b.change_tile(circle, true, 'stone-path')
stone_circle = b.if_else(concrete_square, stone_circle)
local water_circle = b.circle(250)
local land_circle = b.circle(200)
water_circle = b.subtract(water_circle, land_circle)
local cross = b.add(b.line_x(4), b.line_y(4))
cross = b.change_tile(cross, true, 'landfill')
cross = b.subtract(cross, b.invert(water_circle))
water_circle = b.change_tile(water_circle, true, 'water')
water_circle = b.fish(water_circle, 0.0025)
local map = b.if_else(water_circle, b.full_shape)
map = b.if_else(cross, map)
map = b.if_else(stone_circle, map)
return map

View File

@ -2,6 +2,7 @@ local Event = require 'utils.event'
local Global = require 'utils.global' local Global = require 'utils.global'
local RestrictEntities = require 'map_gen.shared.entity_placement_restriction' local RestrictEntities = require 'map_gen.shared.entity_placement_restriction'
local Popup = require 'features.gui.popup' local Popup = require 'features.gui.popup'
local Token = require 'utils.token'
local floor = math.floor local floor = math.floor
@ -37,20 +38,21 @@ local function all_on_landfill(entity)
end end
RestrictEntities.set_keep_alive_callback( RestrictEntities.set_keep_alive_callback(
function(entity) Token.register(
local name = entity.name function(entity)
if name == 'entity-ghost' then local name = entity.name
name = entity.ghost_name if name == 'entity-ghost' then
end name = entity.ghost_name
end
if not rail_entities[name] then if not rail_entities[name] then
return true return true
end end
return all_on_landfill(entity) return all_on_landfill(entity)
end end
)
) )
-- On first time player places rail entity on invalid tile, show popup explaining the rail mechanic. -- On first time player places rail entity on invalid tile, show popup explaining the rail mechanic.
local function restricted_entity_destroyed(event) local function restricted_entity_destroyed(event)
local p = event.player local p = event.player
@ -74,10 +76,7 @@ local function player_joined_game(event)
return return
end end
player.print( player.print("Welcome to RedMew's Rail Grids Map. Rails can only be built on green tiles.", {r = 0, g = 1, b = 0, a = 1})
"Welcome to RedMew's Rail Grids Map. Rails can only be built on green tiles.",
{r = 0, g = 1, b = 0, a = 1}
)
end end
Event.add(RestrictEntities.events.on_restricted_entity_destroyed, restricted_entity_destroyed) Event.add(RestrictEntities.events.on_restricted_entity_destroyed, restricted_entity_destroyed)

View File

@ -1,6 +1,7 @@
-- This module prevents all but the allowed items from being built on top of resources -- This module prevents all but the allowed items from being built on top of resources
local RestrictEntities = require 'map_gen.shared.entity_placement_restriction' local RestrictEntities = require 'map_gen.shared.entity_placement_restriction'
local Event = require 'utils.event' local Event = require 'utils.event'
local Token = require 'utils.token'
--- Items explicitly allowed on ores --- Items explicitly allowed on ores
RestrictEntities.add_allowed( RestrictEntities.add_allowed(
@ -25,18 +26,20 @@ RestrictEntities.add_allowed(
--- The logic for checking that there are resources under the entity's position --- The logic for checking that there are resources under the entity's position
RestrictEntities.set_keep_alive_callback( RestrictEntities.set_keep_alive_callback(
function(entity) Token.register(
-- Some entities have a bounding_box area of zero, eg robots. function(entity)
local area = entity.bounding_box -- Some entities have a bounding_box area of zero, eg robots.
local left_top, right_bottom = area.left_top, area.right_bottom local area = entity.bounding_box
if left_top.x == right_bottom.x and left_top.y == right_bottom.y then local left_top, right_bottom = area.left_top, area.right_bottom
return true if left_top.x == right_bottom.x and left_top.y == right_bottom.y then
return true
end
local count = entity.surface.count_entities_filtered {area = area, type = 'resource', limit = 1}
if count == 0 then
return true
end
end end
local count = entity.surface.count_entities_filtered {area = area, type = 'resource', limit = 1} )
if count == 0 then
return true
end
end
) )
--- Warning for players when their entities are destroyed --- Warning for players when their entities are destroyed

View File

@ -9,6 +9,8 @@
This means you can use any custom logic you want to determine whether an entity should be destroyed or not. This means you can use any custom logic you want to determine whether an entity should be destroyed or not.
The callback function is supplied a valid LuaEntity as an argument. The callback function is supplied a valid LuaEntity as an argument.
A return of true indicates the entity should be kept alive, while false or nil indicate it should be destroyed. A return of true indicates the entity should be kept alive, while false or nil indicate it should be destroyed.
This function must be a registered with the Token module and the keep_alive_callback function will take the Token-id as parameter
This is to prevent upvalue errors
Refunds for items that were placed can be toggled on or off via the enable and disable_refund functions Refunds for items that were placed can be toggled on or off via the enable and disable_refund functions
@ -24,16 +26,18 @@
-- The function provided does nothing but return nil -- The function provided does nothing but return nil
-- every entity will be destroyed except those on the allowed list -- every entity will be destroyed except those on the allowed list
RestrictEntities.add_allowed({'transport-belt'}) RestrictEntities.add_allowed({'transport-belt'})
RestrictEntities.set_keep_alive_callback(function() end) RestrictEntities.set_keep_alive_callback(Token.register(function() end))
-- Danger ores (a lot of important code omitted for the sake of a brief example) -- Danger ores (a lot of important code omitted for the sake of a brief example)
RestrictEntities.add_allowed({belts, power_poles, mining_drills, 'pumpjack'}) RestrictEntities.add_allowed({belts, power_poles, mining_drills, 'pumpjack'})
RestrictEntities.set_keep_alive_callback( RestrictEntities.set_keep_alive_callback(
function(entity) Token.register(
if entity.surface.count_entities_filtered {area = entity.bounding_box, type = 'resource', limit = 1} == 0 then function(entity)
return true if entity.surface.count_entities_filtered {area = entity.bounding_box, type = 'resource', limit = 1} == 0 then
return true
end
end end
end )
) )
]] ]]
local Event = require 'utils.event' local Event = require 'utils.event'
@ -80,7 +84,10 @@ local banned_entities = {}
local primitives = { local primitives = {
event = nil, -- if the event is registered or not event = nil, -- if the event is registered or not
refund = true, -- if we issue a refund or not refund = true, -- if we issue a refund or not
keep_alive_callback = nil -- the function to process entities through prevent_tile_bp = false, -- prevents players from placing blueprints with tiles
spill = false, -- spills items from entities with inventories to prevent destroying items when upgrading
keep_alive_callback = nil, -- the token registered function to process entities through
anti_grief_callback = nil -- the token registered function to process anti griefing through
} }
Global.register( Global.register(
@ -98,6 +105,72 @@ Global.register(
-- Local functions -- Local functions
--- Spill items stacks
-- @param entity <LuaEntity> the entity from which the items should be spilled
-- @param item <ItemStackSpecification> the item stack that should be spilled
local function spill_item_stack(entity, item)
entity.surface.spill_item_stack(entity.position, item, true, entity.force, false)
end
local Task = require 'utils.task'
--- Cleans the players cursor to prevent from spam replacing entities with inventory
-- Somehow required to have a 1 tick delay before cleaning the players cursor
local delay_clean_cursor =
Token.register(
function(param)
param.player.clean_cursor()
end
)
--- Checks if entity has an inventory with items inside, and spills them on the ground
local function entities_with_inventory(entity, player)
if primitives.spill and entity.has_items_inside() then
Task.set_timeout_in_ticks(1, delay_clean_cursor, {player = player})
local type = entity.type
if type == 'container' then
for item, count in pairs(entity.get_inventory(defines.inventory.chest).get_contents()) do
spill_item_stack(entity, {name = item, count = count})
end
elseif type == 'logistic-container' then
entity.surface.create_entity {name = 'steel-chest', position = entity.position, direction = entity.direction, force = entity.force, fast_replace = true, spill = false}
if player and player.valid and primitives.refund then -- refunding materials required to make a logistic container minus the "free" steel-chest generated above
player.insert({name = 'electronic-circuit', count = 3})
player.insert({name = 'advanced-circuit', count = 1})
end
return true
elseif type == 'furnace' then
for item, count in pairs(entity.get_inventory(defines.inventory.fuel).get_contents()) do
spill_item_stack(entity, {name = item, count = count})
end
for item, count in pairs(entity.get_inventory(defines.inventory.furnace_result).get_contents()) do
spill_item_stack(entity, {name = item, count = count})
end
for item, count in pairs(entity.get_inventory(defines.inventory.furnace_source).get_contents()) do
spill_item_stack(entity, {name = item, count = count})
end
elseif type == 'assembling-machine' then
for item, count in pairs(entity.get_inventory(defines.inventory.assembling_machine_input).get_contents()) do
spill_item_stack(entity, {name = item, count = count})
end
for item, count in pairs(entity.get_inventory(defines.inventory.assembling_machine_modules).get_contents()) do
spill_item_stack(entity, {name = item, count = count})
end
for item, count in pairs(entity.get_inventory(defines.inventory.assembling_machine_output).get_contents()) do
spill_item_stack(entity, {name = item, count = count})
end
elseif type == 'ammo-turret' then
for item, count in pairs(entity.get_inventory(defines.inventory.turret_ammo).get_contents()) do
player.insert({name = item, count = count})
end
return -- Prevents triggering when autofill is enabled
end
Token.get(primitives.anti_grief_callback)(entity, player)
end
return false
end
--- Token for the on_built event callback, checks if an entity should be destroyed. --- Token for the on_built event callback, checks if an entity should be destroyed.
local on_built_token = local on_built_token =
Token.register( Token.register(
@ -109,6 +182,9 @@ local on_built_token =
local name = entity.name local name = entity.name
if name == 'tile-ghost' then if name == 'tile-ghost' then
if primitives.prevent_tile_bp and entity.ghost_name ~= 'landfill' then
entity.destroy()
end
return return
end end
@ -132,7 +208,7 @@ local on_built_token =
-- destroy in these cases: -- destroy in these cases:
-- all banned ents -- all banned ents
-- not banned and callback function and not saved by callback -- not banned and callback function and not saved by callback
if not banned_entities[name] and (not keep_alive_callback or keep_alive_callback(entity)) then if not banned_entities[name] and (not keep_alive_callback or Token.get(keep_alive_callback)(entity)) then
return return
end end
@ -149,14 +225,20 @@ local on_built_token =
} }
) )
local player = game.get_player(index)
-- Need to revalidate the entity since we sent it to the raised event -- Need to revalidate the entity since we sent it to the raised event
if entity.valid then if entity.valid then
entity.destroy() -- Checking if the entity has an inventory and spills the content on the ground to prevent destroying those too
if entities_with_inventory(entity, player) then
ghost = true -- Cheating to prevent refunds
else
entity.destroy()
end
end end
-- Check if we issue a refund: make sure refund is enabled, make sure we're not refunding a ghost, -- Check if we issue a refund: make sure refund is enabled, make sure we're not refunding a ghost,
-- and revalidate the stack since we sent it to the raised event -- and revalidate the stack since we sent it to the raised event
local player = game.get_player(index)
local item_returned local item_returned
if player and player.valid and primitives.refund and not ghost and stack.valid then if player and player.valid and primitives.refund and not ghost and stack.valid then
player.insert(stack) player.insert(stack)
@ -201,8 +283,8 @@ end
-- logic on what entities should and should not be destroyed. -- logic on what entities should and should not be destroyed.
-- @param keep_alive_callback <function> -- @param keep_alive_callback <function>
function Public.set_keep_alive_callback(keep_alive_callback) function Public.set_keep_alive_callback(keep_alive_callback)
if type(keep_alive_callback) ~= 'function' then if type(keep_alive_callback) ~= 'number' then
error('Sending a non-function') error('Sending a non-token function')
end end
primitives.keep_alive_callback = keep_alive_callback primitives.keep_alive_callback = keep_alive_callback
check_event_status() check_event_status()
@ -214,6 +296,21 @@ function Public.remove_keep_alive_callback()
check_event_status() check_event_status()
end end
--- Sets the anti_grief_callback function. This function is used to provide
-- logic on what entities should and should not be destroyed.
-- @param anti_grief_callback <function>
function Public.set_anti_grief_callback(anti_grief_callback)
if type(anti_grief_callback) ~= 'number' then
error('Sending a non-token function')
end
primitives.anti_grief_callback = anti_grief_callback
end
--- Removes the anti_grief_callback function
function Public.remove_anti_grief_callback()
primitives.anti_grief_callback = nil
end
--- Adds to the list of allowed entities --- Adds to the list of allowed entities
-- @param ents <table> array of string entity names -- @param ents <table> array of string entity names
function Public.add_allowed(ents) function Public.add_allowed(ents)
@ -272,4 +369,24 @@ function Public.set_refund()
primitives.refund = false primitives.refund = false
end end
--- Enables the ability to blueprint tiles (Landfill always enabled)
function Public.enable_tile_bp()
primitives.prevent_tile_bp = false
end
--- Disables the ability to blueprint tiles (Landfill always enabled)
function Public.set_tile_bp()
primitives.prevent_tile_bp = true
end
--- Enables the spill function
function Public.enable_spill()
primitives.spill = true
end
--- Disables the spill function
function Public.set_spill()
primitives.spill = false
end
return Public return Public