You've asked a lot of questions, so I'll try to address them all
Can you save tables to datastore in Roblox studio? ... I need three values by key. These are: the row, the column and the colour of the platform conquered.
Tables cannot be saved, but if your data can be serialized, you can convert the table to a string using HttpService:JSONEncode(), and back to a table using HttpService:JSONDecode().
local HttpService = game:GetService("HttpService")
local dataString = HttpService:JSONEncode({
row = 5,
column = 10,
color = "Red",
})
print(dataString)
local reconstructedData = HttpService:JSONDecode(dataString)
print(reconstructedData.row, reconstructedData.column, reconstructedData.color)
Can datastore be ''impersonal'' that is not associated necessarily with a player ID as the key
Sure, you can store information under any key you want. But you should be very careful choosing keys because every single game server will be writing to those keys. This is why playerID is always recommended, because it is a guaranteed unique key, and players cannot be in two servers at the same time, so there is no risk of two servers accidentally writing to the same key at the same time.
If you have multiple game servers writing to the same key, there is a very very high chance that two servers are going to overwrite each other's data and someone's stuff is going to get lost.
I want the data saved during the game to be retrieved during the game... I want then every player to access this datastore when they join or when it updates.
This isn't a good use-case for DataStores. DataStores should be used for persistent storage of data about players or the world that must carry across multiple servers. For example, think of a global leaderboard, or a player's game progress, or how deep a hole is that has been dug by multiple people (assuming you want that hole to persist the next time the game starts up).
If you are trying to access game state information and you are still in an active game, you can just have a new player construct their game board based on the current state. There's no need to communicate this through DataStores.
A good way to handle active game state information is to make a "GameManager" object in a server Script, and make it the authority over changes that happen in the game. A player scores? Tell the GameManager, it will update the scoreboard. A player joins? Ask the GameManager what the current state of the platforms/game board is.
You can accomplish all of this with simple lua tables, RemoteEvents, and RemoteFunctions. I like to use a ModuleScript to make my GameManager class. I rough outline of the architecture would be something like this ...
local PlayerService = game:GetService("Players")
-- keep a list of RemoteFunctions and RemoteEvents that are fired by players when they do something
local GetState = game.ReplicatedStorage.Functions.GetState
local PlayerAction = game.ReplicatedStorage.Events.PlayerAction
-- keep a list of RemoteEvents that are fired by the GameManager when something should be communicated to the players
local StartGame = game.ReplicatedStorage.Events.StartGame
local UpdateBoard = game.ReplicatedStorage.Events.UpdateBoard
local EndGame = game.ReplicatedStorage.Events.EndGame
-- make an authority over the game state
local GameManager = {}
GameManager.__index = GameManager
function GameManager.new()
local gm = {
-- keep a list of players
teams = { "red" = {}, "blue" = {} },
-- keep a list of scores per team
scores = { "red" = 0, "blue" = 0 },
-- keep track of the board colors
platforms = {},
-- keep track of the state of the game
currentGameState = "WaitingForPlayers", --InGame, PostGame
-- as good housecleaning, hold onto connection tokens
__tokens = {},
}
setmetatable(gm, GameManager)
-- if anyone ever asks what the current state of the game is, let them know!
GetState.OnServerInvoke = function()
return gm.scores, gm.platforms, gm.currentGameState, gm.teams
end
return gm
end
function GameManager:waitForPlayers()
-- wait for players to join to start the game
while #PlayerService:GetPlayers() < 1 do
wait(5)
end
wait(5)
-- tell everyone the round is starting!
self:startNewGame()
end
function GameManager:startNewGame()
-- start listening to game events
local playerActionToken = PlayerAction:OnServerEvent(function(player, ...)
-- the player has done something, update the game state!
local args = { ... }
print("PlayerAction : ", player.Name, unpack(args))
-- if a platform was taken, alert all players so they can update their stuff
UpdateBoard:FireAllClients(self.platforms)
end)
table.insert(self.__tokens, playerActionToken)
-- assign players to teams...
-- tell all the players that the game has begun
StartGame:FireAllClients()
-- rather than code a game loop, just kill the game for now
spawn(function()
wait(30)
-- tell everyone the game is over
self:endGame()
end)
end
function GameManager:endGame()
self.currentGameState = "PostGame"
-- communicate to all players that the game is over, and let them know the score
EndGame:FireAllClients(self.scores)
-- stop accepting actions from the game and clean up connections
for _, token in ipairs(self.__tokens) do
token:Disconnect()
end
-- start the game over again!
spawn(function()
wait(30)
self:waitForPlayers()
end)
end
return GameManager
Then in a server Script, just create the GameManager...
local GameManager = require(script.Parent.GameManager) -- or wherever you've put it
local gm = GameManager.new()
gm:waitForPlayers()
Then in a LocalScript, have the players request the game state when they join the game...
-- connect to all the game signals that the server might send
game.ReplicatedStorage.Events.StartGame:Connect(function(args)
-- construct the local game board
print("Game has started!")
end)
game.ReplicatedStorage.Events.UpdateBoard:Connect(function(newBoardState)
print("Board state has changed!")
end)
game.ReplicatedStorage.Events.EndGame:Connect(function(scores)
print("Game has ended!")
end)
-- request the current game state with a RemoteFunction
local GetState = game.ReplicatedStorage.Functions.GetState
local scores, platforms, currentGameState, teams= GetState:InvokeServer()
-- parse the current game state and make the board...
for k, v in pairs(scores) do
print(k, v)
end
for k, v in pairs(platforms) do
print(k, v)
end
print(currentGameState)
for k, v in pairs(teams) do
print(k, v)
end