mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-28 20:05:22 +09:00
Merge pull request #163 from Cooldude2606/feature/store-convert
Converted everything dependent on expcore.store
This commit is contained in:
@@ -7,7 +7,6 @@
|
||||
|
||||
local Gui = require 'expcore.gui' --- @dep expcore.gui
|
||||
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
||||
local Store = require 'expcore.store' --- @dep expcore.store
|
||||
local Game = require 'utils.game' --- @dep utils.game
|
||||
local Reports = require 'modules.control.reports' --- @dep modules.control.reports
|
||||
local Warnings = require 'modules.control.warnings' --- @dep modules.control.warnings
|
||||
@@ -15,11 +14,9 @@ local Jail = require 'modules.control.jail' --- @dep modules.control.jail
|
||||
local Colors = require 'utils.color_presets' --- @dep utils.color_presets
|
||||
local format_chat_player_name = _C.format_chat_player_name --- @dep expcore.common
|
||||
|
||||
local selected_player_store = ''
|
||||
local selected_action_store = ''
|
||||
local function set_store_uids(player,action)
|
||||
selected_player_store = player
|
||||
selected_action_store = action
|
||||
local SelectedPlayer, SelectedAction
|
||||
local function set_datastores(player, action)
|
||||
SelectedPlayer, SelectedAction = player, action
|
||||
end
|
||||
|
||||
-- auth that will only allow when on player's of lower roles
|
||||
@@ -33,13 +30,13 @@ end
|
||||
|
||||
-- gets the action player and a coloured name for the action to be used on
|
||||
local function get_action_player_name(player)
|
||||
local selected_player_name = Store.get(selected_player_store,player)
|
||||
local selected_player_name = SelectedPlayer:get(player)
|
||||
local selected_player = Game.get_player_from_any(selected_player_name)
|
||||
local selected_player_color = format_chat_player_name(selected_player)
|
||||
return selected_player_name, selected_player_color
|
||||
end
|
||||
|
||||
-- telports one player to another
|
||||
-- teleports one player to another
|
||||
local function teleport(from_player,to_player)
|
||||
local surface = to_player.surface
|
||||
local position = surface.find_non_colliding_position('character',to_player.position,32,1)
|
||||
@@ -109,7 +106,7 @@ local report_player = new_button('utility/spawn_flag',{'player-list.report-playe
|
||||
if Reports.is_reported(selected_player_name,player.name) then
|
||||
player.print({'expcom-report.already-reported'},Colors.orange_red)
|
||||
else
|
||||
Store.set(selected_action_store,player,'command/report')
|
||||
SelectedAction:set(player, 'command/report')
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -125,7 +122,7 @@ end
|
||||
-- @element warn_player
|
||||
local warn_player = new_button('utility/spawn_flag',{'player-list.warn-player'})
|
||||
:on_click(function(player)
|
||||
Store.set(selected_action_store,player,'command/give-warning')
|
||||
SelectedAction:set(player, 'command/give-warning')
|
||||
end)
|
||||
|
||||
local function warn_player_callback(player,reason)
|
||||
@@ -143,7 +140,7 @@ local jail_player = new_button('utility/multiplayer_waiting_icon',{'player-list.
|
||||
if Jail.is_jailed(selected_player_name) then
|
||||
player.print({'expcom-jail.already-jailed', selected_player_color},Colors.orange_red)
|
||||
else
|
||||
Store.set(selected_action_store,player,'command/jail')
|
||||
SelectedAction:set(player, 'command/jail')
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -162,7 +159,7 @@ local temp_ban_player = new_button('utility/warning_white',{'player-list.temp-ba
|
||||
if Jail.is_jailed(selected_player_name) then
|
||||
player.print({'expcom-jail.already-banned', selected_player_color},Colors.orange_red)
|
||||
else
|
||||
Store.set(selected_action_store,player,'command/temp-ban')
|
||||
SelectedAction:set(player, 'command/temp-ban')
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -177,7 +174,7 @@ end
|
||||
-- @element kick_player
|
||||
local kick_player = new_button('utility/warning_icon',{'player-list.kick-player'})
|
||||
:on_click(function(player)
|
||||
Store.set(selected_action_store,player,'command/kick')
|
||||
SelectedAction:set(player, 'command/kick')
|
||||
end)
|
||||
|
||||
local function kick_player_callback(player,reason)
|
||||
@@ -189,7 +186,7 @@ end
|
||||
-- @element ban_player
|
||||
local ban_player = new_button('utility/danger_icon',{'player-list.ban-player'})
|
||||
:on_click(function(player)
|
||||
Store.set(selected_action_store,player,'command/ban')
|
||||
SelectedAction:set(player, 'command/ban')
|
||||
end)
|
||||
|
||||
local function ban_player_callback(player,reason)
|
||||
@@ -198,7 +195,7 @@ local function ban_player_callback(player,reason)
|
||||
end
|
||||
|
||||
return {
|
||||
set_store_uids = set_store_uids,
|
||||
set_datastores = set_datastores,
|
||||
buttons = {
|
||||
['command/teleport'] = {
|
||||
auth=function(player,selected_player)
|
||||
|
||||
@@ -10,7 +10,7 @@ return {
|
||||
-- Warp cooldowns
|
||||
bypass_warp_cooldown = 'expcore.roles', --- @setting bypass_warp_cooldown dictates who the warp cooldown is applied to; values: all, admin, expcore.roles, none
|
||||
expcore_roles_bypass_warp_cooldown = 'gui/warp-list/bypass-cooldown', --- @setting expcore_roles_bypass_warp_cooldown if expcore.roles is used then this is the required permission
|
||||
cooldown_duraction = 60, --- @setting cooldown_duraction the duration of the warp cooldown in seconds
|
||||
cooldown_duration = 60, --- @setting cooldown_duration the duration of the warp cooldown in seconds
|
||||
|
||||
-- Warp proximity
|
||||
bypass_warp_proximity = 'expcore.roles', --- @setting bypass_warp_proximity dictates who the warp proximity is applied to; values: all, admin, expcore.roles, none
|
||||
|
||||
@@ -251,7 +251,8 @@ function DatastoreManager.ingest(action, datastoreName, key, valueJson)
|
||||
elseif action == 'propagate' or action == 'request' then
|
||||
local success, value = pcall(game.json_to_table, valueJson)
|
||||
if not success or value == nil then value = tonumber(valueJson) or valueJson end
|
||||
value = datastore:raise_event('on_load', key, value)
|
||||
local old_value = datastore:raw_get(key)
|
||||
value = datastore:raise_event('on_load', key, value, old_value)
|
||||
datastore:set(key, value)
|
||||
|
||||
end
|
||||
@@ -495,12 +496,13 @@ ExampleData:set('TestKey', 'Foo')
|
||||
]]
|
||||
function Datastore:set(key, value)
|
||||
key = self:serialize(key)
|
||||
local old_value = self:raw_get(key)
|
||||
if value == self.default and not self.allow_set_to_default then
|
||||
self:raw_set(key)
|
||||
else
|
||||
self:raw_set(key, value)
|
||||
end
|
||||
self:raise_event('on_update', key, value)
|
||||
self:raise_event('on_update', key, value, old_value)
|
||||
if self.auto_save then self:save(key) end
|
||||
return value
|
||||
end
|
||||
@@ -535,11 +537,12 @@ end)
|
||||
function Datastore:update(key, callback)
|
||||
key = self:serialize(key)
|
||||
local value = self:raw_get(key)
|
||||
local old_value = copy(self:raw_get(key))
|
||||
local success, new_value = xpcall(callback, update_error, key, value)
|
||||
if success and new_value ~= nil then
|
||||
self:set(key, new_value)
|
||||
else
|
||||
self:raise_event('on_update', key, value)
|
||||
self:raise_event('on_update', key, value, old_value)
|
||||
if self.auto_save then self:save(key) end
|
||||
end
|
||||
end
|
||||
@@ -554,8 +557,9 @@ ExampleData:remove('TestKey')
|
||||
]]
|
||||
function Datastore:remove(key)
|
||||
key = self:serialize(key)
|
||||
local old_value = self:raw_get(key)
|
||||
self:raw_set(key)
|
||||
self:raise_event('on_update', key)
|
||||
self:raise_event('on_update', key, nil, old_value)
|
||||
if self.save_to_disk then self:write_action('remove', key) end
|
||||
if self.parent and self.parent.auto_save then return self.parent:save(key) end
|
||||
end
|
||||
@@ -622,11 +626,12 @@ end)
|
||||
function Datastore:update_all(callback)
|
||||
local data = self:get_all()
|
||||
for key, value in pairs(data) do
|
||||
local old_value = copy(value)
|
||||
local success, new_value = xpcall(callback, update_error, key, value)
|
||||
if success and new_value ~= nil then
|
||||
self:set(key, new_value)
|
||||
else
|
||||
self:raise_event('on_update', key, value)
|
||||
self:raise_event('on_update', key, value, old_value)
|
||||
if self.auto_save then self:save(key) end
|
||||
end
|
||||
end
|
||||
@@ -749,12 +754,13 @@ local function event_error(err) log('An error ocurred in a datastore event handl
|
||||
value = self:raise_event('on_save', key, value)
|
||||
|
||||
]]
|
||||
function Datastore:raise_event(event_name, key, value, source)
|
||||
function Datastore:raise_event(event_name, key, value, old_value, source)
|
||||
-- Raise the event for the children of this datastore
|
||||
if source ~= 'child' and next(self.children) then
|
||||
if type(value) ~= 'table' then value = {} end
|
||||
for value_name, child in pairs(self.children) do
|
||||
value[value_name] = child:raise_event(event_name, key, value[value_name], 'parent')
|
||||
local old_child_value = old_value and old_value[value_name] or nil
|
||||
value[value_name] = child:raise_event(event_name, key, value[value_name], old_child_value, 'parent')
|
||||
end
|
||||
end
|
||||
|
||||
@@ -762,14 +768,15 @@ function Datastore:raise_event(event_name, key, value, source)
|
||||
local handlers = self.events[event_name]
|
||||
if handlers then
|
||||
for _, handler in ipairs(handlers) do
|
||||
local success, new_value = xpcall(handler, event_error, key, value)
|
||||
local success, new_value = xpcall(handler, event_error, key, value, old_value)
|
||||
if success and new_value ~= nil then value = new_value end
|
||||
end
|
||||
end
|
||||
|
||||
-- Raise the event for the parent of this datastore
|
||||
if source ~= 'parent' and self.parent then
|
||||
self.parent:raise_event(event_name, key, self.parent:raw_get(key, true), 'child')
|
||||
local parent_value = self.parent:raw_get(key, true)
|
||||
self.parent:raise_event(event_name, key, parent_value, parent_value, 'child')
|
||||
end
|
||||
|
||||
-- If this is the save event and the table is empty then return nil
|
||||
|
||||
@@ -90,9 +90,8 @@ local check_data_loaded = Async.register(function(player)
|
||||
end)
|
||||
|
||||
--- When player data loads tell the player if the load had failed previously
|
||||
PlayerData:on_load(function(player_name, player_data)
|
||||
PlayerData:on_load(function(player_name, player_data, existing_data)
|
||||
if not player_data or player_data.valid == false then return end
|
||||
local existing_data = PlayerData:get(player_name)
|
||||
if existing_data and existing_data.valid == false then
|
||||
game.players[player_name].print{'expcore-data.data-restore'}
|
||||
end
|
||||
@@ -133,7 +132,7 @@ Event.add(defines.events.on_player_left_game, function(event)
|
||||
local player_data = PlayerData:get(player)
|
||||
if player_data.valid == true then
|
||||
PlayerData:unload(player)
|
||||
else PlayerData:raw_set(player) end
|
||||
else PlayerData:raw_set(player.name) end
|
||||
end)
|
||||
|
||||
----- Module Return -----
|
||||
|
||||
@@ -1,523 +0,0 @@
|
||||
--[[-- Core Module - Store
|
||||
- Used to store and watch for updates for values in the global table
|
||||
@core Store
|
||||
@alias Store
|
||||
|
||||
@usage-- Require the module and add a store with no keys
|
||||
-- Store with no keys does not need a serializer
|
||||
local Store = require 'expcore.store' --- @dep expcore.store
|
||||
local scenario_diffculty = Store.register()
|
||||
|
||||
-- When the store is changed this function will trigger
|
||||
Store.watch(scenario_diffculty, function(value)
|
||||
game.print('The scenario diffculty has been set to '..value)
|
||||
end)
|
||||
|
||||
Store.set(scenario_diffculty, 'hard') -- Set the value stored to 'hard'
|
||||
Store.get(scenario_diffculty) -- Returns 'hard'
|
||||
Store.update(scenario_diffculty, function(value) -- Will set value to 'normal' if no value is present
|
||||
return not value and 'normal'
|
||||
end)
|
||||
|
||||
@usage-- Require the module and add a store with keys
|
||||
-- Store with keys does not require a serializer but it can be helpful
|
||||
local Store = require 'expcore.store' --- @dep expcore.store
|
||||
local player_scores = Store.register(function(player) -- Use player name as the key
|
||||
return player.name
|
||||
end)
|
||||
|
||||
-- When any key in the store is changed this function will trigger
|
||||
Store.watch(player_scores, function(value, key, old_value)
|
||||
game.print(key..' now has a score of '..value)
|
||||
end)
|
||||
|
||||
Store.set(player_scores, game.player, 10) -- Set your score to 10
|
||||
Store.get(scenario_diffculty, game.player) -- Returns 10
|
||||
Store.update(scenario_diffculty, game.player, function(value) -- Add 1 to your score
|
||||
return value + 1
|
||||
end)
|
||||
|
||||
]]
|
||||
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
|
||||
local Store = {
|
||||
--- The current highest uid that is being used, will not increase during runtime
|
||||
-- @field uid
|
||||
uid = 0,
|
||||
--- An array of the serializers that stores are using, key is store uids
|
||||
-- @table serializers
|
||||
serializers = {},
|
||||
--- An array of watchers that stores will trigger, key is store uids
|
||||
-- @table watchers
|
||||
watchers = {},
|
||||
--- An index used for debuging to find the file where different stores where registered
|
||||
-- @table file_paths
|
||||
file_paths = {}
|
||||
}
|
||||
|
||||
-- All data is stored in global.data_store and is accessed here with data_store
|
||||
local data_store = {}
|
||||
global.data_store = data_store
|
||||
Event.on_load(function()
|
||||
data_store = global.data_store
|
||||
end)
|
||||
|
||||
--- Store Setup.
|
||||
-- @section setup
|
||||
|
||||
--[[-- An error checking and serializing function for checking store uids and keys, note key is not required
|
||||
@tparam number store the uid of the store that you want to check is valid
|
||||
@tparam[opt] ?string|any key the key that you want to serialize or check is a string
|
||||
@tparam[opt=1] number error_stack the position in the stack relative to the current function (1) to raise this error on
|
||||
@treturn string if key is given and a serializer is registered, or key was already a string, then the key is returned
|
||||
|
||||
@usage-- Registering a new store and checking that it is valid
|
||||
-- New store will use player names as the keys
|
||||
local player_scores = Store.register(function(player)
|
||||
return player.name
|
||||
end)
|
||||
|
||||
-- player_scores is a valid store and key will be your player name
|
||||
local key = Store.validate(player_scores, game.player)
|
||||
|
||||
]]
|
||||
function Store.validate(store, key, error_stack)
|
||||
error_stack = error_stack or 1
|
||||
|
||||
if type(store) ~= 'number' then
|
||||
-- Store is not a number and so if not valid
|
||||
error('Store uid given is not a number; recived type '..type(store), error_stack+1)
|
||||
elseif store > Store.uid then
|
||||
-- Store is a number but it is out of range, ie larger than the current highest uid
|
||||
error('Store uid is out of range; recived '..tostring(store), error_stack+1)
|
||||
elseif key ~= nil and type(key) ~= 'string' and Store.serializers[store] == nil then
|
||||
-- Key is present but is not a string and there is no serializer registered
|
||||
error('Store key is not a string and no serializer has been registered; recived '..type(key), error_stack+1)
|
||||
elseif key ~= nil then
|
||||
-- Key is present and so it is serialized and returned
|
||||
local serializer = Store.serializers[store]
|
||||
if type(key) ~= 'string' then
|
||||
local success, serialized_key = pcall(serializer, key)
|
||||
|
||||
if not success then
|
||||
-- Serializer casued an error while serializing the key
|
||||
error('Store watcher casued an error:\n\t'..key, error_stack+1)
|
||||
elseif type(serialized_key) ~= 'string' then
|
||||
-- Serializer was successful but failed to return a string value
|
||||
error('Store key serializer did not return a string; recived type '..type(key), error_stack+1)
|
||||
end
|
||||
|
||||
return serialized_key
|
||||
end
|
||||
|
||||
return key
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--[[-- Required to create new stores and register an serializer to a store, serializer not required
|
||||
@tparam[opt] function serializer the function used to convert non string keys into strings to be used in the store
|
||||
@treturn number the uid for the new store that you have created, use this as the first param to all other functions
|
||||
|
||||
@usage-- Creating a store with no serializer
|
||||
local scenario_diffculty = Store.register()
|
||||
|
||||
@usage-- Creating a store which can take LuaPlayer
|
||||
local player_scores = Store.register(function(player)
|
||||
return player.name
|
||||
end)
|
||||
|
||||
]]
|
||||
function Store.register(serializer)
|
||||
if _LIFECYCLE ~= _STAGE.control then
|
||||
-- Only allow this function to be called during the control stage
|
||||
error('Store can not be registered durring runtime', 2)
|
||||
end
|
||||
|
||||
-- Increment the uid counter
|
||||
local uid = Store.uid + 1
|
||||
Store.uid = uid
|
||||
|
||||
-- Register the serializer if given
|
||||
if serializer then
|
||||
Store.serializers[uid] = serializer
|
||||
end
|
||||
|
||||
-- Add entry in the debug table
|
||||
local file_path = debug.getinfo(2, 'S').source:match('^.+/currently%-playing/(.+)$'):sub(1, -5)
|
||||
Store.file_paths[uid] = file_path
|
||||
|
||||
-- Return the new uid
|
||||
return uid
|
||||
end
|
||||
|
||||
--[[-- Register a watch function to a store that is called when the value in the store is changed, triggers for any key
|
||||
@tparam number store the uid of the store that you want to watch for changes to
|
||||
@tparam function watcher the function that will be called when there is a change to the store
|
||||
|
||||
@usage-- Printing the changed value to all players, no keys
|
||||
-- Register the new store, we are not using keys so we dont need a serializer
|
||||
local scenario_diffculty = Store.register()
|
||||
|
||||
-- Register the watcher so that when we change the value the message is printed
|
||||
Store.watch(scenario_diffculty, function(value)
|
||||
game.print('The scenario diffculty has been set to '..value)
|
||||
end)
|
||||
|
||||
-- Set a new value for the diffculty and see that it has printed to the game
|
||||
Store.set(scenario_diffculty, 'hard')
|
||||
|
||||
@usage-- Printing the changed value to all players, with keys
|
||||
-- Register the new store, we are not using player names as the keys so it would be useful to accept LuaPlayer objects
|
||||
local player_scores = Store.register(function(player)
|
||||
return player.name
|
||||
end)
|
||||
|
||||
-- Register the watcher so that when we change the value the message is printed
|
||||
Store.watch(player_scores, function(value, key, old_value)
|
||||
game.print(key..' now has a score of '..value)
|
||||
end)
|
||||
|
||||
-- Set a new value for your score and see that it has printed to the game
|
||||
Store.set(player_scores, game.player, 10)
|
||||
|
||||
]]
|
||||
function Store.watch(store, watcher)
|
||||
if _LIFECYCLE ~= _STAGE.control then
|
||||
-- Only allow this function to be called during the control stage
|
||||
error('Store watcher can not be registered durring runtime', 2)
|
||||
end
|
||||
|
||||
Store.validate(store, nil, 2)
|
||||
|
||||
-- Add the watchers table if it does not exist
|
||||
local watchers = Store.watchers[store]
|
||||
if not watchers then
|
||||
watchers = {}
|
||||
Store.watchers[store] = watchers
|
||||
end
|
||||
|
||||
-- Append the new watcher function
|
||||
watchers[#watchers+1] = watcher
|
||||
end
|
||||
|
||||
--- Store Data Management.
|
||||
-- @section data
|
||||
|
||||
--[[-- Used to retrive the current data that is stored, key is optional depending on if you are using them
|
||||
@tparam number store the uid of the store that you want to get the value from
|
||||
@tparam[opt] ?string|any key the key that you want to get the value of, must be a string unless you have a serializer
|
||||
@treturn any the data that is stored
|
||||
|
||||
@usage-- Getting the value of a store with no keys
|
||||
-- Register the new store, we are not using keys so we dont need a serializer
|
||||
local scenario_diffculty = Store.register()
|
||||
|
||||
-- Get the current diffculty for the scenario
|
||||
local diffculty = Store.get(scenario_diffculty)
|
||||
|
||||
@usage-- Getting the data from a store with keys
|
||||
-- Register the new store, we are not using player names as the keys so it would be useful to accept LuaPlayer objects
|
||||
local player_scores = Store.register(function(player)
|
||||
return player.name
|
||||
end)
|
||||
|
||||
-- Get your current score
|
||||
local my_score = Store.get(player_scores, game.player)
|
||||
|
||||
-- Get all scores
|
||||
lcoal scores = Store.get(player_scores)
|
||||
|
||||
]]
|
||||
function Store.get(store, key)
|
||||
key = Store.validate(store, key, 2)
|
||||
|
||||
-- Get the data from the data store
|
||||
local data = data_store[store]
|
||||
if key then
|
||||
if type(data) ~= 'table' then
|
||||
data_store[store] = {_value = data_store[store]}
|
||||
return nil
|
||||
else
|
||||
return data[key]
|
||||
end
|
||||
end
|
||||
|
||||
-- Return all data if there is no key
|
||||
return data
|
||||
end
|
||||
|
||||
--[[-- Used to clear the data in a store, will trigger any watchers, key is optional depending on if you are using them
|
||||
@tparam number store the uid of the store that you want to clear
|
||||
@tparam[opt] ?string|any key the key that you want to clear, must be a string unless you have a serializer
|
||||
|
||||
@usage-- Clear a store which does not use keys
|
||||
-- Register the new store, we are not using keys so we dont need a serializer
|
||||
local scenario_diffculty = Store.register()
|
||||
|
||||
-- Clear the scenario diffculty
|
||||
Store.clear(scenario_diffculty)
|
||||
|
||||
@usage-- Clear data that is in a store with keys
|
||||
-- Register the new store, we are not using player names as the keys so it would be useful to accept LuaPlayer objects
|
||||
local player_scores = Store.register(function(player)
|
||||
return player.name
|
||||
end)
|
||||
|
||||
-- Clear your score
|
||||
Store.clear(player_scores, game.player)
|
||||
|
||||
-- Clear all scores
|
||||
Store.clear(player_scores)
|
||||
|
||||
]]
|
||||
function Store.clear(store, key)
|
||||
key = Store.validate(store, key, 2)
|
||||
local old_value
|
||||
|
||||
-- Check if there is a key being used
|
||||
if key then
|
||||
if type(data_store[store]) == 'table' then
|
||||
old_value = data_store[store][key]
|
||||
data_store[store][key] = nil
|
||||
end
|
||||
else
|
||||
old_value = data_store[store]
|
||||
data_store[store] = nil
|
||||
end
|
||||
|
||||
-- Trigger any watch functions
|
||||
Store.raw_trigger(store, key, nil, old_value)
|
||||
end
|
||||
|
||||
--[[-- Used to set the data in a store, will trigger any watchers, key is optional depending on if you are using them
|
||||
@tparam number store the uid of the store that you want to set
|
||||
@tparam[opt] ?string|any key the key that you want to set, must be a string unless you have a serializer
|
||||
@tparam any value the value that you want to set
|
||||
|
||||
@usage-- Setting a store which does not use keys
|
||||
-- Register the new store, we are not using keys so we dont need a serializer
|
||||
local scenario_diffculty = Store.register()
|
||||
|
||||
-- Set the new scenario diffculty
|
||||
Store.set(scenario_diffculty, 'hard')
|
||||
|
||||
@usage-- Set data in a store with keys
|
||||
-- Register the new store, we are not using player names as the keys so it would be useful to accept LuaPlayer objects
|
||||
local player_scores = Store.register(function(player)
|
||||
return player.name
|
||||
end)
|
||||
|
||||
-- Set your current score
|
||||
Store.set(player_scores, game.player, 10)
|
||||
|
||||
-- Set all scores, note this might not have much use
|
||||
Store.set(player_scores, {
|
||||
[game.player.name] = 10,
|
||||
['SomeOtherPlayer'] = 0
|
||||
})
|
||||
|
||||
]]
|
||||
function Store.set(store, key, value)
|
||||
-- Allow for key to be optional
|
||||
if value == nil then
|
||||
value = key
|
||||
key = nil
|
||||
end
|
||||
|
||||
-- Check the store is valid
|
||||
key = Store.validate(store, key, 2)
|
||||
local old_value
|
||||
|
||||
-- If there is a key being used then the store must be a able
|
||||
if key then
|
||||
if type(data_store[store]) ~= 'table' then
|
||||
data_store[store] = {_value = data_store[store]}
|
||||
end
|
||||
old_value = data_store[store][key]
|
||||
data_store[store][key] = value
|
||||
else
|
||||
old_value = data_store[store]
|
||||
data_store[store] = value
|
||||
end
|
||||
|
||||
-- Trigger any watchers
|
||||
Store.raw_trigger(store, key, value, old_value)
|
||||
end
|
||||
|
||||
--[[-- Used to update the data in a store, use this with tables, will trigger any watchers, key is optional depending on if you are using them
|
||||
@tparam number store the uid of the store that you want to update
|
||||
@tparam[opt] ?string|any key the key that you want to update, must be a string unless you have a serializer
|
||||
@tparam function updater the function which is called to make changes to the value, such as changing table keys, if a value is returned it will replace the current value in the store
|
||||
|
||||
@usage-- Incrementing a global score
|
||||
-- Because we are only going to have one score so we will not need keys or a serializer
|
||||
local game_score = Store.register()
|
||||
|
||||
-- Setting a default value
|
||||
Store.set(game_score, 0)
|
||||
|
||||
-- We now will update the game score by one, we return the value so that it is set as the new value in the store
|
||||
Store.update(game_score, function(value)
|
||||
return value + 1
|
||||
end)
|
||||
|
||||
@usage-- Updating keys in a table of data
|
||||
-- Register the new store, we are not using player names as the keys so it would be useful to accept LuaPlayer objects
|
||||
local player_data = Store.register(function(player)
|
||||
return player.name
|
||||
end)
|
||||
|
||||
-- Setting a default value for your player, used to show the table structure
|
||||
Store.set(player_data, game.player, {
|
||||
group = 'Admin',
|
||||
role = 'Owner',
|
||||
show_group_config = false
|
||||
})
|
||||
|
||||
-- Updating the show_group_config key in your player data, note that it would be harder to call set every time
|
||||
-- We do not need to return anything in this case as we are not replacing all the data
|
||||
Store.update(player_data, game.player, function(data)
|
||||
data.show_group_config = not data.show_group_config
|
||||
end)
|
||||
|
||||
]]
|
||||
function Store.update(store, key, updater)
|
||||
-- Allow for key to be nil
|
||||
if updater == nil then
|
||||
updater = key
|
||||
key = nil
|
||||
end
|
||||
|
||||
-- Check the store is valid
|
||||
key = Store.validate(store, key, 2)
|
||||
local value, old_value
|
||||
|
||||
-- If a key is used then the store must be a table
|
||||
if key then
|
||||
if type(data_store[store]) ~= 'table' then
|
||||
data_store[store] = {_value = data_store[store]}
|
||||
end
|
||||
|
||||
-- Call the updater and if it returns a value then set this value
|
||||
local rtn = updater(data_store[store][key])
|
||||
if rtn then
|
||||
old_value = data_store[store][key]
|
||||
data_store[store][key] = rtn
|
||||
end
|
||||
value = data_store[store][key]
|
||||
|
||||
else
|
||||
-- Call the updater and if it returns a value then set this value
|
||||
local rtn = updater(data_store[store])
|
||||
if rtn then
|
||||
old_value = data_store[store][key]
|
||||
data_store[store] = rtn
|
||||
end
|
||||
value = data_store[store]
|
||||
|
||||
end
|
||||
|
||||
-- Trigger any watchers
|
||||
Store.raw_trigger(store, key, value, old_value)
|
||||
end
|
||||
|
||||
--[[-- Used to update all values that are in a store, similar to Store.update but acts on all keys at once, will trigger watchers for every key present
|
||||
@tparam number store the uid of the store that you want to map
|
||||
@tparam function updater the function that is called on every key in this store
|
||||
|
||||
@usage-- Updating keys in a table of data
|
||||
-- Register the new store, we are not using player names as the keys so it would be useful to accept LuaPlayer objects
|
||||
local player_data = Store.register(function(player)
|
||||
return player.name
|
||||
end)
|
||||
|
||||
-- Setting a default value for your player, used to show the table structure
|
||||
Store.set(player_data, game.player, {
|
||||
group = 'Admin',
|
||||
role = 'Owner',
|
||||
show_group_config = false
|
||||
})
|
||||
|
||||
-- Updating the show_group_config key for all players, note that it would be harder to call set every time
|
||||
-- We do not need to return anything in this case as we are not replacing all the data
|
||||
-- We also have access to the current key being updated if needed
|
||||
Store.map(player_data, function(data, key)
|
||||
data.show_group_config = not data.show_group_config
|
||||
end)
|
||||
|
||||
]]
|
||||
function Store.map(store, updater)
|
||||
Store.validate(store, nil, 2)
|
||||
|
||||
-- Get all that data in the store and check its a table
|
||||
local data = data_store[store]
|
||||
if type(data) ~= 'table' then
|
||||
return
|
||||
end
|
||||
|
||||
-- Loop over all the keys and call the updater, setting value if returned, and calling watcher functions
|
||||
for key, value in pairs(data) do
|
||||
local rtn = updater(value, key)
|
||||
if rtn then
|
||||
data[key] = rtn
|
||||
end
|
||||
Store.raw_trigger(store, key, data[key], value)
|
||||
end
|
||||
end
|
||||
|
||||
--[[-- Used to trigger watcher functions, this may be used to trigger them if you did not use Store.update or Store.set
|
||||
@tparam number store the uid of the store that you want to trigger
|
||||
@tparam[opt] ?string|any key the key that you want to trigger, must be a string unless you have a serializer
|
||||
@usage-- Faking the update to a store
|
||||
-- The type of store we use does not really matter for this as long as you pass it what you watchers are expecting
|
||||
local scenario_diffculty = Store.register()
|
||||
|
||||
-- Trigger the watchers with a fake change of diffculty
|
||||
Store.trigger(scenario_diffculty)
|
||||
|
||||
]]
|
||||
function Store.trigger(store, key)
|
||||
key = Store.validate(store, key, 2)
|
||||
|
||||
-- Get the data from the data store
|
||||
local data = data_store[store]
|
||||
if key then
|
||||
data = data[key]
|
||||
Store.raw_trigger(store, key, data, data)
|
||||
else
|
||||
Store.raw_trigger(store, key, data, data)
|
||||
end
|
||||
end
|
||||
|
||||
--[[-- Used to trigger watcher functions, the value and key are passed directly to the watchers regardless if the value is correct
|
||||
@tparam number store the uid of the store that you want to trigger
|
||||
@tparam[opt] ?string|any key the key that you want to trigger, must be a string unless you have a serializer
|
||||
@tparam[opt] any value the new value that is at this key or store, passed directly to the watcher
|
||||
@tparam[opt] any old_value the old value that was at this key or store often the same if value is a table, passed directly to the watcher
|
||||
|
||||
@usage-- Triggering a manule call of the watchers
|
||||
-- The type of store we use does not really matter for this as long as you pass it what you watchers are expecting
|
||||
local scenario_diffculty = Store.register()
|
||||
|
||||
-- Trigger the watchers with a fake change of diffculty
|
||||
-- This is mostly used internally but it can be useful in other cases
|
||||
Store.raw_trigger(scenario_diffculty, nil, 'normal', 'normal')
|
||||
|
||||
]]
|
||||
function Store.raw_trigger(store, key, value, old_value)
|
||||
key = Store.validate(store, key, 2)
|
||||
|
||||
-- Get the watchers and then loop over them
|
||||
local watchers = Store.watchers[store] or {}
|
||||
for _, watcher in pairs(watchers) do
|
||||
local success, err = pcall(watcher, value, key, old_value)
|
||||
if not success then
|
||||
error('Store watcher casued an error:\n\t'..err)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Module return
|
||||
return Store
|
||||
@@ -15,7 +15,6 @@ local interface_modules = {
|
||||
['output']=Common.player_return,
|
||||
['Group']='expcore.permission_groups',
|
||||
['Roles']='expcore.roles',
|
||||
['Store']='expcore.store',
|
||||
['Gui']='expcore.gui',
|
||||
['Async']='expcore.async',
|
||||
['Datastore']='expcore.datastore'
|
||||
|
||||
@@ -10,22 +10,21 @@ Tasks.update_task(task_id, 'We need more iron!', game.player.name)
|
||||
|
||||
]]
|
||||
|
||||
local Store = require 'expcore.store' --- @dep expcore.store
|
||||
local Datastore = require 'expcore.datastore' --- @dep expcore.datastore
|
||||
local Global = require 'utils.global' --- @dep utils.global
|
||||
local Token = require 'utils.token' --- @dep utils.token
|
||||
|
||||
--- Stores all data for the warp gui
|
||||
local TaskData = Datastore.connect('TaskData')
|
||||
TaskData:set_serializer(function(raw_key) return raw_key.task_id end)
|
||||
|
||||
local Tasks = {}
|
||||
|
||||
-- Global lookup table for force name to task ids
|
||||
local force_tasks = {}
|
||||
local force_tasks = {_uid=1}
|
||||
Global.register(force_tasks, function(tbl)
|
||||
force_tasks = tbl
|
||||
end)
|
||||
|
||||
-- Task store is keyed by task id, value is a table
|
||||
local task_store = Store.register()
|
||||
Tasks.store = task_store
|
||||
|
||||
--- Setters.
|
||||
-- functions used to created and alter tasks
|
||||
-- @section setters
|
||||
@@ -43,8 +42,9 @@ local task_id = Tasks.add_task(game.player.force.name, nil, game.player.name)
|
||||
]]
|
||||
function Tasks.add_task(force_name, task_number, player_name, task_message)
|
||||
-- Get a new task id
|
||||
local task_id = tostring(Token.uid())
|
||||
local task_id = tostring(force_tasks._uid)
|
||||
task_message = task_message or 'New Task'
|
||||
force_tasks._uid = force_tasks._uid + 1
|
||||
|
||||
-- Get the existing tasks for this force
|
||||
local tasks = force_tasks[force_name]
|
||||
@@ -67,13 +67,13 @@ function Tasks.add_task(force_name, task_number, player_name, task_message)
|
||||
end
|
||||
|
||||
-- Add the new task to the store
|
||||
Store.set(task_store, task_id, {
|
||||
TaskData:set(task_id, {
|
||||
task_id = task_id,
|
||||
force_name = force_name,
|
||||
message = task_message,
|
||||
last_edit_name = player_name or '<server>',
|
||||
last_edit_time = game.tick,
|
||||
curently_editing = editing
|
||||
currently_editing = editing
|
||||
})
|
||||
|
||||
return task_id
|
||||
@@ -87,10 +87,10 @@ Tasks.remove_task(task_id)
|
||||
|
||||
]]
|
||||
function Tasks.remove_task(task_id)
|
||||
local task = Store.get(task_store, task_id)
|
||||
local task = TaskData:get(task_id)
|
||||
local force_name = task.force_name
|
||||
table.remove_element(force_tasks[force_name], task_id)
|
||||
Store.clear(task_store, task_id)
|
||||
TaskData:remove(task_id)
|
||||
end
|
||||
|
||||
--[[-- Update the message and last edited information for a task
|
||||
@@ -103,7 +103,7 @@ Task.update_task(task_id, 'We need more iron!', game.player.name)
|
||||
|
||||
]]
|
||||
function Tasks.update_task(task_id, new_message, player_name)
|
||||
Store.update(task_store, task_id, function(task)
|
||||
TaskData:update(task_id, function(_, task)
|
||||
task.last_edit_name = player_name or '<server>'
|
||||
task.last_edit_time = game.tick
|
||||
task.message = new_message
|
||||
@@ -120,8 +120,8 @@ Tasks.set_editing(task_id, game.player.name, true)
|
||||
|
||||
]]
|
||||
function Tasks.set_editing(task_id, player_name, state)
|
||||
Store.update(task_store, task_id, function(task)
|
||||
task.curently_editing[player_name] = state
|
||||
TaskData:update(task_id, function(_, task)
|
||||
task.currently_editing[player_name] = state
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -135,7 +135,7 @@ end)
|
||||
|
||||
]]
|
||||
function Tasks.on_update(handler)
|
||||
Store.watch(task_store, handler)
|
||||
TaskData:on_update(handler)
|
||||
end
|
||||
|
||||
--- Getters.
|
||||
@@ -151,7 +151,7 @@ local task = Tasks.get_task(task_id)
|
||||
|
||||
]]
|
||||
function Tasks.get_task(task_id)
|
||||
return Store.get(task_store, task_id)
|
||||
return TaskData:get(task_id)
|
||||
end
|
||||
|
||||
--[[-- Gets all the task ids that a force has
|
||||
@@ -176,8 +176,8 @@ local editing = Tasks.get_editing(task_id, game.player.name)
|
||||
|
||||
]]
|
||||
function Tasks.get_editing(task_id, player_name)
|
||||
local task = Store.get(task_store, task_id)
|
||||
return task.curently_editing[player_name]
|
||||
local task = TaskData:get(task_id)
|
||||
return task.currently_editing[player_name]
|
||||
end
|
||||
|
||||
-- Module Return
|
||||
|
||||
@@ -21,25 +21,24 @@ Warps.make_warp_tag(warp_id)
|
||||
|
||||
]]
|
||||
|
||||
local Store = require 'expcore.store' --- @dep expcore.store
|
||||
local Datastore = require 'expcore.datastore' --- @dep expcore.datastore
|
||||
local Global = require 'utils.global' --- @dep utils.global
|
||||
local Token = require 'utils.token' --- @dep utils.token
|
||||
local config = require 'config.gui.warps' --- @dep config.warps
|
||||
|
||||
--- Stores all data for the warp system
|
||||
local WrapData = Datastore.connect('WrapData')
|
||||
WrapData:set_serializer(function(raw_key) return raw_key.warp_id end)
|
||||
|
||||
local Warps = {}
|
||||
|
||||
-- Global lookup table for force name to task ids
|
||||
local force_warps = {}
|
||||
local force_warps = {_uid=1}
|
||||
Global.register(force_warps, function(tbl)
|
||||
force_warps = tbl
|
||||
end)
|
||||
|
||||
-- Warp store is keyed by warp id, value is a table
|
||||
local warp_store = Store.register()
|
||||
Warps.store = warp_store
|
||||
|
||||
-- When a warp is updated change its chat tag and resort the warp order
|
||||
Store.watch(warp_store, function(warp, warp_id)
|
||||
WrapData:on_update(function(warp_id, warp, old_warp)
|
||||
if warp then
|
||||
-- Update the map chart tag if there is one
|
||||
if warp.tag then
|
||||
@@ -47,7 +46,7 @@ Store.watch(warp_store, function(warp, warp_id)
|
||||
end
|
||||
|
||||
-- Check that the name of the warp has been changed
|
||||
if warp.name == warp.old_name then return end
|
||||
if not old_warp or warp.name == old_warp.name then return end
|
||||
|
||||
-- Get the names of all the warp points for this force
|
||||
local force_name = warp.force_name
|
||||
@@ -56,7 +55,7 @@ Store.watch(warp_store, function(warp, warp_id)
|
||||
|
||||
local warp_names = {}
|
||||
for _, next_warp_id in pairs(warp_ids) do
|
||||
local next_warp = Store.get(warp_store, next_warp_id)
|
||||
local next_warp = WrapData:get(next_warp_id)
|
||||
if next_warp_id ~= spawn_id then
|
||||
warp_names[next_warp.name..next_warp_id] = next_warp_id
|
||||
end
|
||||
@@ -70,9 +69,9 @@ Store.watch(warp_store, function(warp, warp_id)
|
||||
end
|
||||
end)
|
||||
|
||||
--- Map Intergration.
|
||||
--- Map Integration.
|
||||
-- functions used to create and alter warps with in the map
|
||||
-- @section mapIntergration
|
||||
-- @section mapIntegration
|
||||
|
||||
--[[-- Add or update the chat tag for this warp
|
||||
@tparam string warp_id the uid of the warp you want the chart tag for
|
||||
@@ -83,7 +82,7 @@ local tag_added = Warps.make_warp_tag(warp_id)
|
||||
|
||||
]]
|
||||
function Warps.make_warp_tag(warp_id)
|
||||
local warp = Store.get(warp_store, warp_id)
|
||||
local warp = WrapData:get(warp_id)
|
||||
local name = warp.name
|
||||
local icon = warp.icon
|
||||
|
||||
@@ -120,7 +119,7 @@ local removed = Warps.remove_warp_tag(warp_id)
|
||||
|
||||
]]
|
||||
function Warps.remove_warp_tag(warp_id)
|
||||
local warp = Store.get(warp_store, warp_id)
|
||||
local warp = WrapData:get(warp_id)
|
||||
|
||||
-- Check there is a tag to remove
|
||||
local tag = warp.tag
|
||||
@@ -144,7 +143,7 @@ Warps.make_warp_area(warp_id)
|
||||
|
||||
]]
|
||||
function Warps.make_warp_area(warp_id)
|
||||
local warp = Store.get(warp_store, warp_id)
|
||||
local warp = WrapData:get(warp_id)
|
||||
local surface = warp.surface
|
||||
local position = warp.position
|
||||
local posx = position.x
|
||||
@@ -170,7 +169,7 @@ function Warps.make_warp_area(warp_id)
|
||||
end
|
||||
surface.set_tiles(base_tiles)
|
||||
|
||||
-- Add a tile patern ontop of the base
|
||||
-- Add a tile pattern on top of the base
|
||||
local tiles = {}
|
||||
for _, pos in pairs(config.tiles) do
|
||||
table.insert(tiles, {name=base_tile, position={pos[1]+posx, pos[2]+posy}})
|
||||
@@ -199,7 +198,7 @@ Warps.remove_warp_area(warp_id)
|
||||
|
||||
]]
|
||||
function Warps.remove_warp_area(warp_id)
|
||||
local warp = Store.get(warp_store, warp_id)
|
||||
local warp = WrapData:get(warp_id)
|
||||
local position = warp.position
|
||||
local surface = warp.surface
|
||||
local radius = config.standard_proximity_radius
|
||||
@@ -222,7 +221,7 @@ function Warps.remove_warp_area(warp_id)
|
||||
end
|
||||
surface.set_tiles(tiles)
|
||||
|
||||
-- Remove all the entites that are in the area
|
||||
-- Remove all the entities that are in the area
|
||||
local entities = surface.find_entities_filtered{
|
||||
force='neutral',
|
||||
area={
|
||||
@@ -243,7 +242,7 @@ Warps.set_spawn_warp(warp_id, game.player.force)
|
||||
]]
|
||||
function Warps.set_spawn_warp(warp_id, force)
|
||||
-- Check the force owns this warp
|
||||
local warp = Store.get(warp_store, warp_id)
|
||||
local warp = WrapData:get(warp_id)
|
||||
if warp.force_name ~= force.name then return end
|
||||
|
||||
-- Set this warp as the spawn
|
||||
@@ -267,7 +266,7 @@ Warps.teleport_player(warp_id, game.player)
|
||||
|
||||
]]
|
||||
function Warps.teleport_player(warp_id, player)
|
||||
local warp = Store.get(warp_store, warp_id)
|
||||
local warp = WrapData:get(warp_id)
|
||||
local surface = warp.surface
|
||||
local position = {
|
||||
x=warp.position.x+0.5,
|
||||
@@ -299,7 +298,8 @@ local warp_id = Warps.add_warp(player.force.name, player.surface, player.positio
|
||||
]]
|
||||
function Warps.add_warp(force_name, surface, position, player_name, warp_name)
|
||||
-- Get new warp id
|
||||
local warp_id = tostring(Token.uid())
|
||||
local warp_id = tostring(force_warps._uid)
|
||||
force_warps._uid = force_warps._uid + 1
|
||||
warp_name = warp_name or 'New warp'
|
||||
|
||||
-- Get the existing warps for this force
|
||||
@@ -319,7 +319,7 @@ function Warps.add_warp(force_name, surface, position, player_name, warp_name)
|
||||
end
|
||||
|
||||
-- Add the new warp to the store
|
||||
Store.set(warp_store, warp_id, {
|
||||
WrapData:set(warp_id, {
|
||||
warp_id = warp_id,
|
||||
force_name = force_name,
|
||||
name = warp_name,
|
||||
@@ -345,11 +345,11 @@ Warps.remove_warp(warp_id)
|
||||
|
||||
]]
|
||||
function Warps.remove_warp(warp_id)
|
||||
local warp = Store.get(warp_store, warp_id)
|
||||
local warp = WrapData:get(warp_id)
|
||||
local force_name = warp.force_name
|
||||
Warps.remove_warp_tag(warp_id)
|
||||
Warps.remove_warp_area(warp_id)
|
||||
Store.clear(warp_store, warp_id)
|
||||
WrapData:remove(warp_id)
|
||||
table.remove_element(force_warps[force_name], warp_id)
|
||||
end
|
||||
|
||||
@@ -364,10 +364,9 @@ Warps.update_warp(warp_id, 'My Warp', 'iron-plate', game.player.name)
|
||||
|
||||
]]
|
||||
function Warps.update_warp(warp_id, new_name, new_icon, player_name)
|
||||
Store.update(warp_store, warp_id, function(warp)
|
||||
WrapData:update(warp_id, function(_, warp)
|
||||
warp.last_edit_name = player_name or '<server>'
|
||||
warp.last_edit_time = game.tick
|
||||
warp.old_name = warp.name
|
||||
warp.name = new_name or warp.name
|
||||
warp.icon = new_icon or warp.icon
|
||||
end)
|
||||
@@ -383,7 +382,7 @@ Warps.set_editing(warp_id, game.player.name, true)
|
||||
|
||||
]]
|
||||
function Warps.set_editing(warp_id, player_name, state)
|
||||
Store.update(warp_store, warp_id, function(warp)
|
||||
WrapData:update(warp_id, function(_, warp)
|
||||
warp.currently_editing[player_name] = state
|
||||
end)
|
||||
end
|
||||
@@ -398,7 +397,7 @@ end)
|
||||
|
||||
]]
|
||||
function Warps.on_update(handler)
|
||||
Store.watch(warp_store, handler)
|
||||
WrapData:on_update(handler)
|
||||
end
|
||||
|
||||
--- Getters.
|
||||
@@ -414,7 +413,7 @@ local warp = Warps.get_warp(warp_id)
|
||||
|
||||
]]
|
||||
function Warps.get_warp(warp_id)
|
||||
return Store.get(warp_store, warp_id)
|
||||
return WrapData:get(warp_id)
|
||||
end
|
||||
|
||||
--[[-- Gets all the warp ids that a force has
|
||||
@@ -452,7 +451,7 @@ local editing = Warps.get_editing(warp_id, game.player.name)
|
||||
|
||||
]]
|
||||
function Warps.get_editing(warp_id, player_name)
|
||||
local warp = Store.get(warp_store, warp_id)
|
||||
local warp = WrapData:get(warp_id)
|
||||
return warp.currently_editing[player_name]
|
||||
end
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ if config.DamageDealt then
|
||||
local stat = Statistics:combine('Kills')
|
||||
Event.add(defines.events.on_entity_died, function(event)
|
||||
local character = event.cause -- Check character is valid
|
||||
if not character.valid or character.type ~= 'character' then return end
|
||||
if not character or not character.valid or character.type ~= 'character' then return end
|
||||
local player = character.player -- Check player is valid
|
||||
if not player.valid or not player.connected then return end
|
||||
local entity = event.entity -- Check entity is valid
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
local Gui = require 'utils.gui' --- @dep utils.gui
|
||||
local Store = require 'expcore.store' --- @dep utils.global
|
||||
local Color = require 'utils.color_presets' --- @dep utils.color_presets
|
||||
local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model
|
||||
|
||||
local dump = Model.dump
|
||||
local dump_text = Model.dump_text
|
||||
local concat = table.concat
|
||||
|
||||
local Public = {}
|
||||
|
||||
local header_name = Gui.uid_name()
|
||||
local left_panel_name = Gui.uid_name()
|
||||
local right_panel_name = Gui.uid_name()
|
||||
local input_text_box_name = Gui.uid_name()
|
||||
local refresh_name = Gui.uid_name()
|
||||
|
||||
Public.name = 'Store'
|
||||
|
||||
function Public.show(container)
|
||||
local main_flow = container.add {type = 'flow', direction = 'horizontal'}
|
||||
|
||||
local left_panel = main_flow.add {type = 'scroll-pane', name = left_panel_name}
|
||||
local left_panel_style = left_panel.style
|
||||
left_panel_style.width = 300
|
||||
|
||||
for store_id, file_path in pairs(Store.file_paths) do
|
||||
local header = left_panel.add({type = 'flow'}).add {type = 'label', name = header_name, caption = store_id..' - '..file_path}
|
||||
Gui.set_data(header, store_id)
|
||||
end
|
||||
|
||||
local right_flow = main_flow.add {type = 'flow', direction = 'vertical'}
|
||||
|
||||
local right_top_flow = right_flow.add {type = 'flow', direction = 'horizontal'}
|
||||
|
||||
local input_text_box = right_top_flow.add {type = 'text-box', name = input_text_box_name}
|
||||
local input_text_box_style = input_text_box.style
|
||||
input_text_box_style.horizontally_stretchable = true
|
||||
input_text_box_style.height = 32
|
||||
input_text_box_style.maximal_width = 1000
|
||||
|
||||
local refresh_button =
|
||||
right_top_flow.add {type = 'sprite-button', name = refresh_name, sprite = 'utility/reset', tooltip = 'refresh'}
|
||||
local refresh_button_style = refresh_button.style
|
||||
refresh_button_style.width = 32
|
||||
refresh_button_style.height = 32
|
||||
|
||||
local right_panel = right_flow.add {type = 'text-box', name = right_panel_name}
|
||||
right_panel.read_only = true
|
||||
right_panel.selectable = true
|
||||
|
||||
local right_panel_style = right_panel.style
|
||||
right_panel_style.vertically_stretchable = true
|
||||
right_panel_style.horizontally_stretchable = true
|
||||
right_panel_style.maximal_width = 1000
|
||||
right_panel_style.maximal_height = 1000
|
||||
|
||||
local data = {
|
||||
right_panel = right_panel,
|
||||
input_text_box = input_text_box,
|
||||
selected_header = nil
|
||||
}
|
||||
|
||||
Gui.set_data(input_text_box, data)
|
||||
Gui.set_data(left_panel, data)
|
||||
Gui.set_data(refresh_button, data)
|
||||
end
|
||||
|
||||
Gui.on_click(
|
||||
header_name,
|
||||
function(event)
|
||||
local element = event.element
|
||||
local store_id = Gui.get_data(element)
|
||||
|
||||
local left_panel = element.parent.parent
|
||||
local data = Gui.get_data(left_panel)
|
||||
local right_panel = data.right_panel
|
||||
local selected_header = data.selected_header
|
||||
local input_text_box = data.input_text_box
|
||||
|
||||
if selected_header then
|
||||
selected_header.style.font_color = Color.white
|
||||
end
|
||||
|
||||
element.style.font_color = Color.orange
|
||||
data.selected_header = element
|
||||
|
||||
input_text_box.text = concat {'global.data_store[', store_id, ']'}
|
||||
input_text_box.style.font_color = Color.black
|
||||
|
||||
local content = dump(Store.get(store_id)) or 'nil'
|
||||
right_panel.text = content
|
||||
end
|
||||
)
|
||||
|
||||
local function update_dump(text_input, data, player)
|
||||
local suc, ouput = dump_text(text_input.text, player)
|
||||
if not suc then
|
||||
text_input.style.font_color = Color.red
|
||||
else
|
||||
text_input.style.font_color = Color.black
|
||||
data.right_panel.text = ouput
|
||||
end
|
||||
end
|
||||
|
||||
Gui.on_text_changed(
|
||||
input_text_box_name,
|
||||
function(event)
|
||||
local element = event.element
|
||||
local data = Gui.get_data(element)
|
||||
|
||||
update_dump(element, data, event.player)
|
||||
end
|
||||
)
|
||||
|
||||
Gui.on_click(
|
||||
refresh_name,
|
||||
function(event)
|
||||
local element = event.element
|
||||
local data = Gui.get_data(element)
|
||||
|
||||
local input_text_box = data.input_text_box
|
||||
|
||||
update_dump(input_text_box, data, event.player)
|
||||
end
|
||||
)
|
||||
|
||||
return Public
|
||||
@@ -6,7 +6,6 @@ local Public = {}
|
||||
local pages = {
|
||||
require 'modules.gui.debug.redmew_global_view',
|
||||
require 'modules.gui.debug.expcore_datastore_view',
|
||||
require 'modules.gui.debug.expcore_store_view',
|
||||
require 'modules.gui.debug.expcore_gui_view',
|
||||
require 'modules.gui.debug.global_view',
|
||||
require 'modules.gui.debug.package_view',
|
||||
|
||||
@@ -7,25 +7,21 @@
|
||||
-- luacheck:ignore 211/Colors
|
||||
local Gui = require 'expcore.gui' --- @dep expcore.gui
|
||||
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
||||
local Store = require 'expcore.store' --- @dep expcore.store
|
||||
local Datastore = require 'expcore.datastore' --- @dep expcore.datastore
|
||||
local Game = require 'utils.game' --- @dep utils.game
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local config = require 'config.gui.player_list_actions' --- @dep config.gui.player_list_actions
|
||||
local Colors = require 'utils.color_presets' --- @dep utils.color_presets
|
||||
local format_time = _C.format_time --- @dep expcore.common
|
||||
|
||||
-- Stores the name of the player a player has selected
|
||||
local selected_player_store = Store.register(function(player)
|
||||
return player.name
|
||||
end)
|
||||
|
||||
-- Stores the current action that a player wants to do
|
||||
local selected_action_store = Store.register(function(player)
|
||||
return player.name
|
||||
end)
|
||||
--- Stores all data for the warp gui
|
||||
local PlayerListData = Datastore.connect('PlayerListData')
|
||||
PlayerListData:set_serializer(Datastore.name_serializer)
|
||||
local SelectedPlayer = PlayerListData:combine('SelectedPlayer')
|
||||
local SelectedAction = PlayerListData:combine('SelectedAction')
|
||||
|
||||
-- Set the config to use these stores
|
||||
config.set_store_uids(selected_player_store, selected_action_store)
|
||||
config.set_datastores(SelectedPlayer, SelectedAction)
|
||||
|
||||
--- Button used to open the action bar
|
||||
-- @element open_action_bar
|
||||
@@ -43,11 +39,11 @@ Gui.element{
|
||||
}
|
||||
:on_click(function(player, element, _)
|
||||
local selected_player_name = element.parent.name
|
||||
local old_selected_player_name = Store.get(selected_player_store, player)
|
||||
local old_selected_player_name = SelectedPlayer:get(player)
|
||||
if selected_player_name == old_selected_player_name then
|
||||
Store.clear(selected_player_store, player)
|
||||
SelectedPlayer:remove(player)
|
||||
else
|
||||
Store.set(selected_player_store, player, selected_player_name)
|
||||
SelectedPlayer:set(player, selected_player_name)
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -62,8 +58,8 @@ Gui.element{
|
||||
}
|
||||
:style(Gui.sprite_style(30, -1, { top_margin = -1, right_margin = -1 }))
|
||||
:on_click(function(player, _)
|
||||
Store.clear(selected_player_store, player)
|
||||
Store.clear(selected_action_store, player)
|
||||
SelectedPlayer:remove(player)
|
||||
SelectedAction:remove(player)
|
||||
end)
|
||||
|
||||
--- Button used to confirm a reason
|
||||
@@ -78,11 +74,11 @@ Gui.element{
|
||||
:style(Gui.sprite_style(30, -1, { left_margin = -2, right_margin = -1 }))
|
||||
:on_click(function(player, element)
|
||||
local reason = element.parent.entry.text or 'Non Given'
|
||||
local action_name = Store.get(selected_action_store, player)
|
||||
local action_name = SelectedAction:get(player)
|
||||
local reason_callback = config.buttons[action_name].reason_callback
|
||||
reason_callback(player, reason)
|
||||
Store.clear(selected_player_store, player)
|
||||
Store.clear(selected_action_store, player)
|
||||
SelectedPlayer:remove(player)
|
||||
SelectedAction:remove(player)
|
||||
element.parent.entry.text = ''
|
||||
end)
|
||||
|
||||
@@ -126,12 +122,12 @@ end)
|
||||
event.player.zoom_to_world(position, 1.75)
|
||||
else
|
||||
-- RMB will toggle the settings
|
||||
local old_selected_player_name = Store.get(selected_player_store, player)
|
||||
local old_selected_player_name = SelectedPlayer:get(player)
|
||||
if selected_player_name == old_selected_player_name then
|
||||
Store.clear(selected_player_store, player)
|
||||
Store.clear(selected_action_store, player)
|
||||
SelectedPlayer:remove(player)
|
||||
SelectedAction:remove(player)
|
||||
else
|
||||
Store.set(selected_player_store, player, selected_player_name)
|
||||
SelectedPlayer:set(player, selected_player_name)
|
||||
end
|
||||
end
|
||||
end)
|
||||
@@ -174,7 +170,7 @@ end)
|
||||
--- Updates the visible state of the action bar buttons
|
||||
local function update_action_bar(element)
|
||||
local player = Gui.get_player_from_element(element)
|
||||
local selected_player_name = Store.get(selected_player_store, player)
|
||||
local selected_player_name = SelectedPlayer:get(player)
|
||||
|
||||
if not selected_player_name then
|
||||
-- Hide the action bar when no player is selected
|
||||
@@ -185,8 +181,8 @@ local function update_action_bar(element)
|
||||
if not selected_player.connected then
|
||||
-- If the player is offline then reest stores
|
||||
element.visible = false
|
||||
Store.clear(selected_player_store, player)
|
||||
Store.clear(selected_action_store, player)
|
||||
SelectedPlayer:remove(player)
|
||||
SelectedAction:remove(player)
|
||||
|
||||
else
|
||||
-- Otherwise check what actions the player is allowed to use
|
||||
@@ -367,10 +363,10 @@ Event.add(defines.events.on_player_left_game, function(event)
|
||||
local scroll_table = frame.container.scroll.table
|
||||
remove_player_base(scroll_table, remove_player)
|
||||
|
||||
local selected_player_name = Store.get(selected_player_store, player)
|
||||
local selected_player_name = SelectedPlayer:get(player)
|
||||
if selected_player_name == remove_player.name then
|
||||
Store.clear(selected_player_store, player)
|
||||
Store.clear(selected_action_store, player)
|
||||
SelectedPlayer:remove(player)
|
||||
SelectedAction:remove(player)
|
||||
end
|
||||
end
|
||||
end)
|
||||
@@ -393,7 +389,7 @@ Event.add(Roles.events.on_role_assigned, redraw_player_list)
|
||||
Event.add(Roles.events.on_role_unassigned, redraw_player_list)
|
||||
|
||||
--- When the action player is changed the action bar will update
|
||||
Store.watch(selected_player_store, function(value, player_name)
|
||||
SelectedPlayer:on_update(function(player_name, selected_player)
|
||||
local player = Game.get_player_from_any(player_name)
|
||||
local frame = Gui.get_left_element(player, player_list_container)
|
||||
local scroll_table = frame.container.scroll.table
|
||||
@@ -401,7 +397,7 @@ Store.watch(selected_player_store, function(value, player_name)
|
||||
for _, next_player in pairs(game.connected_players) do
|
||||
local element = scroll_table[next_player.name][open_action_bar.name]
|
||||
local style = 'frame_button'
|
||||
if next_player.name == value then
|
||||
if next_player.name == selected_player then
|
||||
style = 'tool_button'
|
||||
end
|
||||
element.style = style
|
||||
@@ -413,20 +409,20 @@ Store.watch(selected_player_store, function(value, player_name)
|
||||
end)
|
||||
|
||||
--- When the action name is changed the reason input will update
|
||||
Store.watch(selected_action_store, function(value, player_name)
|
||||
SelectedAction:on_update(function(player_name, selected_action)
|
||||
local player = Game.get_player_from_any(player_name)
|
||||
local frame = Gui.get_left_element(player, player_list_container)
|
||||
local element = frame.container.reason_bar
|
||||
if value then
|
||||
if selected_action then
|
||||
-- if there is a new value then check the player is still online
|
||||
local selected_player_name = Store.get(selected_player_store, player_name)
|
||||
local selected_player_name = SelectedPlayer:get(player_name)
|
||||
local selected_player = Game.get_player_from_any(selected_player_name)
|
||||
if selected_player.connected then
|
||||
element.visible = true
|
||||
else
|
||||
-- Clear if the player is offline
|
||||
Store.clear(selected_player_store, player_name)
|
||||
Store.clear(selected_action_store, player_name)
|
||||
SelectedPlayer:remove(player)
|
||||
SelectedAction:remove(player)
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
@@ -240,7 +240,7 @@ local function update_task(player, task_table, task_id)
|
||||
-- Update the edit flow
|
||||
local edit_flow = task_table['edit-'..task_id]
|
||||
local player_allowed_edit = check_player_permissions(player, task)
|
||||
local players_editing = table.get_keys(task.curently_editing)
|
||||
local players_editing = table.get_keys(task.currently_editing)
|
||||
local edit_task_element = edit_flow[edit_task.name]
|
||||
local discard_task_element = edit_flow[discard_task.name]
|
||||
|
||||
@@ -257,7 +257,7 @@ local function update_task(player, task_table, task_id)
|
||||
-- Check if the player is was editing and/or currently editing
|
||||
local task_entry = task_flow[task_editing.name] or task_label(task_flow, task)
|
||||
local player_was_editing = task_entry.type == 'textfield'
|
||||
local player_is_editing = task.curently_editing[player.name]
|
||||
local player_is_editing = task.currently_editing[player.name]
|
||||
|
||||
-- Update the task flow
|
||||
if not player_was_editing and not player_is_editing then
|
||||
@@ -361,14 +361,14 @@ Gui.left_toolbar_button('utility/not_enough_repair_packs_icon', {'task-list.main
|
||||
return Roles.player_allowed(player, 'gui/task-list')
|
||||
end)
|
||||
|
||||
--- When a new task is added it will udpate the task list for everyone on that force
|
||||
Tasks.on_update(function(task, task_id, removed_task)
|
||||
--- When a new task is added it will update the task list for everyone on that force
|
||||
Tasks.on_update(function(task_id, task, old_task)
|
||||
-- Get the force to update, task is nil when removed
|
||||
local force
|
||||
if task then
|
||||
force = game.forces[task.force_name]
|
||||
else
|
||||
force = game.forces[removed_task.force_name]
|
||||
force = game.forces[old_task.force_name]
|
||||
end
|
||||
|
||||
-- Update the task for all the players on the force
|
||||
|
||||
@@ -5,33 +5,30 @@
|
||||
]]
|
||||
|
||||
local Gui = require 'expcore.gui' --- @dep expcore.gui
|
||||
local Store = require 'expcore.store' --- @dep expcore.store
|
||||
local Datastore = require 'expcore.datastore' --- @dep expcore.datastore
|
||||
local Global = require 'utils.global' --- @dep utils.global
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local Game = require 'utils.game' --- @dep utils.game
|
||||
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
||||
local Colors = require 'utils.color_presets' --- @dep utils.color_presets
|
||||
local config = require 'config.gui.warps' --- @dep config.gui.warps
|
||||
local Warps = require 'modules.control.warps' --- @dep modules.control.warps
|
||||
local format_time = _C.format_time --- @dep expcore.common
|
||||
|
||||
-- Stores a boolean value indexed by player name
|
||||
local player_in_range_store = Store.register(function(player)
|
||||
return player.name
|
||||
end)
|
||||
--- Stores all data for the warp gui
|
||||
local WrapGuiData = Datastore.connect('WrapGuiData')
|
||||
WrapGuiData:set_serializer(Datastore.name_serializer)
|
||||
local PlayerInRange = WrapGuiData:combine('PlayerInRange')
|
||||
PlayerInRange:set_default(false)
|
||||
local PlayerCooldown = WrapGuiData:combine('PlayerCooldown')
|
||||
PlayerCooldown:set_default(0)
|
||||
|
||||
-- Stores the time remaing for a players warp cooldown
|
||||
local player_warp_cooldown_store = Store.register(function(player)
|
||||
return player.name
|
||||
end)
|
||||
|
||||
-- Table that stores a boolean value of weather to keep the warp gui open
|
||||
--- Table that stores a boolean value of weather to keep the warp gui open
|
||||
local keep_gui_open = {}
|
||||
Global.register(keep_gui_open, function(tbl)
|
||||
keep_gui_open = tbl
|
||||
end)
|
||||
|
||||
-- Styles used for sprite buttons
|
||||
--- Styles used for sprite buttons
|
||||
local Styles = {
|
||||
sprite20 = Gui.sprite_style(20),
|
||||
sprite22 = Gui.sprite_style(20, nil, { right_margin = -3 }),
|
||||
@@ -55,7 +52,7 @@ local function check_player_permissions(player, action, warp)
|
||||
end
|
||||
end
|
||||
|
||||
-- Check player has permisison based on value in the config
|
||||
-- Check player has permission based on value in the config
|
||||
local action_config = config[action]
|
||||
if action_config == 'all' then
|
||||
return true
|
||||
@@ -65,7 +62,7 @@ local function check_player_permissions(player, action, warp)
|
||||
return Roles.player_allowed(player, config['expcore_roles_'..action])
|
||||
end
|
||||
|
||||
-- Return false as all other condidtions have not been met
|
||||
-- Return false as all other conditions have not been met
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -187,7 +184,7 @@ Gui.element{
|
||||
Warps.set_editing(warp_id, player.name)
|
||||
end)
|
||||
|
||||
--- Editing state for a warp, contrins a text field and the two edit buttons
|
||||
--- Editing state for a warp, contains a text field and the two edit buttons
|
||||
-- @element warp_editing
|
||||
warp_editing =
|
||||
Gui.element(function(event_trigger, parent, warp)
|
||||
@@ -246,7 +243,7 @@ end)
|
||||
player.zoom_to_world(position, 1.5)
|
||||
end)
|
||||
|
||||
|
||||
local update_wrap_buttons
|
||||
--- Default state for the warp icon, when pressed teleports the player
|
||||
-- @element warp_icon_button
|
||||
warp_icon_button =
|
||||
@@ -269,8 +266,8 @@ end)
|
||||
|
||||
-- Reset the warp cooldown if the player does not have unlimited warps
|
||||
if not check_player_permissions(player, 'bypass_warp_cooldown') then
|
||||
Store.set(player_warp_cooldown_store, player, config.cooldown_duraction)
|
||||
Store.trigger(player_in_range_store, player)
|
||||
PlayerCooldown:set(player, config.cooldown_duration)
|
||||
update_wrap_buttons(player)
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -293,15 +290,43 @@ end)
|
||||
local warp_timer =
|
||||
Gui.element{
|
||||
type = 'progressbar',
|
||||
tooltip = {'warp-list.timer-tooltip', config.cooldown_duraction},
|
||||
tooltip = {'warp-list.timer-tooltip', config.cooldown_duration},
|
||||
minimum_value = 0,
|
||||
maximum_value = config.cooldown_duraction*config.update_smoothing
|
||||
maximum_value = config.cooldown_duration*config.update_smoothing
|
||||
}
|
||||
:style{
|
||||
horizontally_stretchable = true,
|
||||
color = Colors.light_blue
|
||||
}
|
||||
|
||||
local warp_list_container
|
||||
--- Update the warp buttons for a player
|
||||
function update_wrap_buttons(player, timer, in_range)
|
||||
-- Get the warp table
|
||||
local frame = Gui.get_left_element(player, warp_list_container)
|
||||
local scroll_table = frame.container.scroll.table
|
||||
|
||||
-- Check if the buttons should be active
|
||||
timer = timer or PlayerCooldown:get(player)
|
||||
in_range = in_range or PlayerInRange:get(player)
|
||||
local button_disabled = timer > 0 or not in_range
|
||||
|
||||
-- Change the enabled state of the warp buttons
|
||||
local warp_ids = Warps.get_force_warp_ids(player.force.name)
|
||||
for _, warp_id in pairs(warp_ids) do
|
||||
local element = scroll_table['icon-'..warp_id][warp_icon_button.name]
|
||||
if element and element.valid then
|
||||
element.enabled = not button_disabled
|
||||
if button_disabled then
|
||||
element.tooltip = {'warp-list.goto-disabled'}
|
||||
else
|
||||
local position = Warps.get_warp(warp_id).position
|
||||
element.tooltip = {'warp-list.goto-tooltip', position.x, position.y}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Updates a warp for a player
|
||||
local function update_warp(player, warp_table, warp_id)
|
||||
local warp = Warps.get_warp(warp_id)
|
||||
@@ -358,10 +383,10 @@ local function update_warp(player, warp_table, warp_id)
|
||||
|
||||
icon_flow.clear()
|
||||
local warp_icon_element = warp_icon_button(icon_flow, warp)
|
||||
local timer = Store.get(player_warp_cooldown_store, player)
|
||||
local in_range = Store.get(player_in_range_store, player)
|
||||
local timer = PlayerCooldown:get(player)
|
||||
local in_range = PlayerInRange:get(player)
|
||||
local apply_proximity = not check_player_permissions(player, 'bypass_warp_proximity')
|
||||
if (timer and timer > 0) or (apply_proximity and not in_range) then
|
||||
if timer > 0 or (apply_proximity and not in_range) then
|
||||
warp_icon_element.enabled = false
|
||||
warp_icon_element.tooltip = {'warp-list.goto-disabled'}
|
||||
end
|
||||
@@ -381,7 +406,20 @@ end
|
||||
-- Update all the warps for a player
|
||||
local function update_all_warps(player, warp_table)
|
||||
local warp_ids = Warps.get_force_warp_ids(player.force.name)
|
||||
if #warp_ids > 0 then
|
||||
warp_table.clear()
|
||||
for _, warp_id in ipairs(warp_ids) do
|
||||
update_warp(player, warp_table, warp_id)
|
||||
end
|
||||
end
|
||||
|
||||
-- Update all warps for all players on a force
|
||||
local function update_all_wrap_force(force)
|
||||
local warp_ids = Warps.get_force_warp_ids(force.name)
|
||||
for _, player in pairs(force.connected_players) do
|
||||
local frame = Gui.get_left_element(player, warp_list_container)
|
||||
local warp_table = frame.container.scroll.table
|
||||
|
||||
warp_table.clear()
|
||||
for _, warp_id in ipairs(warp_ids) do
|
||||
update_warp(player, warp_table, warp_id)
|
||||
end
|
||||
@@ -390,7 +428,7 @@ end
|
||||
|
||||
--- Main warp list container for the left flow
|
||||
-- @element warp_list_container
|
||||
local warp_list_container =
|
||||
warp_list_container =
|
||||
Gui.element(function(event_trigger, parent)
|
||||
-- Draw the internal container
|
||||
local container = Gui.container(parent, event_trigger, 200)
|
||||
@@ -399,7 +437,7 @@ Gui.element(function(event_trigger, parent)
|
||||
local header = Gui.header(
|
||||
container,
|
||||
{'warp-list.main-caption'},
|
||||
{'warp-list.sub-tooltip', config.cooldown_duraction, config.standard_proximity_radius},
|
||||
{'warp-list.sub-tooltip', config.cooldown_duration, config.standard_proximity_radius},
|
||||
true
|
||||
)
|
||||
|
||||
@@ -421,16 +459,16 @@ Gui.element(function(event_trigger, parent)
|
||||
|
||||
-- Change the progress of the warp timer
|
||||
local progress = 1
|
||||
local timer = Store.get(player_warp_cooldown_store, player)
|
||||
if timer and timer > 0 then
|
||||
progress = 1 - (timer/config.cooldown_duraction)
|
||||
local timer = PlayerCooldown:get(player)
|
||||
if timer > 0 then
|
||||
progress = 1 - (timer/config.cooldown_duration)
|
||||
end
|
||||
warp_timer_element.value = progress
|
||||
|
||||
-- Add any existing warps
|
||||
update_all_warps(player, scroll_table)
|
||||
|
||||
-- Return the exteral container
|
||||
-- Return the external container
|
||||
return container.parent
|
||||
end)
|
||||
:add_to_left_flow()
|
||||
@@ -446,26 +484,140 @@ end)
|
||||
end)
|
||||
|
||||
--- When the name of a warp is updated this is triggered
|
||||
Warps.on_update(function(warp, _,removed_warp)
|
||||
Warps.on_update(function(_, warp, old_warp)
|
||||
-- Get the force to update, warp is nil when removed
|
||||
local force
|
||||
if warp then
|
||||
force = game.forces[warp.force_name]
|
||||
update_all_wrap_force(game.forces[warp.force_name])
|
||||
else
|
||||
force = game.forces[removed_warp.force_name]
|
||||
update_all_wrap_force(game.forces[old_warp.force_name])
|
||||
end
|
||||
end)
|
||||
|
||||
--- When the player leaves or enters range of a warp this is triggered
|
||||
PlayerInRange:on_update(function(player_name, player_in_range)
|
||||
local player = game.players[player_name]
|
||||
|
||||
-- Change if the frame is visible based on if the player is in range
|
||||
if not keep_gui_open[player.name] then
|
||||
Gui.toggle_left_element(player, warp_list_container, player_in_range)
|
||||
end
|
||||
|
||||
-- Update the gui for selected players
|
||||
local warp_ids = Warps.get_force_warp_ids(force.name)
|
||||
for _, player in pairs(force.connected_players) do
|
||||
local frame = Gui.get_left_element(player, warp_list_container)
|
||||
local scroll_table = frame.container.scroll.table
|
||||
-- Check if the player requires proximity
|
||||
if not check_player_permissions(player, 'bypass_warp_proximity') then
|
||||
update_wrap_buttons(player, nil, player_in_range)
|
||||
end
|
||||
end)
|
||||
|
||||
-- Update the gui
|
||||
scroll_table.clear()
|
||||
for _, next_warp_id in ipairs(warp_ids) do
|
||||
update_warp(player, scroll_table, next_warp_id)
|
||||
--- Update the warp cooldown progress bars to match the current cooldown
|
||||
PlayerCooldown:on_update(function(player_name, player_cooldown)
|
||||
-- Get the progress bar element
|
||||
local player = game.players[player_name]
|
||||
local frame = Gui.get_left_element(player, warp_list_container)
|
||||
local warp_timer_element = frame.container[warp_timer.name]
|
||||
|
||||
-- Set the progress
|
||||
local progress = 1
|
||||
if player_cooldown and player_cooldown > 0 then
|
||||
progress = 1 - (player_cooldown/config.cooldown_duration)
|
||||
end
|
||||
warp_timer_element.value = progress
|
||||
|
||||
-- Trigger update of buttons if cooldown is now 0
|
||||
if player_cooldown == 0 then
|
||||
update_wrap_buttons(player, player_cooldown, nil)
|
||||
end
|
||||
end)
|
||||
|
||||
--- Handles updating the timer and checking distance from a warp
|
||||
local r2 = config.standard_proximity_radius^2
|
||||
local rs2 = config.spawn_proximity_radius^2
|
||||
local mr2 = config.minimum_distance^2
|
||||
Event.on_nth_tick(math.floor(60/config.update_smoothing), function()
|
||||
PlayerCooldown:update_all(function(_, player_cooldown)
|
||||
if player_cooldown > 0 then return player_cooldown - 1 end
|
||||
end)
|
||||
|
||||
local force_warps = {}
|
||||
local warps = {}
|
||||
for _, player in pairs(game.connected_players) do
|
||||
local was_in_range = PlayerInRange:get(player)
|
||||
|
||||
-- Get the ids of all the warps on the players force
|
||||
local force_name = player.force.name
|
||||
local warp_ids = force_warps[force_name]
|
||||
if not warp_ids then
|
||||
warp_ids = Warps.get_force_warp_ids(force_name)
|
||||
force_warps[force_name] = warp_ids
|
||||
end
|
||||
|
||||
-- Check if the force has any warps
|
||||
local closest_warp
|
||||
local closest_distance
|
||||
if #warp_ids > 0 then
|
||||
local surface = player.surface
|
||||
local pos = player.position
|
||||
local px, py = pos.x, pos.y
|
||||
|
||||
-- Loop over each warp
|
||||
for _, warp_id in ipairs(warp_ids) do
|
||||
-- Check if warp id is cached
|
||||
local warp = warps[warp_id]
|
||||
if not warp then
|
||||
warp = Warps.get_warp(warp_id)
|
||||
warps[warp_id] = warp
|
||||
end
|
||||
|
||||
-- Check if the player is within range
|
||||
local warp_pos = warp.position
|
||||
if warp.surface == surface then
|
||||
local dx, dy = px-warp_pos.x, py-warp_pos.y
|
||||
local dist = (dx*dx)+(dy*dy)
|
||||
if closest_distance == nil or dist < closest_distance then
|
||||
closest_warp = warp
|
||||
closest_distance = dist
|
||||
if dist < r2 then break end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Check the dist to the closest warp
|
||||
local in_range = closest_warp.warp_id == warp_ids.spawn and closest_distance < rs2 or closest_distance < r2
|
||||
if was_in_range and not in_range then
|
||||
PlayerInRange:set(player, false)
|
||||
elseif not was_in_range and in_range then
|
||||
PlayerInRange:set(player, true)
|
||||
end
|
||||
|
||||
-- Change the enabled state of the add warp button
|
||||
local frame = Gui.get_left_element(player, warp_list_container)
|
||||
local add_warp_element = frame.container.header.alignment[add_new_warp.name]
|
||||
local was_able_to_make_warp = add_warp_element.enabled
|
||||
local can_make_warp = closest_distance > mr2
|
||||
if can_make_warp and not was_able_to_make_warp then
|
||||
add_warp_element.enabled = true
|
||||
add_warp_element.tooltip = {'warp-list.add-tooltip'}
|
||||
elseif not can_make_warp and was_able_to_make_warp then
|
||||
add_warp_element.enabled = false
|
||||
add_warp_element.tooltip = {'warp-list.too-close', closest_warp.name}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
--- When a player is created make sure that there is a spawn warp created
|
||||
Event.add(defines.events.on_player_created, function(event)
|
||||
-- If the force has no spawn then make a spawn warp
|
||||
local player = game.players[event.player_index]
|
||||
local force = player.force
|
||||
local spawn_id = Warps.get_spawn_warp_id(force.name)
|
||||
if not spawn_id then
|
||||
local spawn_position = force.get_spawn_position(player.surface)
|
||||
spawn_id = Warps.add_warp(force.name, player.surface, spawn_position, nil, 'Spawn')
|
||||
Warps.set_spawn_warp(spawn_id, force)
|
||||
Warps.make_warp_tag(spawn_id)
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -494,163 +646,6 @@ end
|
||||
Event.add(Roles.events.on_role_assigned, role_update_event)
|
||||
Event.add(Roles.events.on_role_unassigned, role_update_event)
|
||||
|
||||
--- When the player leaves or enters range of a warp this is triggered
|
||||
Store.watch(player_in_range_store, function(value, player_name)
|
||||
local player = game.players[player_name]
|
||||
local force = player.force
|
||||
|
||||
-- Change if the frame is visible based on if the player is in range
|
||||
if not keep_gui_open[player.name] then
|
||||
Gui.toggle_left_element(player, warp_list_container, value)
|
||||
end
|
||||
|
||||
-- Check if the player requires proximity
|
||||
if check_player_permissions(player, 'bypass_warp_proximity') then
|
||||
return
|
||||
end
|
||||
|
||||
-- Get the warp table
|
||||
local frame = Gui.get_left_element(player, warp_list_container)
|
||||
local scroll_table = frame.container.scroll.table
|
||||
|
||||
-- Check if the buttons should be active
|
||||
local timer = Store.get(player_warp_cooldown_store, player)
|
||||
local button_disabled = timer and timer > 0 or not value
|
||||
|
||||
-- Change the enabled state of the warp buttons
|
||||
local warp_ids = Warps.get_force_warp_ids(force.name)
|
||||
for _, warp_id in pairs(warp_ids) do
|
||||
local element = scroll_table['icon-'..warp_id][warp_icon_button.name]
|
||||
if element and element.valid then
|
||||
element.enabled = not button_disabled
|
||||
if button_disabled then
|
||||
element.tooltip = {'warp-list.goto-disabled'}
|
||||
else
|
||||
local position = Warps.get_warp(warp_id).position
|
||||
element.tooltip = {'warp-list.goto-tooltip', position.x, position.y}
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
--- Update the warp cooldown progress bars to match the store
|
||||
Store.watch(player_warp_cooldown_store, function(value, player_name, old_value)
|
||||
if value == old_value then return end
|
||||
-- Get the progress bar element
|
||||
local player = game.players[player_name]
|
||||
local frame = Gui.get_left_element(player, warp_list_container)
|
||||
local warp_timer_element = frame.container[warp_timer.name]
|
||||
|
||||
-- Set the progress
|
||||
local progress = 1
|
||||
local timer = Store.get(player_warp_cooldown_store, player)
|
||||
if timer and timer > 0 then
|
||||
progress = 1 - (timer/config.cooldown_duraction)
|
||||
end
|
||||
warp_timer_element.value = progress
|
||||
|
||||
-- Trigger update of buttons if cooldown is now 0
|
||||
if value == 0 then
|
||||
Store.trigger(player_in_range_store, player_name)
|
||||
end
|
||||
end)
|
||||
|
||||
--- Handles updating the timer and checking distance from a warp
|
||||
local r2 = config.standard_proximity_radius^2
|
||||
local rs2 = config.spawn_proximity_radius^2
|
||||
local mr2 = config.minimum_distance^2
|
||||
Event.on_nth_tick(math.floor(60/config.update_smoothing), function()
|
||||
Store.map(player_warp_cooldown_store, function(value)
|
||||
if value > 0 then
|
||||
return value - 1
|
||||
end
|
||||
end)
|
||||
|
||||
local force_warps = {}
|
||||
local warps = {}
|
||||
for _, player in pairs(game.connected_players) do
|
||||
local was_in_range = Store.get(player_in_range_store, player)
|
||||
|
||||
-- Get the ids of all the warps on the players force
|
||||
local force_name = player.force.name
|
||||
local warp_ids = force_warps[force_name]
|
||||
if not warp_ids then
|
||||
warp_ids = Warps.get_force_warp_ids(force_name)
|
||||
force_warps[force_name] = warp_ids
|
||||
end
|
||||
|
||||
-- Check if the force has any warps
|
||||
local closest_warp
|
||||
local closest_distance
|
||||
if #warp_ids > 0 then
|
||||
local surface = player.surface
|
||||
local pos = player.position
|
||||
local px, py = pos.x, pos.y
|
||||
|
||||
-- Loop over each warp
|
||||
for _, warp_id in ipairs(warp_ids) do
|
||||
-- Check if warp id is chached
|
||||
local warp = warps[warp_id]
|
||||
if not warp then
|
||||
warp = Warps.get_warp(warp_id)
|
||||
warps[warp_id] = warp
|
||||
end
|
||||
|
||||
-- Check if the player is within range
|
||||
local warp_pos = warp.position
|
||||
if warp.surface == surface then
|
||||
local dx, dy = px-warp_pos.x, py-warp_pos.y
|
||||
local dist = (dx*dx)+(dy*dy)
|
||||
if closest_distance == nil or dist < closest_distance then
|
||||
closest_warp = warp
|
||||
closest_distance = dist
|
||||
if dist < r2 then break end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Check the dist to the closest warp
|
||||
local in_range = closest_warp.warp_id == warp_ids.spawn and closest_distance < rs2 or closest_distance < r2
|
||||
if was_in_range and not in_range then
|
||||
Store.set(player_in_range_store, player, false)
|
||||
elseif not was_in_range and in_range then
|
||||
Store.set(player_in_range_store, player, true)
|
||||
end
|
||||
|
||||
-- Change the enabled state of the add warp button
|
||||
local frame = Gui.get_left_element(player, warp_list_container)
|
||||
local add_warp_element = frame.container.header.alignment[add_new_warp.name]
|
||||
local was_able_to_make_warp = add_warp_element.enabled
|
||||
local can_make_warp = closest_distance > mr2
|
||||
if can_make_warp and not was_able_to_make_warp then
|
||||
add_warp_element.enabled = true
|
||||
add_warp_element.tooltip = {'warp-list.add-tooltip'}
|
||||
elseif not can_make_warp and was_able_to_make_warp then
|
||||
add_warp_element.enabled = false
|
||||
add_warp_element.tooltip = {'warp-list.too-close', closest_warp.name}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
--- When a player is created make sure that there is a spawn warp created
|
||||
Event.add(defines.events.on_player_created, function(event)
|
||||
-- If the force has no spawn then make a spawn warp
|
||||
local player = Game.get_player_by_index(event.player_index)
|
||||
local force = player.force
|
||||
local spawn_id = Warps.get_spawn_warp_id(force.name)
|
||||
if not spawn_id then
|
||||
local spawn_position = force.get_spawn_position(player.surface)
|
||||
spawn_id = Warps.add_warp(force.name, player.surface, spawn_position, nil, 'Spawn')
|
||||
Warps.set_spawn_warp(spawn_id, force)
|
||||
Store.trigger(Warps.store, spawn_id)
|
||||
Warps.make_warp_tag(spawn_id)
|
||||
end
|
||||
end)
|
||||
|
||||
--- When a chart tag is removed or edited make sure it is not one that belongs to a warp
|
||||
local function maintain_tag(event)
|
||||
if not event.player_index then return end
|
||||
@@ -659,8 +654,8 @@ local function maintain_tag(event)
|
||||
local warp_ids = Warps.get_force_warp_ids(force_name)
|
||||
for _, warp_id in pairs(warp_ids) do
|
||||
local warp = Warps.get_warp(warp_id)
|
||||
local wtag = warp.tag
|
||||
if not wtag or not wtag.valid or wtag == tag then
|
||||
local warp_tag = warp.tag
|
||||
if not warp_tag or not warp_tag.valid or warp_tag == tag then
|
||||
if event.name == defines.events.on_chart_tag_removed then
|
||||
warp.tag = nil
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user