1
0
mirror of https://github.com/Refactorio/RedMew.git synced 2024-12-14 10:13:13 +02:00

Diggy initial commit

This commit is contained in:
Lynn 2018-09-08 18:29:27 +02:00 committed by Maik Wild
parent a8e883b8ec
commit 96602aa0f0
13 changed files with 822 additions and 0 deletions

62
Diggy/Config.lua Normal file
View File

@ -0,0 +1,62 @@
-- dependencies
-- this
local Config = {
-- enable debug mode, shows extra messages
debug = true,
-- allow cheats. Example: by default the player will have 1000 mining speed
cheats = true,
-- initial starting position size, values higher than 30 might break
starting_size = 7,
-- the daytime value used for cave lighting
daytime = 0.5,
-- a list of features to register and enable
-- to disable a feature, change the flag
features = {
StartingZone = {
enabled = true,
register = require 'Diggy.Feature.StartingZone'.register,
initialize = require 'Diggy.Feature.StartingZone'.initialize,
},
SetupPlayer = {
enabled = true,
register = require 'Diggy.Feature.SetupPlayer'.register,
initialize = require 'Diggy.Feature.SetupPlayer'.initialize,
},
DiggyHole = {
enabled = true,
register = require 'Diggy.Feature.DiggyHole'.register,
initialize = require 'Diggy.Feature.DiggyHole'.initialize,
},
DiggyCaveCollapse = {
enabled = true,
register = require 'Diggy.Feature.DiggyCaveCollapse'.register,
initialize = require 'Diggy.Feature.DiggyCaveCollapse'.initialize,
out_of_map_support_beam_range = 14,
support_beam_entities = {
{name = "stone-wall", range = 10},
{name = "stone-brick", range = 1},
{name = "concrete", range = 2},
{name = "hazard-concrete", range = 2},
{name = "refined-concrete", range = 3},
{name = "refined-hazard-concrete", range = 3},
},
},
RefreshMap = {
enabled = true,
register = require 'Diggy.Feature.RefreshMap'.register,
initialize = require 'Diggy.Feature.RefreshMap'.initialize,
},
SimpleRoomGenerator = {
enabled = true,
register = require 'Diggy.Feature.SimpleRoomGenerator'.register,
initialize = require 'Diggy.Feature.SimpleRoomGenerator'.initialize,
},
},
}
return Config

48
Diggy/Debug.lua Normal file
View File

@ -0,0 +1,48 @@
-- dependencies
-- this
local Debug = {}
-- private state
local debug = false
local cheats = false
function Debug.enable_debug()
debug = true
end
function Debug.disable_debug()
debug = false
end
function Debug.enable_cheats()
cheats = true
end
function Debug.disable_cheats()
cheats = true
end
--[[--
Shows the given message if _DEBUG == true.
@param message string
]]
function Debug.print(message)
if (debug) then
game.print(message)
end
end
--[[--
Executes the given callback if _DIGGY_CHEATS == true.
@param callback function
]]
function Debug.cheat(callback)
if (cheats) then
callback()
end
end
return Debug

View File

@ -0,0 +1,149 @@
--[[-- info
Provides the ability to collapse caves when digging.
]]
-- dependencies
require 'utils.list_utils'
local Event = require 'utils.event'
local Template = require 'Diggy.Template'
local Mask = require 'Diggy.Mask'
local PressureMap = require 'Diggy.PressureMap'
local DiggyHole = require 'Diggy.Feature.DiggyHole'
-- this
local DiggyCaveCollapse = {}
--[[--
@param surface LuaSurface
@param position Position with x and y
@param support_beam_range the supported range from this position
@param support_removed boolean true if the location was removed
]]
local function update_pressure_map(surface, position, support_beam_range, support_removed)
Mask.circle(position.x, position.y, support_beam_range, function(x, y, tile_distance_to_center)
local fraction = 1
local modifier = -1
if (support_removed) then
modifier = 1
end
if (0 ~= tile_distance_to_center) then
fraction = tile_distance_to_center / support_beam_range
end
PressureMap.add(surface, {x = x, y = y}, fraction * modifier)
end)
if (support_removed) then
PressureMap.process_maxed_values_buffer(surface, function ()
require 'Diggy.Debug'.print('Cave collapsed at: ' .. position.x .. ',' .. position.y)
end)
end
end
--[[--
@param config Table {@see Diggy.Config}.
@param entity LuaEntity
@return number the range this entity supports the cave
]]
local function get_entity_support_range(config, entity)
for _, support_entity in pairs(config.features.DiggyCaveCollapse.support_beam_entities) do
if (support_entity.name == entity.name) then
return entity.range
end
end
return 0
end
--[[--
Registers all event handlers.]
@param config Table {@see Diggy.Config}.
]]
function DiggyCaveCollapse.register(config)
Event.add(defines.events.on_robot_built_entity, function(event)
local range = get_entity_support_range(config, event.created_entity)
if (0 == range) then
return
end
update_pressure_map(event.created_entity.surface, {
x = event.created_entity.position.x,
y = event.created_entity.position.y,
}, range, false)
end)
Event.add(defines.events.on_built_entity, function(event)
local range = get_entity_support_range(config, event.created_entity)
if (0 == range) then
return
end
update_pressure_map(event.created_entity.surface, {
x = event.created_entity.position.x,
y = event.created_entity.position.y,
}, range, false)
end)
Event.add(Template.events.on_entity_placed, function(event)
local range = get_entity_support_range(config, event.entity)
if (0 == range) then
return
end
update_pressure_map(event.entity.surface, {
x = event.entity.position.x,
y = event.entity.position.y,
}, range, false)
end)
Event.add(DiggyHole.events.on_out_of_map_removed, function(event)
update_pressure_map(event.surface, {
x = event.position.x,
y = event.position.y,
}, config.features.DiggyCaveCollapse.out_of_map_support_beam_range, false)
end)
Event.add(defines.events.on_entity_died, function(event)
local range = get_entity_support_range(config, event.entity)
if (0 == range) then
return
end
update_pressure_map(event.surface, {
x = event.position.x,
y = event.position.y,
}, range, true)
end)
Event.add(defines.events.on_player_mined_entity, function(event)
local range = get_entity_support_range(config, event.entity)
if (0 == range) then
return
end
update_pressure_map(event.surface, {
x = event.position.x,
y = event.position.y,
}, range, true)
end)
end
--[[--
Initializes the Feature.
@param config Table {@see Diggy.Config}.
]]
function DiggyCaveCollapse.initialize(config)
end
return DiggyCaveCollapse

View File

@ -0,0 +1,87 @@
--[[-- info
Provides the ability to "mine" through out-of-map tiles by destroying or
mining rocks next to it.
]]
-- dependencies
local Event = require 'utils.event'
local Scanner = require 'Diggy.Scanner'
local Template = require 'Diggy.Template'
-- this
local DiggyHole = {}
-- list of all possible events to subscribe to
DiggyHole.events = {
--[[--
Triggers when an 'out-of-map' tile is replaced by a rock in
DiggyHole.diggy_hole.
Can be fired for each position replaced. It's recommended to avoid
performance heavy listeners. Off-load them into a queue processed on
ticks.
]]
on_out_of_map_removed = script.generate_event_name(),
}
--[[--
Triggers a diggy diggy hole for a given sand-rock-big.
Will return true even if the tile behind it is immune.
@param entity LuaEntity
@param temporary_inventory LuaInventory
]]
local function diggy_hole(entity, temporary_inventory)
if (entity.name ~= 'sand-rock-big') then
return
end
-- prevent the mined ore from reaching the inventory
if (nil ~= temporary_inventory) then
temporary_inventory.clear()
end
local tiles = {}
local rocks = {}
local out_of_map_found = Scanner.scan_around_position(entity.surface, entity.position, 'out-of-map');
for _, position in pairs(out_of_map_found) do
table.insert(tiles, {name = 'dirt-' .. math.random(1, 7), position = {position.x, position.y}})
table.insert(rocks, {name = 'sand-rock-big', position = {position.x, position.y}})
end
Template.insert(entity.surface, tiles, rocks)
for _, position in pairs(out_of_map_found) do
script.raise_event(DiggyHole.events.on_out_of_map_removed, {
surface = entity.surface,
position = {x = position.x, y = position.y}
})
end
end
--[[--
Registers all event handlers.
]]
function DiggyHole.register(config)
Event.add(defines.events.on_entity_died, function (event)
diggy_hole(event.entity)
end)
Event.add(defines.events.on_player_mined_entity, function (event)
diggy_hole(event.entity, event.buffer)
end)
end
--[[--
Initializes the Feature.
@param config Table {@see Diggy.Config}.
]]
function DiggyHole.initialize(config)
end
return DiggyHole

View File

@ -0,0 +1,48 @@
--[[-- info
Provides the ability to refresh the map and generate darkness.
]]
-- dependencies
local Event = require 'utils.event'
local Template = require 'Diggy.Template'
-- this
local RefreshMap = {}
--[[--
Registers all event handlers.
]]
function RefreshMap.register(config)
Event.add(defines.events.on_chunk_generated, function (event)
local tiles = {}
for x = 0, 31, 1 do
for y = 0, 31, 1 do
local target_x = event.area.left_top.x + x
local target_y = event.area.left_top.y + y
local tile = 'out-of-map'
if (target_x < 1 and target_y < 1 and target_x > -2 and target_y > -2) then
tile = 'lab-dark-1'
end
table.insert(tiles, {
name = tile,
position = {target_x, target_y}
})
end
end
Template.insert(event.surface, tiles)
end)
end
--[[--
Initializes the Feature.
@param config Table {@see Diggy.Config}.
]]
function RefreshMap.initialize(config)
end
return RefreshMap

View File

@ -0,0 +1,33 @@
--[[-- info
Provides the ability to setup a player when first joined.
]]
-- dependencies
local Event = require 'utils.event'
local Debug = require 'Diggy.Debug'
-- this
local SetupPlayer = {}
--[[--
Registers all event handlers.
]]
function SetupPlayer.register(config)
Event.add(defines.events.on_player_created, function (event)
Debug.cheat(function()
local player =game.players[event.player_index]
player.force.manual_mining_speed_modifier = 1000
end)
end)
end
--[[--
Initializes the Feature.
@param config Table {@see Diggy.Config}.
]]
function SetupPlayer.initialize(config)
end
return SetupPlayer

View File

@ -0,0 +1,26 @@
--[[-- info
Provides the ability to make a simple room with contents
]]
-- dependencies
-- this
local SimpleRoomGenerator = {}
--[[--
Registers all event handlers.
]]
function SimpleRoomGenerator.register(config)
end
--[[--
Initializes the Feature.
@param config Table {@see Diggy.Config}.
]]
function SimpleRoomGenerator.initialize(config)
end
return SimpleRoomGenerator

View File

@ -0,0 +1,59 @@
--[[-- info
Provides the ability to create a pre-configured starting zone.
]]
-- dependencies
local Event = require 'utils.event'
local Token = require 'utils.global_token'
local Mask = require 'Diggy.Mask'
local Template = require 'Diggy.Template'
-- this
local StartingZone = {}
--[[--
Registers all event handlers.
]]
function StartingZone.register(config)
local callback_token
local function on_chunk_generated(event)
if (4 ~= #event.surface.find_tiles_filtered({{-1, -1}, {0, 0}, name='lab-dark-1', limit = 4})) then
return
end
local tiles = {}
local rocks = {}
Mask.circle(0, 0, config.starting_size, function(x, y, tile_distance_to_center)
table.insert(tiles, {name = 'dirt-' .. math.random(1, 7), position = {x, y}})
if (tile_distance_to_center > config.starting_size - 2) then
table.insert(rocks, {name = 'sand-rock-big', position = {x, y}})
end
end)
Template.insert(event.surface, tiles, rocks)
Event.remove_removable(defines.events.on_chunk_generated, callback_token)
end
callback_token = Token.register(on_chunk_generated)
Event.add_removable(defines.events.on_chunk_generated, callback_token)
end
--[[--
Initializes the Feature.
@param config Table {@see Diggy.Config}.
]]
function StartingZone.initialize(config)
local surface = game.surfaces.nauvis
surface.daytime = config.daytime
surface.freeze_daytime = 1
end
return StartingZone

24
Diggy/Mask.lua Normal file
View File

@ -0,0 +1,24 @@
-- this
local Mask = {}
--[[--
Masks in the shape of a circle.
@param x_start number, center point
@param y_start number, center point
@param diameter number size of the circle
@param callback function to execute on each tile within the circle callback(x, y, tile_distance_to_center, diameter)
]]
function Mask.circle(x_start, y_start, diameter, callback)
for x = (diameter * -1), diameter, 1 do
for y = (diameter * -1), diameter, 1 do
local tile_distance_to_center = math.floor(math.sqrt(x^2 + y^2))
if (tile_distance_to_center < diameter) then
callback(x + x_start, y + y_start, tile_distance_to_center, diameter)
end
end
end
end
return Mask

115
Diggy/PressureMap.lua Normal file
View File

@ -0,0 +1,115 @@
-- dependencies
-- this
local PressureMap = {}
-- private state
local pressure_map_storage = {}
--[[--
Adds a fraction to a given location on the pressure_map. Returns the new
fraction value of that position.
@param pressure_map Table of {@see get_pressure_map}
@param position Table with x and y
@param number fraction
@return number sum of old fraction + new fraction
]]
local function add_fraction(pressure_map, position, fraction)
local map
if position.x >= 0 then
if position.y >= 0 then
map = pressure_map.quadrant1
else
map = pressure_map.quadrant4
end
else
if position.y >= 0 then
map = pressure_map.quadrant2
else
map = pressure_map.quadrant3
end
end
if (not map[position.x]) then
map[position.x] = {[position.y] = fraction}
return fraction
end
if (not map[position.x][position.y]) then
map[position.x][position.y] = fraction
return fraction
end
local value = map[position.x][position.y] + fraction
map[position.x][position.y] = value
return value
end
--[[--
Creates a new pressure map if it doesn't exist yet and returns it.
@param surface LuaSurface
@return Table with maxed_values_buffer, quadrant1, quadrant2, quadrant3 and quadrant4
]]
local function get_pressure_map(surface)
if (nil == pressure_map_storage[surface.name]) then
pressure_map_storage[surface.name] = {
-- contains all coordinates that are at max pressure until cleared.
maxed_values_buffer = {},
-- map with coordinates, stored as [x][y] = fraction.
quadrant1 = {},
quadrant2 = {},
quadrant3 = {},
quadrant4 = {},
}
end
return pressure_map_storage[surface.name]
end
function PressureMap.process_maxed_values_buffer(surface, callback)
if ('table' ~= type(surface) or nil == surface.name) then
error('PressureMap.process_maxed_values_buffer argument #1 expects a LuaSurface, ' .. type(surface) .. ' given.')
end
if ('function' ~= type(callback)) then
error('PressureMap.process_maxed_values_buffer argument #2 expects a callback function, ' .. type(callback) .. ' given.')
end
local buffer = get_pressure_map(surface).maxed_values_buffer
for _, position in pairs(buffer) do
callback({x = position.x, y = position.y})
end
buffer = {}
end
--[[--
@param surface LuaSurface
@param position Position with x and y
@param number fraction to add to the given position on the surface increase or decreasing pressure
]]
function PressureMap.add(surface, position, fraction)
if ('table' ~= type(surface) or nil == surface.name) then
error('PressureMap.set argument #1 expects a LuaSurface, ' .. type(surface) .. ' given.')
end
if ('table' ~= type(position) or nil == position.x or nil == position.y) then
error('PressureMap.set argument #2 expects a position with x and y, ' .. type(surface) .. ' given.')
end
local pressure_map = get_pressure_map(surface)
fraction = add_fraction(pressure_map, position, fraction)
if (fraction >= 1 ) then
table.insert(pressure_map.maxed_values_buffer, position)
end
end
return PressureMap

40
Diggy/Scanner.lua Normal file
View File

@ -0,0 +1,40 @@
-- dependencies
-- this
local Scanner = {}
--[[--
returns a list with all direct positions that contain out-of-map.
@param surface LuaSurface
@param position Position
@param tile_search string name of the tile to search for
@return table with 0~4 directions of which have the tile searched for adjacent
]]
function Scanner.scan_around_position(surface, position, tile_search)
local out_of_map_found = {}
-- north
if (tile_search == surface.get_tile(position.x, position.y - 1).name) then
table.insert(out_of_map_found, {x = position.x, y = position.y - 1})
end
-- east
if (tile_search == surface.get_tile(position.x + 1, position.y).name) then
table.insert(out_of_map_found, {x = position.x + 1, y = position.y})
end
-- south
if (tile_search == surface.get_tile(position.x, position.y + 1).name) then
table.insert(out_of_map_found, {x = position.x, y = position.y + 1})
end
-- west
if (tile_search == surface.get_tile(position.x - 1, position.y).name) then
table.insert(out_of_map_found, {x = position.x - 1, y = position.y})
end
return out_of_map_found;
end
return Scanner

99
Diggy/Scenario.lua Normal file
View File

@ -0,0 +1,99 @@
-- dependencies
local Event = require 'utils.event'
local Config = require 'Diggy.Config'
local Debug = require 'Diggy.Debug'
require 'utils.list_utils'
require 'utils.utils'
-- this
local Scenario = {}
-- private state
local scenario_registered = false
local scenario_initialized = false
--[[--
Allows calling a callback for each enabled feature.
Signature: callback(feature_name, Table feature_data) from {@see Config.features}.
@param if_enabled function to be called if enabled
]]
local function each_enabled_feature(if_enabled)
local type = type(if_enabled)
if ('function' ~= type) then
error('each_enabled_feature expects callback to be a function, given type: ' .. type)
end
for current_name, feature_data in pairs(Config.features) do
if (nil == feature_data.enabled) then
error('Feature ' .. current_name .. ' did not define the enabled property.')
end
if (feature_data.enabled) then
if_enabled(current_name, feature_data)
end
end
end
--[[--
Register the events required to initialize the scenario.
]]
function Scenario.register(debug)
if scenario_registered then
error('Cannot register the scenario multiple times.')
return
end
-- using the on_player_created to initialize all the features
Event.add(defines.events.on_player_created, function (event)
if ('boolean' == type(debug)) then
Config.Debug = debug
end
if (Config.debug) then
Debug.enable_debug()
end
if (Config.cheats) then
Debug.enable_cheats()
end
Scenario.initialize(Config)
end)
each_enabled_feature(function(feature_name, feature_data)
if ('function' ~= type(feature_data.register)) then
error('Feature ' .. feature_name .. ' did not define a register function.')
end
feature_data.register(Config)
end)
scenario_registered = true
end
--[[--
Initializes the starting position.
@param config Table {@see Diggy.Config}.
]]
function Scenario.initialize(config)
if scenario_initialized then
return
end
each_enabled_feature(function(feature_name, feature_data)
if ('function' ~= type(feature_data.initialize)) then
error('Feature ' .. feature_name .. ' did not define an initialize function.')
end
feature_data.initialize(config)
end)
scenario_initialized = true
end
return Scenario

32
Diggy/Template.lua Normal file
View File

@ -0,0 +1,32 @@
-- this
local Template = {}
Template.events = {
on_entity_placed = script.generate_event_name()
}
--[[--
Inserts a batch of tiles and then entities.
@see LuaSurface.set_tiles
@see LuaSurface.entity
@param surface LuaSurface to put the tiles and entities on
@param tiles table of tiles as required by set_tiles
@param entities table of entities as required by create_entity
]]
function Template.insert(surface, tiles, entities)
if (nil == entities) then
entities = {}
end
surface.set_tiles(tiles)
for _, entity in pairs(entities) do
surface.create_entity(entity)
script.raise_event(Template.events.on_entity_placed, {entity = entity})
end
end
return Template