Data in module doesn't save

  1. What do you want to achieve? Keep it simple and clear!
    I want to save data from my module scripts into datastores. (Player data and world data)

  2. What is the issue? Include screenshots / videos if possible!
    Data isn’t being loaded properly.

  • The script prints data saving successfully print("Saved world data with id test"). Always on autosaves but I don’t think I see it on all leaves (If you know why also tell me) image image,

  • When I use print() while playing, I can see new data is added to the module
    image

  • My script says that it has loaded data, however it is no different from the default module data and has no changes made in the last game session.
    image

image

  • Studio access to API services on, not using updateAsync improperly
    image
  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

Above. Studio access api on, not using updateAsync improperly. Developer hub doesn’t really help because I think my dataStoreModule is functional.
I have made a system like this is a past, but only with player data.

Edit: Also moved set/get functions into script and replaced calling them


Scripts

dataManager (Module)

local dataManager = {}

local config = {
	autosaveTime = 300, --Seconds per each autosave
	studioWorldId = "test", --The id used when teleport service is unavailable
}

local serverScriptService = game:GetService("ServerScriptService")
local serverStorage = game:GetService("ServerStorage")

local dataStoreModule = require(serverScriptService.dataStoreModule)
local securityModule = require(serverScriptService.securityManager)

local players = game:GetService("Players")
local runService = game:GetService("RunService")

--World id
local worldId
if (game.PrivateServerId ~= "" and game.PrivateServerOwnerId == 0) or runService:IsStudio() then
	if runService:IsStudio() then
		dataManager.worldId = config.studioWorldId
	else
		dataManager.worldId = game.PrivateServerId
	end
end
print("World id is "..tostring(dataManager.worldId))

--Data modules
local worldData = require(serverStorage.data.worldData)
local playerData = require(serverStorage.data.playerData)

--Save functions
dataManager.canAutosave = true

local function savePlayer(userId)
	local success = dataStoreModule.set("playerData", userId, playerData[userId])
	local username = players:GetNameFromUserIdAsync(userId)
	if success then
		print("Saved player with name "..username)
	else
		print("Failed to save player with name "..username)
	end
end
players.PlayerRemoving:Connect(function(player)
	local userId = player.UserId
	savePlayer(userId)
end)

local function saveWorld()
	if dataManager.worldId == nil then
		warn("Attempt to save nonexistant world")
		return
	end
	
	local success = dataStoreModule.set("worldData", dataManager.worldId, worldData)
	if success then
		print("Saved world data with id "..tostring(dataManager.worldId))
	else
		print("Failed to save world with id "..tostring(dataManager.worldId))
	end
end
game:BindToClose(function()
	local currentPlayers = players:GetPlayers()
	
	local targetSaves = #currentPlayers
	local currentSaves = 0
	if dataManager.worldId then
		targetSaves += 1
	end
	
	spawn(function()
		saveWorld()
		currentSaves += 1
	end)
	for _, player in currentPlayers do
		spawn(function()
			savePlayer(player.UserId)
			currentSaves += 1
		end)
	end
	wait(0.25)
end)

--Load functions
local function loadPlayer(player)
	local userId = player.UserId

	local data = dataStoreModule.get("playerData", userId)
	if data == false then
		player:Kick("Failed to fetch player data")
		return
	elseif data == nil then
		data = playerData.template
	end
	playerData[userId] = data

	spawn(function()
		while true do
			wait(config.autosaveTime)
			if not dataManager.canAutosave then
				break
			end
			savePlayer(userId)
		end
	end)
end
players.PlayerAdded:Connect(loadPlayer)

function dataManager.loadWorld()
	if dataManager.worldId == nil then
		warn("Attempt to load nonexistant world")
		return
	end
	
	
	local data = dataStoreModule.get("worldData", dataManager.worldId)
	if data == false then
		securityModule.shutdown("Failed to fetch world data")
		return
	elseif data ~= nil then
		print(data)
		print("Using saved data")
		worldData = data
	else
		print("Using current data")
	end
	
	spawn(function()
		while true do
			wait(config.autosaveTime)
			if not dataManager.canAutosave then
				break
			end
			saveWorld()
		end
	end)
end

dataManager.config = config
return dataManager

dataStoreModule (Module)

local dataStoreModule = {}

local dataStoreService = game:GetService("DataStoreService")
local runService = game:GetService("RunService")

function dataStoreModule.set(store, key, value, players)
	local storeName = store
	local store = dataStoreService:GetDataStore(store)
	local failed = true
	for i = 1, 5 do
		local success, returned = pcall(function()
			if value == nil then
				store:RemoveAsync(key)
			else
				store:SetAsync(key, value, players)
			end
		end)
		if success then
			failed = false
			break
		end
		if runService:IsStudio() then
			break
		end
		wait(1)
	end
	if failed then
		if storeName == nil then
			storeName = "nil"
		end
		if key == nil then
			key = "nil"
		end
		if value == nil then
			value = "nil"
		end
		warn(string.format("Data store error:\nAction: Set\nStore: %s\nKey: %s\nValue: %s", storeName, key, tostring(value)))
		return false
	else
		return true
	end
end

function dataStoreModule.get(storeName, key)
	local store = dataStoreService:GetDataStore(storeName)
	local value = nil
	local failed = true
	for i = 1, 5 do
		local success, returned = pcall(function()
			value = store:GetAsync(key)
		end)
		if success then
			failed = false
			break
		end
		if runService:IsStudio() then
			break
		end
		wait(1)
	end
	if failed then
		if storeName == nil then
			storeName = "nil"
		end
		if key == nil then
			key = "nil"
		end
		warn(string.format("Data store error:\nAction: Get\nStore: %s\nKey: %s", storeName, key))
		return false
	else
		return value
	end
end

function dataStoreModule.remove(storeName, key)
	local store = dataStoreService:GetDataStore(storeName)
	local failed = true
	for i = 1, 5 do
		local success, returned = pcall(function()
			store:RemoveAsync(key)
		end)
		if success then
			failed = false
			break
		end
		if runService:IsStudio() then
			break
		end
		wait(1)
	end
	if failed then
		if storeName == nil then
			storeName = "nil"
		end
		if key == nil then
			key = "nil"
		end
		warn(string.format("Data store error:\nAction: Remove\nStore: %s\nKey: %s", storeName, key))
		return false
	else
		return true
	end
end

return dataStoreModule

setupManager (Server script, Lines 60-73)

dataManager.loadWorld()

local i = 0
for _, _ in worldData.tiles do
	i += 1
end
print(worldData)
if i == 0 then
	print("Creating tiles")
	generationManager.create() --Supposed to only run first time world created
end

print("Loading tiles")
generationManager.load()

I think I found the solution.

When trying to set data manually, I got this error.
image

I might try and use JSON Encode to convert it all to a string.