1
0
mirror of https://github.com/Refactorio/RedMew.git synced 2025-02-19 19:10:33 +02:00

Use a uniform storage for score storage

This commit is contained in:
Lynn 2019-05-30 20:22:21 +02:00
parent a5703fa2bb
commit 34e3190882
4 changed files with 220 additions and 100 deletions

View File

@ -331,7 +331,7 @@ local column_builders = {
local player_index = player.index
return {
count = PlayerStats.get_death_count(player_index),
causes = PlayerStats.get_all_death_counts_by_cause(player_index)
causes = PlayerStats.get_all_death_causes_by_player(player_index)
}
end,
sort = function(a, b)

View File

@ -2,8 +2,8 @@ local Event = require 'utils.event'
local PlayerStats = require 'features.player_stats'
local Gui = require 'utils.gui'
local Color = require 'resources.color_presets'
local Server = require('features.server')
local Server = require 'features.server'
local ScoreTracker = require 'utils.score_tracker'
local concat = table.concat
local main_frame_name = Gui.uid_name()

View File

@ -1,24 +1,40 @@
local Event = require 'utils.event'
local Global = require 'utils.global'
local ScoreTracker = require 'utils.score_tracker'
require 'utils.table'
local pairs = pairs
local sqrt = math.sqrt
local rocks_smashed_name = 'rocks-smashed'
local trees_cut_name = 'trees-cut'
local player_count_name = 'player-count'
local kills_by_trains_name = 'kills-by-trains'
local built_by_robots_name = 'built-by-robots'
local built_by_players_name = 'built-by-players'
local aliens_killed_name = 'aliens-killed'
local coins_spent_name = 'coins-spent'
local coins_earned_name = 'coins-earned'
local player_deaths_name = 'player-deaths'
local player_console_chats_name = 'player-console-chats'
local player_items_crafted_name = 'player-items-crafted'
local player_distance_walked_name = 'player-distance_walked'
ScoreTracker.register(rocks_smashed_name, {'Rocks smashed'}, '[img=entity.rock-huge]')
ScoreTracker.register(trees_cut_name, {'Trees cut down'}, '[img=entity.tree-02]')
ScoreTracker.register(player_count_name, {'Total players'})
ScoreTracker.register(kills_by_trains_name, {'Kills by trains'}, '[img=item.locomotive]')
ScoreTracker.register(built_by_players_name, {'Built by hand'}, '[img=utility.hand]')
ScoreTracker.register(built_by_robots_name, {'Built by robots'}, '[img=item.construction-robot]')
ScoreTracker.register(aliens_killed_name, {'Aliens liberated'}, '[img=entity.medium-biter]')
ScoreTracker.register(coins_earned_name, {'Coins earned'}, '[img=item.coin]')
ScoreTracker.register(coins_spent_name, {'Coins spent'}, '[img=item.coin]')
ScoreTracker.register(player_deaths_name, {'Player deaths'})
ScoreTracker.register(player_console_chats_name, {'Player console chats'})
ScoreTracker.register(player_items_crafted_name, {'Player items crafted'})
ScoreTracker.register(player_distance_walked_name, {'Player distance walked'})
local player_last_position = {}
local player_walk_distances = {}
local player_coin_earned = {}
local player_coin_spent = {}
local player_crafted_items = {}
local player_console_chats = {}
local player_deaths = {}
local total_players = {0}
local total_train_kills = {0}
local total_player_trees_mined = {0}
local total_player_rocks_mined = {0}
local total_robot_built_entities = {0}
local total_player_built_entities = {0}
local total_biter_kills = {0}
local total_coins_spent = {0}
local player_death_causes = {}
local train_kill_causes = {
['locomotive'] = true,
@ -30,37 +46,11 @@ local train_kill_causes = {
Global.register(
{
player_last_position = player_last_position,
player_walk_distances = player_walk_distances,
player_coin_earned = player_coin_earned,
player_coin_spent = player_coin_spent,
player_deaths = player_deaths,
total_players = total_players,
total_train_kills = total_train_kills,
total_player_trees_mined = total_player_trees_mined,
total_player_rocks_mined = total_player_rocks_mined,
player_crafted_items = player_crafted_items,
player_console_chats = player_console_chats,
total_robot_built_entities = total_robot_built_entities,
total_player_built_entities = total_player_built_entities,
total_biter_kills = total_biter_kills,
total_coins_spent = total_coins_spent
player_death_causes = player_death_causes,
},
function(tbl)
player_last_position = tbl.player_last_position
player_walk_distances = tbl.player_walk_distances
player_coin_earned = tbl.player_coin_earned
player_coin_spent = tbl.player_coin_spent
player_deaths = tbl.player_deaths
total_players = tbl.total_players
total_train_kills = tbl.total_train_kills
total_player_trees_mined = tbl.total_player_trees_mined
total_player_rocks_mined = tbl.total_player_rocks_mined
player_crafted_items = tbl.player_crafted_items
player_console_chats = tbl.player_console_chats
total_robot_built_entities = tbl.total_robot_built_entities
total_player_built_entities = tbl.total_player_built_entities
total_biter_kills = tbl.total_biter_kills
total_coins_spent = tbl.total_coins_spent
player_death_causes = tbl.player_death_causes
end
)
@ -69,13 +59,8 @@ local function player_created(event)
local index = event.player_index
player_last_position[index] = game.get_player(index).position
player_walk_distances[index] = 0
player_coin_earned[index] = 0
player_coin_spent[index] = 0
player_crafted_items[index] = 0
player_console_chats[index] = 0
player_deaths[index] = {causes = {}, count = 0}
total_players[1] = total_players[1] + 1
player_death_causes[index] = {}
ScoreTracker.changeForGlobal(player_count_name, 1)
end
local function get_cause_name(cause)
@ -97,60 +82,55 @@ local function player_died(event)
local player_index = event.player_index
local cause = get_cause_name(event.cause)
local data = player_deaths[player_index]
data.count = data.count + 1
local causes = data.causes
local causes = player_death_causes[player_index]
local cause_count = causes[cause] or 0
causes[cause] = cause_count + 1
ScoreTracker.changeForPlayer(player_index, player_deaths_name, 1)
if train_kill_causes[cause] then
total_train_kills[1] = total_train_kills[1] + 1
ScoreTracker.changeForGlobal(kills_by_trains_name, 1)
end
end
local function picked_up_item(event)
local stack = event.item_stack
if stack.name == 'coin' then
local player_index = event.player_index
player_coin_earned[player_index] = player_coin_earned[player_index] + stack.count
ScoreTracker.changeForPlayer(event.player_index, coins_earned_name, stack.count)
end
end
local function player_mined_item(event)
if event.entity.type == 'simple-entity' then -- Cheap check for rock, may have other side effects
total_player_rocks_mined[1] = total_player_rocks_mined[1] + 1
ScoreTracker.changeForGlobal(rocks_smashed_name, 1)
return
end
if event.entity.type == 'tree' then
total_player_trees_mined[1] = total_player_trees_mined[1] + 1
ScoreTracker.changeForGlobal(trees_cut_name, 1)
end
end
local function player_crafted_item(event)
local stack = event.item_stack
local player_index = event.player_index
player_crafted_items[player_index] = player_crafted_items[player_index] + stack.count
ScoreTracker.changeForPlayer(event.player_index, player_items_crafted_name, event.item_stack.count)
end
local function player_console_chat(event)
local player_index = event.player_index
if player_index then
player_console_chats[player_index] = player_console_chats[player_index] + 1
ScoreTracker.changeForPlayer(player_index, player_console_chats_name, 1)
end
end
local function player_built_entity()
total_player_built_entities[1] = total_player_built_entities[1] + 1
ScoreTracker.changeForGlobal(built_by_players_name, 1)
end
local function robot_built_entity()
total_robot_built_entities[1] = total_robot_built_entities[1] + 1
ScoreTracker.changeForGlobal(built_by_robots_name, 1)
end
local function biter_kill_counter(event)
if event.entity.force.name == 'enemy' then
total_biter_kills[1] = total_biter_kills[1] + 1
ScoreTracker.changeForGlobal(aliens_killed_name, 1)
end
end
@ -164,8 +144,8 @@ local function tick()
local d_x = last_pos.x - pos.x
local d_y = last_pos.y - pos.y
player_walk_distances[index] = player_walk_distances[index] + sqrt(d_x * d_x + d_y * d_y)
player_last_position[index] = pos
ScoreTracker.changeForPlayer(index, player_distance_walked_name, sqrt(d_x * d_x + d_y * d_y))
end
end
end
@ -186,85 +166,73 @@ Event.on_nth_tick(62, tick)
local Public = {}
function Public.get_walk_distance(player_index)
return player_walk_distances[player_index]
return ScoreTracker.getForPlayer(player_index, player_distance_walked_name)
end
function Public.get_coin_earned(player_index)
return player_coin_earned[player_index]
end
function Public.set_coin_earned(player_index, value)
player_coin_earned[player_index] = value
return ScoreTracker.getForPlayer(player_index, coins_earned_name)
end
function Public.change_coin_earned(player_index, amount)
player_coin_earned[player_index] = player_coin_earned[player_index] + amount
ScoreTracker.changeForPlayer(player_index, coins_earned_name, amount)
end
function Public.get_coin_spent(player_index)
return player_coin_spent[player_index]
end
function Public.set_coin_spent(player_index, value)
local old_value = player_coin_spent[player_index]
player_coin_spent[player_index] = value
local diff = value - old_value
total_coins_spent[1] = total_coins_spent[1] + diff
return ScoreTracker.getForPlayer(player_index, coins_spent_name)
end
function Public.change_coin_spent(player_index, amount)
player_coin_spent[player_index] = player_coin_spent[player_index] + amount
total_coins_spent[1] = total_coins_spent[1] + amount
ScoreTracker.changeForPlayer(player_index, coins_spent_name, amount)
ScoreTracker.changeForGlobal(coins_spent_name, amount)
end
function Public.get_death_count(player_index)
return player_deaths[player_index].count
return ScoreTracker.getForPlayer(player_index, player_deaths_name)
end
function Public.get_crafted_item(player_index)
return player_crafted_items[player_index]
return ScoreTracker.getForPlayer(player_index, player_items_crafted_name)
end
function Public.get_console_chat(player_index)
return player_console_chats[player_index]
return ScoreTracker.getForPlayer(player_index, player_console_chats_name)
end
-- Returns a dictionary of cause_name -> count
function Public.get_all_death_counts_by_cause(player_index)
return player_deaths[player_index].causes or {}
function Public.get_all_death_causes_by_player(player_index)
return player_death_causes[player_index] or {}
end
function Public.get_total_player_count()
return total_players[1]
return ScoreTracker.getForGlobal(player_count_name)
end
function Public.get_total_train_kills()
return total_train_kills[1]
return ScoreTracker.getForGlobal(kills_by_trains_name)
end
function Public.get_total_player_trees_mined()
return total_player_trees_mined[1]
return ScoreTracker.getForGlobal(trees_cut_name)
end
function Public.get_total_player_rocks_mined()
return total_player_rocks_mined[1]
return ScoreTracker.getForGlobal(rocks_smashed_name)
end
function Public.get_total_robot_built_entities()
return total_robot_built_entities[1]
return ScoreTracker.getForGlobal(built_by_robots_name)
end
function Public.get_total_player_built_entities()
return total_player_built_entities[1]
return ScoreTracker.getForGlobal(built_by_players_name)
end
function Public.get_total_biter_kills()
return total_biter_kills[1]
return ScoreTracker.getForGlobal(aliens_killed_name)
end
function Public.get_total_coins_spent()
return total_coins_spent[1]
return ScoreTracker.getForGlobal(coins_spent_name)
end
return Public

152
utils/score_tracker.lua Normal file
View File

@ -0,0 +1,152 @@
local Global = require 'utils.global'
local Event = require 'utils.event'
local error = error
local format = string.format
local raise_event = script.raise_event
local score_metadata = {}
local memory = {
players = {},
global = {}
}
Global.register(memory, function (tbl) memory = tbl end)
local Public = {}
Public.events = {
-- Event {
-- score_name = score_name
-- old_value = old_value
-- new_value = new_value
-- player_index = player_index
-- }
on_player_score_changed = Event.generate_event_name('on_player_score_changed'),
-- Event {
-- score_name = score_name
-- old_value = old_value
-- new_value = new_value
-- }
on_global_score_changed = Event.generate_event_name('on_global_score_changed'),
}
---Register a specific score.
---
--- This function must be called in the control stage, i.e. not inside an event.
---
---@param name string
---@param localisation_string table
---@param icon string
function Public.register(name, localisation_string, icon)
if _LIFECYCLE ~= _STAGE.control then
error(format('You can only register score types in the control stage, i.e. not inside events. Tried setting "%s".', name), 2)
end
if score_metadata[name] then
error(format('Trying to register score type for "%s" while it has already been registered.', name), 2)
end
local score = {
name = name,
icon = icon,
localised_string = localisation_string
}
score_metadata[name] = score
return score
end
---Sets a setting to a specific value for a player.
---
---@param player_index number
---@param score_name string
---@param value number|nil number to subtract or add
function Public.changeForPlayer(player_index, score_name, value)
local setting = score_metadata[score_name]
if not setting then
if _DEBUG then
error(format('Trying to change score "%s" while it has was never registered.', score_name), 2)
end
return
end
local player_score = memory.players[player_index]
if not player_score then
player_score = {}
memory.players[player_index] = player_score
end
local old_value = player_score[score_name] or 0
local new_value = old_value + value
player_score[score_name] = new_value
raise_event(Public.events.on_player_score_changed, {
score_name = score_name,
old_value = old_value,
new_value = new_value,
player_index = player_index
})
end
---Sets a setting to a specific value for a player.
---
---@param score_name string
---@param value number|nil number to subtract or add
function Public.changeForGlobal(score_name, value)
local setting = score_metadata[score_name]
if not setting then
if _DEBUG then
error(format('Trying to change score "%s" while it has was never registered.', score_name), 2)
end
return
end
local old_value = memory.global[score_name] or 0
local new_value = old_value + value
memory.global[score_name] = new_value
raise_event(Public.events.on_global_score_changed, {
score_name = score_name,
old_value = old_value,
new_value = new_value
})
end
---Returns the value for this player of a specific score.
---
---@param player_index number
---@param score_name string
function Public.getForPlayer(player_index, score_name)
local setting = score_metadata[score_name]
if not setting then
return nil
end
local player_scores = memory.players[player_index]
if not player_scores then
return 0
end
return player_scores[score_name] or 0
end
---Returns the value of the game score.
---
---@param score_name string
function Public.getForGlobal(score_name)
local setting = score_metadata[score_name]
if not setting then
return 0
end
return memory.global[score_name] or 0
end
---Returns the full score metadata, note that this is a reference, do not modify
---this data unless you know what you're doing!
function Public.get_score_metadata()
return score_metadata
end
return Public