Problem with tycoon saving

  1. What do you want to achieve? Keep it simple and clear!
    So basically i’m saving a data for my tycoon.
  2. What is the issue? Include screenshots / videos if possible!
    For some strange reason it break button which set amount of money and which get amount of money. Also this is not button problem, while there were no datastore it worked fine
  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub? Well i was making this by youtube video. Also i put a lot of prints. First Button buys everything fine. But when i try buy second it always prints:
    image

Code:

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local PlayerData = DataStoreService:GetDataStore("PlayerData")


local function LeaderboardSetup(value)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	print("Data sent")
	local Cash = Instance.new("NumberValue")
	Cash.Name = "Cash"
	Cash.Value = value
	Cash.Parent = leaderstats
	return leaderstats
end

local function LoadData(player)
	local success, result = pcall(function()
		print("Data Loading...")
		return PlayerData:GetAsync(player.UserId)
	end)
	if not success then
		warn("LOADING DATASTORE ERROR, PLEASE FIX IT")
	end	
	return success, result
end

local function SaveData(player, data)
	local success, result = pcall(function()
		print("Data Saving...")
		PlayerData:SetAsync(player.UserId, data)
	end)
	if not success then
		warn("SAVING DATASTORE ERROR, PLEASE FIX IT")
	end
	return success
end

local sessionData = {}

local playerAdded = Instance.new("BindableEvent")
local playerRemoving = Instance.new("BindableEvent")

local PlayerManager = {}

PlayerManager.PlayerAdded = playerAdded.Event
PlayerManager.PlayerRemoving = playerRemoving.Event
function PlayerManager.Start()
	for _,player in ipairs(Players:GetPlayers()) do
	  coroutine.wrap(PlayerManager.OnPlayerAdded)(player)	
	end
	
	Players.PlayerAdded:Connect(PlayerManager.OnPlayerAdded)	
	Players.PlayerRemoving:Connect(PlayerManager.OnPlayerRemoving)	
	
	game:BindToClose(PlayerManager.OnClose)
end

function PlayerManager.OnPlayerAdded(player)
	player.CharacterAdded:Connect(function(character)
		PlayerManager.OnCharacterAdded(player, character)
	end)
	
	local success, data = LoadData(player)
	sessionData[player.UserId] = success and data or {
		Cash = 0,
		UnlockIds = {}
	}
	print("Data Loaded Successfully")
	local leaderstats = LeaderboardSetup(PlayerManager.GetMoney(player))
	leaderstats.Parent = player
	
	playerAdded:Fire(player)
end

function PlayerManager.OnCharacterAdded(player, character)
	local humanoid = character:FindFirstChild("Humanoid")
	if humanoid then
		humanoid.Died:Connect(function()
			wait(1)
			player:LoadCharacter()
		end)
	end
end

function PlayerManager.GetMoney(player)
 print("Got Data")
 return sessionData[player.UserId].Cash -- i think problem is here
end

function PlayerManager.SetMoney(player, value)
	if value then
        sessionData[player.UserId].Cash = value -- or here
		print("Saved Session Data")
		local leaderstats = player:FindFirstChild("leaderstats")
		if leaderstats then
			print("leaderstats exists")
			local Cash = leaderstats:FindFirstChild("Cash")
			if Cash then
				print("Cash Exists")
				print("Buying Complete")
				Cash.Value = value
			end
		end	
	end
end

function PlayerManager.OnPlayerRemoving(player)
	print("Data Saved")
	SaveData(player, sessionData[player.UserId])
	playerRemoving:Fire(player)
end

function PlayerManager.OnClose()
	print("Data for all saved")
	for _, player in ipairs(Players:GetPlayers()) do
		PlayerManager.OnPlayerRemoving(player)
	end
end

return PlayerManager

Yeah 6th topic

Also, button Module do not call GetMoney function, i have no idea why it get called instead of SetMoney function

I know that this is from bricey’s tycoon tutorial. You should check if your code is the same as his in the github page and you should ask him in his discord server because he can probably figure it out.

Well i’m using a bit different variables, and different code in some parts, so copying code from github not best solution.

Man this is way to complicated lemme fix this :smiley:

You should have just copied the code at first (since you don’t know how to fix it) and then changes the variables after.

1 Like

Also what’s your button script?

Well this didn’t work out, still same problem.

I already mentioned that this is not button problem, in case without datastores it was working fine

It could be a button problem, especially since the button is setting the vital data for when a player buys stuff (which is saved later on).

Well let me send, also just for a sure checked a script without DS it works fine.

--Vars and Services
local DataStore = game:GetService("DataStoreService"):GetDataStore("MainDatastore")

--Functions
function formatData(player)

	local data = {}

	local YourFolder = player:WaitForChild("leaderstats")
	local Values = {}

	for i,piece in pairs(YourFolder:GetChildren()) do
		table.insert(Values, piece.Value)
	end

	table.insert(data, Values)
	return data
end

function saveData(player)
	local Key = "Player_"..player.UserId
	local stuffToSave = formatData(player)

	local succes, err = pcall(function()

		if stuffToSave then
			DataStore:SetAsync(Key, stuffToSave)
		end

	end)

	if err then
		warn('WARNING: COULD NOT SAVE PLAYER DATA: '..err)
	end
end

function loadData(player)
	--CREATING FOLDERS
	local Key = "Player_"..player.UserId

	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player
	local Cash = Instance.new("IntValue", leaderstats)
	Cash.Name = "Cash"
	------------------------------------------------------------

	--GETTING PLAYER DATA
	local sucess, err = pcall(function()
		local data = DataStore:GetAsync(Key)
		if data then
			if data[1] then
				Cash.Value = data[1][1] -- The first section of the folder, first value: Cash
			else
				Cash.Value = 0
			end
		else  -- if data doesn't exist         
			Cash.Value = 0
		end
	end)

	if err then
		warn('WARNING: COULD NOT LOAD PLAYER DATA: '..err)
	end

end

function onServerShutdown()
	if game:GetService("RunService"):IsStudio() then
		wait(2)
	else
		for _, player in pairs(game.Players:GetPlayers()) do
			local finished = Instance.new("BindableEvent")

			saveData(player) --It's easier to use the previous saveData function on each player than it is to write new code

			finished.Event:Wait()
		end		
	end
end


--Binding Events
game:BindToClose(onServerShutdown)
game.Players.PlayerAdded:Connect(loadData)
game.Players.PlayerRemoving:Connect(saveData)
local PlayerManager = require(script.Parent.Parent.PlayerManager)
local Button = {}
Button.__index = Button

function Button.new(tycoon, part)
	local self = setmetatable({}, Button)
	self.Tycoon = tycoon
	self.Instance = part
	
	return self
end

function Button:Init()
	self.Prompt = self:CreatePrompt()
	self.Prompt.Triggered:Connect(function(...)
		self:Press(...)
	end)
end

function Button:CreatePrompt()
	local prompt = Instance.new("ProximityPrompt")
	prompt.HoldDuration = 0.5
	prompt.ActionText = ""
	prompt.Parent = self.Instance.Forcefield
	self.Instance.TopPart.BillboardGui.Frame.UpgradeName.Text = self.Instance:GetAttribute("Display")
	if self.Instance:GetAttribute("Cost") == 0 then
		self.Instance.TopPart.BillboardGui.Frame.Price.Text = "FREE"
	else
		self.Instance.TopPart.BillboardGui.Frame.Price.Text = self.Instance:GetAttribute("Cost").."$"
	end
	return prompt
end

function Button:Press(player)
	local id = self.Instance:GetAttribute("Id")
	local cost = self.Instance:GetAttribute("Cost")
	local cash = PlayerManager.GetMoney(player)
	if player == self.Tycoon.Owner and cash >= cost then
		PlayerManager.SetMoney(player, cash - cost)
		self.Tycoon:PublishTopic("Button", id)
		self.Instance:Destroy()
	end
end

return Button

What? This is not compatible with this guy’s tycoon and also, the B Ricey tutorial shows a better method of doing these types of tycoons so that they are more modifiable and modular.

Hm, it could be a problem with your unlockable component but I really don’t know. You should go to the B Ricey discord server and ask him to help.

When I made the tycoon it worked fine for me.

Well then it won’t work without datastore, but it works. Also here is unlockable m
module:

local Unlockable = {}
Unlockable.__index = Unlockable

function Unlockable.new(tycoon, instance)
	local self = setmetatable({}, Unlockable)
	self.Tycoon = tycoon
	self.Instance = instance
	
	return self
end

function Unlockable:Init()
	self.Subscription = self.Tycoon:SubscribeTopic("Button", function(...)
		self:OnButtonPressed(...)
	end)
end

function Unlockable:OnButtonPressed(id)
	if id == self.Instance:GetAttribute("UnlockID") then
		self.Tycoon:Unlock(self.Instance, id)
		self.Subscription:Disconnect()
	end
end


return Unlockable

I just made this script for him. It saves the Data when he leaves or the game crashes and it loads the data when he joins. He said the problem was saving his data. He could use this script and remove the onplayer removing, on close, on playeradded and the start function. Or did I understand something wrong?

He wants help with his current tycoon saving code, not for you to create new code, especially when your new code probably won’t be compatible with his tycoon (without heavy modifications which will be considerably more challenging than just editing his original code).

Alright! [–character limit–]

1 Like

Dear @PhantomGame_Youtube,
I tried “fixing” your script:

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local PlayerData = DataStoreService:GetDataStore("PlayerData")


local function LeaderboardSetup(value)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	print("Data sent")
	local Cash = Instance.new("NumberValue")
	Cash.Name = "Cash"
	Cash.Value = value
	Cash.Parent = leaderstats
	return leaderstats
end

local function LoadData(player)
	local success, result = pcall(function()
		print("Data Loading...")
		return PlayerData:GetAsync(player.UserId)
	end)
	if not success then
		warn("LOADING DATASTORE ERROR, PLEASE FIX IT")
	end	
	return success, result
end

function SaveData(player, data)
	local Key = "Player_"..player.UserId
	local succes, err = pcall(function()
		if data then
			DataStoreService:SetAsync(Key, data)
		end
	end)
	if err then
		warn('WARNING: COULD NOT SAVE PLAYER DATA: '..err)
	end
end

local sessionData = {}

local playerAdded = Instance.new("BindableEvent")
local playerRemoving = Instance.new("BindableEvent")

local PlayerManager = {}

PlayerManager.PlayerAdded = playerAdded.Event
PlayerManager.PlayerRemoving = playerRemoving.Event
function PlayerManager.Start()
	for _,player in ipairs(Players:GetPlayers()) do
		coroutine.wrap(PlayerManager.OnPlayerAdded)(player)	
	end

	Players.PlayerAdded:Connect(PlayerManager.OnPlayerAdded)	
	Players.PlayerRemoving:Connect(PlayerManager.OnPlayerRemoving)	

	game:BindToClose(PlayerManager.OnClose)
end

function PlayerManager.OnPlayerAdded(player)
	player.CharacterAdded:Connect(function(character)
		PlayerManager.OnCharacterAdded(player, character)
	end)

	local success, data = LoadData(player)
	sessionData[player.UserId] = success and data or {
		Cash = 0,
		UnlockIds = {}
	}
	print("Data Loaded Successfully")
	local leaderstats = LeaderboardSetup(PlayerManager.GetMoney(player))
	leaderstats.Parent = player

	playerAdded:Fire(player)
end

function PlayerManager.OnCharacterAdded(player, character)
	local humanoid = character:FindFirstChild("Humanoid")
	if humanoid then
		humanoid.Died:Connect(function()
			wait(1)
			player:LoadCharacter()
		end)
	end
end

function PlayerManager.GetMoney(player)
	print("Got Data")
	table.insert(sessionData, player.leaderstats.Cash.Value)
end

function PlayerManager.SetMoney(player, value)
	if value then
		table.insert(sessionData, player.leaderstats.Cash.Value)
		print("Saved Session Data")
		local leaderstats = player:FindFirstChild("leaderstats")
		if leaderstats then
			print("leaderstats exists")
			local Cash = leaderstats:FindFirstChild("Cash")
			if Cash then
				print("Cash Exists")
				print("Buying Complete")
				Cash.Value = value
			end
		end	
	end
end

function PlayerManager.OnPlayerRemoving(player)
	print("Data Saved")
	SaveData(player, sessionData)
	playerRemoving:Fire(player)
end

function PlayerManager.OnClose()
	print("Data for all saved")
	for _, player in ipairs(Players:GetPlayers()) do
		PlayerManager.OnPlayerRemoving(player)
	end
end

return PlayerManager

BUUTTT since i am a newbie I am not sure if this version will work for you, BUT I hope it will. May you could try this and if it does not work pls tell me >_<