1
0
mirror of https://github.com/Refactorio/RedMew.git synced 2025-01-03 22:52:13 +02:00

Add player settings for corpse pings + tests.

This commit is contained in:
James Gillham 2020-11-13 20:06:01 +00:00
parent 86cbfac9a7
commit eb7b43cf1c
8 changed files with 441 additions and 119 deletions

View File

@ -3,6 +3,18 @@ local Global = require 'utils.global'
local Task = require 'utils.task'
local Token = require 'utils.token'
local Utils = require 'utils.core'
local Settings = require 'utils.redmew_settings'
local Public = {}
local ping_own_death_name = 'corpse_util.ping_own_death'
local ping_other_death_name = 'corpse_util.ping_other_death'
Public.ping_own_death_name = ping_own_death_name
Public.ping_other_death_name = ping_other_death_name
Settings.register(ping_own_death_name, Settings.types.boolean, true, 'corpse_util.ping_own_death')
Settings.register(ping_other_death_name, Settings.types.boolean, false, 'corpse_util.ping_other_death')
local player_corpses = {}
@ -49,13 +61,26 @@ local function player_died(event)
return
end
player.force.print({
'corpse_util.marked_tag',
player.name,
string.format('%.1f', position.x),
string.format('%.1f', position.y),
player.surface.name
})
if Settings.get(player_index, ping_own_death_name) then
player.print({
'corpse_util.own_corpse_location',
string.format('%.1f', position.x),
string.format('%.1f', position.y),
player.surface.name
})
end
for _, other_player in pairs(player.force.players) do
if other_player ~= player and Settings.get(other_player.index, ping_other_death_name) then
other_player.print({
'corpse_util.other_corpse_location',
player.name,
string.format('%.1f', position.x),
string.format('%.1f', position.y),
player.surface.name
})
end
end
player_corpses[player_index * 0x100000000 + tick] = tag
end
@ -144,3 +169,11 @@ Event.add(defines.events.on_player_died, player_died)
Event.add(defines.events.on_character_corpse_expired, corpse_expired)
Event.add(defines.events.on_pre_player_mined_item, mined_entity)
Event.add(defines.events.on_gui_opened, on_gui_opened)
function Public.clear()
table.clear_table(player_corpses)
end
Public._player_died = player_died
return Public

View File

@ -0,0 +1,235 @@
local Declare = require 'utils.test.declare'
local EventFactory = require 'utils.test.event_factory'
local Assert = require 'utils.test.assert'
local Helper = require 'utils.test.helper'
local Settings = require 'utils.redmew_settings'
local CorpseUtil = require 'features.corpse_util'
local function test_teardown(context)
context:add_teardown(CorpseUtil.clear)
end
local function declare_test(name, func)
local function test_func(context)
test_teardown(context)
func(context)
end
Declare.test(name, test_func)
end
Declare.module({'features', 'corpse_util'}, function()
local teardown
Declare.module_startup(function(context)
teardown = Helper.startup_test_surface(context)
-- wait for surface to be charted, needed before a tag can be created.
context:next(function()
local player = context.player
Helper.wait_for_chunk_to_be_charted(context, player.force, player.surface, {0, 0})
end)
end)
Declare.module_teardown(function()
teardown()
end)
local function change_settings_for_test(context, key, value)
local player_index = context.player.index
local current_value = Settings.get(player_index, key)
Settings.set(player_index, key, value)
context:add_teardown(function()
Settings.set(player_index, key, current_value)
end)
end
local function fake_death(player)
local surface = player.surface
local position = player.position
local entity = surface.create_entity {
name = 'character-corpse',
position = position,
player_index = player.index
}
if not entity or not entity.valid then
error('no corpse')
end
return EventFactory.on_player_died(player.index)
end
declare_test('ping player corpse location when died', function(context)
-- Arrange.
local player = context.player
local actual_text
Helper.modify_lua_object(context, player, 'print', function(text)
actual_text = text
end)
Helper.modify_lua_object(context, game, 'get_player', function()
return player
end)
local event = fake_death(player)
-- Act.
CorpseUtil._player_died(event)
-- Assert.
local expected = {'corpse_util.own_corpse_location', '0.0', '0.0', player.surface.name}
Assert.table_equal(expected, actual_text)
end)
declare_test('ping other player corpse location when other player died', function(context)
-- Arrange.
local player = context.player
local force = player.force
local actual_text
local second_player = {
index = 2,
valid = true,
name = 'second_player',
surface = player.surface,
force = force,
print = function()
end,
position = EventFactory.position({1, 1})
}
change_settings_for_test(context, CorpseUtil.ping_other_death_name, true)
Helper.modify_lua_object(context, game, 'get_player', function(index)
if index == player.index then
return player
end
if index == second_player.index then
return second_player
end
end)
Helper.modify_lua_object(context, force, 'players', {player, second_player})
Helper.modify_lua_object(context, player, 'print', function(text)
actual_text = text
end)
local event = fake_death(second_player)
-- Act.
CorpseUtil._player_died(event)
-- Assert.
local expected = {'corpse_util.other_corpse_location', second_player.name, '1.0', '1.0', player.surface.name}
Assert.table_equal(expected, actual_text)
end)
declare_test('do not ping player corpse location when died and setting disabled', function(context)
-- Arrange.
local player = context.player
change_settings_for_test(context, CorpseUtil.ping_own_death_name, false)
local actual_text
Helper.modify_lua_object(context, player, 'print', function(text)
actual_text = text
end)
Helper.modify_lua_object(context, game, 'get_player', function()
return player
end)
local event = fake_death(player)
-- Act.
CorpseUtil._player_died(event)
-- Assert.
Assert.is_nil(actual_text)
end)
declare_test('do not ping other player corpse location when other player died and settings disabled',
function(context)
-- Arrange.
local player = context.player
local force = player.force
local actual_text
local second_player = {
index = 2,
valid = true,
name = 'second_player',
surface = player.surface,
force = force,
print = function()
end,
position = EventFactory.position({1, 1})
}
change_settings_for_test(context, CorpseUtil.ping_other_death_name, false)
Helper.modify_lua_object(context, game, 'get_player', function(index)
if index == player.index then
return player
end
if index == second_player.index then
return second_player
end
end)
Helper.modify_lua_object(context, force, 'players', {player, second_player})
Helper.modify_lua_object(context, player, 'print', function(text)
actual_text = text
end)
local event = fake_death(second_player)
-- Act.
CorpseUtil._player_died(event)
-- Assert.
Assert.is_nil(actual_text)
end)
declare_test('do not ping other player corpse location for self', function(context)
-- Arrange.
local player = context.player
local force = player.force
local actual_text
change_settings_for_test(context, CorpseUtil.ping_own_death_name, false)
change_settings_for_test(context, CorpseUtil.ping_other_death_name, true)
Helper.modify_lua_object(context, game, 'get_player', function()
return player
end)
Helper.modify_lua_object(context, player, 'force', force)
Helper.modify_lua_object(context, force, 'players', {player})
Helper.modify_lua_object(context, player, 'print', function(text)
actual_text = text
end)
local event = fake_death(player)
-- Act.
CorpseUtil._player_died(event)
-- Assert.
Assert.is_nil(actual_text)
end)
end)

View File

@ -179,4 +179,7 @@ instructions=Select a brush tile to replace [item=refined-concrete] and [item=re
no_place_landfill=Coloured concrete can not be placed on landfill tiles.
[corpse_util]
marked_tag=__1__'s corpse has been marked on the map at [gps=__2__,__3__,__4__]
ping_own_death=Ping the location when you die.
ping_other_death=Ping the location when other players die.
own_corpse_location=[color=red][Corpse][/color] Your corpse is located at [gps=__1__,__2__,__3__]
other_corpse_location=[Color=red][Corpse][/Color] __1__'s corpse is located at [gps=__2__,__3__,__4__]

View File

@ -1,3 +1,4 @@
local table = require 'utils.table'
local error = error
local concat = table.concat
@ -25,6 +26,28 @@ function Public.equal(a, b, optional_message)
error(message, 2)
end
function Public.is_nil(value, optional_message)
if value == nil then
return
end
local message = {tostring(value), ' was not nil'}
if optional_message then
message[#message + 1] = ' - '
message[#message + 1] = optional_message
end
message = concat(message)
error(message, 2)
end
function Public.table_equal(a, b)
-- Todo write own table equal
if not table.equals(a, b) then
error('tables not equal', 2)
end
end
function Public.is_true(condition, optional_message)
if not condition then
error(optional_message or 'condition was not true', 2)

View File

@ -2,7 +2,7 @@ local Public = {}
Public.__index = Public
function Public.new(player)
return setmetatable({player = player, _steps = {}}, Public)
return setmetatable({player = player, _steps = {}, _teardowns = {}}, Public)
end
function Public.timeout(self, delay, func)
@ -15,4 +15,15 @@ function Public.next(self, func)
return self:timeout(1, func)
end
function Public.wait(self, delay)
return self:timeout(delay, function()
end)
end
function Public.add_teardown(self, func)
local teardowns = self._teardowns
teardowns[#teardowns + 1] = func
return self
end
return Public

View File

@ -57,18 +57,20 @@ function Public.on_player_deconstructed_area(player_index, surface, area, item)
end
function Public.do_player_deconstruct_area(cursor, player, area, optional_skip_fog_of_war)
cursor.deconstruct_area(
{
surface = player.surface,
force = player.force,
area = area,
by_player = player,
skip_fog_of_war = optional_skip_fog_of_war
}
)
cursor.deconstruct_area({
surface = player.surface,
force = player.force,
area = area,
by_player = player,
skip_fog_of_war = optional_skip_fog_of_war
})
local event = Public.on_player_deconstructed_area(player.index, player.surface, area, cursor.name)
Public.raise(event)
end
function Public.on_player_died(player_index)
return {name = defines.events.on_player_died, tick = game.tick, player_index = player_index, cause = nils}
end
return Public

View File

@ -4,12 +4,9 @@ local Public = {}
local surface_count = 0
Global.register(
{surface_count = surface_count},
function(tbl)
surface_count = tbl.surface_count
end
)
Global.register({surface_count = surface_count}, function(tbl)
surface_count = tbl.surface_count
end)
local function get_surface_name()
surface_count = surface_count + 1
@ -17,62 +14,21 @@ local function get_surface_name()
end
local autoplace_settings = {
tile = {
treat_missing_as_default = false,
settings = {
['grass-1'] = {frequency = 1, size = 1, richness = 1}
}
}
tile = {treat_missing_as_default = false, settings = {['grass-1'] = {frequency = 1, size = 1, richness = 1}}}
}
local autoplace_controls = {
trees = {
frequency = 1,
richness = 1,
size = 0
},
['enemy-base'] = {
frequency = 1,
richness = 1,
size = 0
},
coal = {
frequency = 1,
richness = 1,
size = 0
},
['copper-ore'] = {
frequency = 1,
richness = 1,
size = 0
},
['crude-oil'] = {
frequency = 1,
richness = 1,
size = 0
},
['iron-ore'] = {
frequency = 1,
richness = 1,
size = 0
},
stone = {
frequency = 1,
richness = 1,
size = 0
},
['uranium-ore'] = {
frequency = 1,
richness = 1,
size = 0
}
trees = {frequency = 1, richness = 1, size = 0},
['enemy-base'] = {frequency = 1, richness = 1, size = 0},
coal = {frequency = 1, richness = 1, size = 0},
['copper-ore'] = {frequency = 1, richness = 1, size = 0},
['crude-oil'] = {frequency = 1, richness = 1, size = 0},
['iron-ore'] = {frequency = 1, richness = 1, size = 0},
stone = {frequency = 1, richness = 1, size = 0},
['uranium-ore'] = {frequency = 1, richness = 1, size = 0}
}
local cliff_settings = {
cliff_elevation_0 = 1024,
cliff_elevation_interval = 10,
name = 'cliff'
}
local cliff_settings = {cliff_elevation_0 = 1024, cliff_elevation_interval = 10, name = 'cliff'}
function Public.startup_test_surface(context, options)
options = options or {}
@ -84,34 +40,29 @@ function Public.startup_test_surface(context, options)
local old_position = player.position
local old_character = player.character
local surface =
game.create_surface(
name,
{
width = area.x or area[1],
height = area.y or area[2],
autoplace_settings = autoplace_settings,
autoplace_controls = autoplace_controls,
cliff_settings = cliff_settings
}
)
local surface = game.create_surface(name, {
width = area.x or area[1],
height = area.y or area[2],
autoplace_settings = autoplace_settings,
autoplace_controls = autoplace_controls,
cliff_settings = cliff_settings
})
surface.request_to_generate_chunks({0, 0}, 32)
surface.force_generate_chunk_requests()
player.force.chart_all(surface)
context:next(
function()
for k, v in pairs(surface.find_entities()) do
v.destroy()
end
surface.destroy_decoratives {area = {{-32, -32}, {32, 32}}}
player.character = nil
player.teleport({0, 0}, surface)
player.create_character()
context:next(function()
for k, v in pairs(surface.find_entities()) do
v.destroy()
end
)
surface.destroy_decoratives {area = {{-32, -32}, {32, 32}}}
player.character = nil
player.teleport({0, 0}, surface)
player.create_character()
end)
return function()
player.character = nil
@ -125,4 +76,26 @@ function Public.startup_test_surface(context, options)
end
end
function Public.wait_for_chunk_to_be_charted(context, force, surface, chunk_position, next)
if not force.is_chunk_charted(surface, chunk_position) then
context:next(function()
Public.wait_for_chunk_to_be_charted(context, force, surface, chunk_position)
end)
return
end
if next then
context:next(next)
end
end
function Public.modify_lua_object(context, object, key, value)
local old_value = object[key]
rawset(object, key, value)
context:add_teardown(function()
rawset(object, key, old_value)
end)
end
return Public

View File

@ -8,9 +8,7 @@ local pcall = pcall
local Public = {}
Public.events = {
tests_run_finished = Event.generate_event_name('test_run_finished')
}
Public.events = {tests_run_finished = Event.generate_event_name('test_run_finished')}
local run_runnables_token
@ -67,6 +65,10 @@ local function print_hook_error(hook)
hook.context.player.print(table.concat {'Failed ', hook.name, " hook -':", tostring(hook.error)}, {r = 1})
end
local function print_teardown_error(context, name, error_message)
context.player.print(table.concat {'Failed ', name, " teardown -':", error_message}, {r = 1})
end
local function record_hook_error_in_module(hook)
if hook.name == 'startup' then
hook.module.startup_error = hook.error
@ -86,6 +88,32 @@ local function do_termination(data)
return true
end
local function run_teardown(teardown, errors)
local success, error_message = pcall(teardown)
if not success then
errors[#errors + 1] = error_message
end
end
local function do_teardowns(context, name)
local teardowns = context._teardowns
local errors = {}
for i = 1, #teardowns do
run_teardown(teardowns[i], errors)
end
if #errors > 0 then
local error_message = table.concat(errors, '\n')
print_teardown_error(context, name, error_message)
return error_message
end
return nil
end
local function run_hook(hook)
local context = hook.context
local steps = context._steps
@ -104,14 +132,22 @@ local function run_hook(hook)
hook.error = return_value
print_hook_error(hook)
record_hook_error_in_module(hook)
do_teardowns(context, hook.name)
return false
end
if current_step == #steps then
return true
if current_step ~= #steps then
return nil
end
return nil
local error_message = do_teardowns(context, hook.name)
if error_message then
hook.error = error_message
record_hook_error_in_module(hook)
return false
end
return true
end
local function do_hook(hook, data)
@ -152,16 +188,24 @@ local function run_test(test)
print_error(context.player, test.name, return_value)
test.passed = false
test.error = return_value
do_teardowns(context, test.name)
return false
end
if current_step == #steps then
print_success(context.player, test.name)
test.passed = true
return true
if current_step ~= #steps then
return nil
end
return nil
local error_message = do_teardowns(context, test.name)
if error_message then
test.passed = false
test.error = error_message
return false
end
print_success(context.player, test.name)
test.passed = true
return true
end
local function do_test(test, data)
@ -219,16 +263,14 @@ end
local function run(runnables, player, options)
options = validate_options(options)
run_runnables(
{
runnables = runnables,
player = player,
index = 1,
count = 0,
fail_count = 0,
stop_on_first_error = options.stop_on_first_error
}
)
run_runnables({
runnables = runnables,
player = player,
index = 1,
count = 0,
fail_count = 0,
stop_on_first_error = options.stop_on_first_error
})
end
function Public.run_module(module, player, options)