## Store core

Core Module - Store - Used to store and watch for updates for values in the global table

### 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)

    -- 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)

### Dependencies

utils.event

### Tables

serializers | An array of the serializers that stores are using, key is store uids
watchers | An array of watchers that stores will trigger, key is store uids
file_paths | An index used for debuging to find the file where different stores where registered

### Fields

uid | The current highest uid that is being used, will not increase during runtime

### Store Setup

validate(store[, key][, error_stack=1]) | An error checking and serializing function for checking store uids and keys, note key is not required
register([serializer]) | Required to create new stores and register an serializer to a store, serializer not required
watch(store, watcher) | Register a watch function to a store that is called when the value in the store is changed, triggers for any key

### Store Data Management

get(store[, key]) | Used to retrive the current data that is stored, key is optional depending on if you are using them
clear(store[, key]) | Used to clear the data in a store, will trigger any watchers, key is optional depending on if you are using them
set(store[, key], value) | Used to set the data in a store, will trigger any watchers, key is optional depending on if you are using them
update(store[, key], updater) | 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
map(store, updater) | 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
trigger(store[, key]) | Used to trigger watcher functions, this may be used to trigger them if you did not use Store.update or Store.set
raw_trigger(store[, key][, value][, old_value]) | Used to trigger watcher functions, the value and key are passed directly to the watchers regardless if the value is correct

### Dependencies

# utils.event

### Tables

# serializers

  An array of the serializers that stores are using, key is store uids

# watchers

  An array of watchers that stores will trigger, key is store uids

# file_paths

  An index used for debuging to find the file where different stores where registered

### Fields

# uid

  The current highest uid that is being used, will not increase during runtime

  - uid

### Store Setup

# validate(store[, key][, error_stack=1])

  An error checking and serializing function for checking store uids and keys, note key is not required

  Parameters:
  - store : (number) the uid of the store that you want to check is valid
  - key : (string or any) the key that you want to serialize or check is a string (optional)
  - error_stack : (number) the position in the stack relative to the current function (1) to raise this error on (default: 1)
  Returns:
  - (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)

# register([serializer])

  Required to create new stores and register an serializer to a store, serializer not required

  Parameters:
  - serializer : (function) the function used to convert non string keys into strings to be used in the store (optional)
  Returns:
  - (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()

      -- Creating a store which can take LuaPlayer
      local player_scores = Store.register(function(player)
          return player.name
      end)

# watch(store, watcher)

  Register a watch function to a store that is called when the value in the store is changed, triggers for any key

  Parameters:
  - store : (number) the uid of the store that you want to watch for changes to
  - watcher : (function) 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')

      -- 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)

### Store Data Management

# get(store[, key])

  Used to retrive the current data that is stored, key is optional depending on if you are using them

  Parameters:
  - store : (number) the uid of the store that you want to get the value from
  - key : (string or any) the key that you want to get the value of, must be a string unless you have a serializer (optional)
  Returns:
  - (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)

      -- 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)

# clear(store[, key])

  Used to clear the data in a store, will trigger any watchers, key is optional depending on if you are using them

  Parameters:
  - store : (number) the uid of the store that you want to clear
  - key : (string or any) the key that you want to clear, must be a string unless you have a serializer (optional)
  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)

      -- 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)

# set(store[, key], value)

  Used to set the data in a store, will trigger any watchers, key is optional depending on if you are using them

  Parameters:
  - store : (number) the uid of the store that you want to set
  - key : (string or any) the key that you want to set, must be a string unless you have a serializer (optional)
  - value : (any) 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')

      -- 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
      })

# update(store[, key], updater)

  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

  Parameters:
  - store : (number) the uid of the store that you want to update
  - key : (string or any) the key that you want to update, must be a string unless you have a serializer (optional)
  - updater : (function) 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)

      -- 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)

# map(store, updater)

  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

  Parameters:
  - store : (number) the uid of the store that you want to map
  - updater : (function) 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)

# trigger(store[, key])

  Used to trigger watcher functions, this may be used to trigger them if you did not use Store.update or Store.set

  Parameters:
  - store : (number) the uid of the store that you want to trigger
  - key : (string or any) the key that you want to trigger, must be a string unless you have a serializer (optional)
  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)

# raw_trigger(store[, key][, value][, old_value])

  Used to trigger watcher functions, the value and key are passed directly to the watchers regardless if the value is correct

  Parameters:
  - store : (number) the uid of the store that you want to trigger
  - key : (string or any) the key that you want to trigger, must be a string unless you have a serializer (optional)
  - value : (any) the new value that is at this key or store, passed directly to the watcher (optional)
  - old_value : (any) the old value that was at this key or store often the same if value is a table, passed directly to the watcher (optional)
  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')