My House Script is very broken, with no logical explanation

local datastore = game:GetService("DataStoreService")
local ds1 = datastore:GetDataStore("GemSaveSystem")
local ds2 = datastore:GetDataStore("CashSaveSystem")
local ds3 = datastore:GetDataStore("jb")
local DS = game:GetService("DataStoreService"):GetDataStore("YourDataStore")
local Plots = game.Workspace.Plots
local StarterHouse = game.ServerStorage.Houses.StarterHouse:Clone()
local DFChildren = Plots:GetChildren() -- Returns a table
local random = DFChildren[math.random(1, #DFChildren)]

game.Players.PlayerAdded:connect(function(plr, player)
	local folder = Instance.new("Folder", plr)
	folder.Name = "leaderstats"
	local gems = Instance.new("IntValue", folder)
	gems.Name = "House"
	local cash = Instance.new("IntValue", folder)
	cash.Name = "Cash"
	local jb = Instance.new("IntValue", folder)
	jb.Name = "jb"
	
	gems.Value = ds1:GetAsync(plr.UserId) or 0
	ds1:SetAsync(plr.UserId, gems.Value)
	
	cash.Value = ds2:GetAsync(plr.UserId) or 0
	ds2:SetAsync(plr.UserId, cash.Value)
	
	jb.Value = ds3:GetAsync(plr.UserId) or 0
	ds3:SetAsync(plr.UserId, jb.Value)

	cash.Changed:connect(function()
		ds2:SetAsync(plr.UserId, cash.Value)
	end)
	
	gems.Changed:connect(function()
		ds1:SetAsync(plr.UserId, gems.Value)
	end)
	
	jb.Changed:connect(function()
		ds3:SetAsync(plr.UserId, jb.Value)
	end)
	
	if folder.jb.Value == 0 then
		print("Never Joined Before")
		folder.House.Value = 1
		folder.Cash.Value = 10000
		folder.jb.Value = 1
	else
		print("Joined Before")
	end
	
	if folder.House.Value == 1 then
		StarterHouse.Parent = workspace
		StarterHouse:SetPrimaryPartCFrame(random.CFrame)
	end
end)

This is my Script that Spawns in a Players House when the Join. Although I get the followings errors:

Test Mode In Studio:
Works Fine!

Local Test In Studio (2 Players):
Does not work atall.

Team Test In Studio (2 Players):
1 house spawns, with the floor removed.

Actual Game:
Does not work atall.

1 Like

This only runs once: when the server script starts. Meaning after everyone loads in, they’re going to have the exact same ‘random’ plot.

  1. You shouldn’t update a data store right after the value changes, that’s the fastest way to fill your data store queues. You should save the player’s data when the leave/get disconnected
  2. You should be using protected calls because DataStore:GetAsync() and DataStore:SetAsync() can both fail and break your script

Can’t you just use 1 data store and save a table into it?

This. Also (this is just a small note) using Instance.new()'s second parenting parameter isn’t recommended. It’s been proven to cause significant latency. Parent your objects at the end rather then right after calling Instance.new()

Source

Ive updated all of these things now, but my thing still doesn’t work.

What does your script look like now?

local datastore = game:GetService("DataStoreService")
local ds1 = datastore:GetDataStore("GemSaveSystem")
local ds2 = datastore:GetDataStore("CashSaveSystem")
local ds3 = datastore:GetDataStore("jb")
local DS = game:GetService("DataStoreService"):GetDataStore("YourDataStore")
local Plots = game.Workspace.Plots
local PlotsInUse = game.Workspace.PlotsInUse
local StarterHouse = game.ServerStorage.Houses.StarterHouse:Clone()
local DFChildren = Plots:GetChildren() -- Returns a table

game.Players.PlayerAdded:connect(function(plr, player)
	local random = DFChildren[math.random(1, #DFChildren)]
	local folder = Instance.new("Folder", plr)
	folder.Name = "leaderstats"
	local gems = Instance.new("IntValue", folder)
	gems.Name = "House"
	local cash = Instance.new("IntValue", folder)
	cash.Name = "Cash"
	local jb = Instance.new("IntValue", folder)
	jb.Name = "jb"
	
	gems.Value = ds1:GetAsync(plr.UserId) or 0
	ds1:SetAsync(plr.UserId, gems.Value)
	
	cash.Value = ds2:GetAsync(plr.UserId) or 0
	ds2:SetAsync(plr.UserId, cash.Value)
	
	jb.Value = ds3:GetAsync(plr.UserId) or 0
	ds3:SetAsync(plr.UserId, jb.Value)

	cash.Changed:connect(function()
		ds2:SetAsync(plr.UserId, cash.Value)
	end)
	
	gems.Changed:connect(function()
		ds1:SetAsync(plr.UserId, gems.Value)
	end)
	
	jb.Changed:connect(function()
		ds3:SetAsync(plr.UserId, jb.Value)
	end)
	
	if folder.jb.Value == 0 then
		print("Never Joined Before")
		folder.House.Value = 1
		folder.Cash.Value = 10000
		folder.jb.Value = 1
	else
		print("Joined Before")
	end
	
	if folder.House.Value == 1 then
		StarterHouse.Parent = workspace
		StarterHouse:SetPrimaryPartCFrame(random.CFrame)
		random.Parent = PlotsInUse
	end
end)
-- services here
local dss = game:GetService("DataStoreService")
local serverStorage = game:GetService("ServerStorage")
local players = game:GetService("Players")

-- data stores
local ds1 = dss:GetDataStore("GemSaveSystem")
local ds2 = dss:GetDataStore("CashSaveSystem")
local ds3 = dss:GetDataStore("jb")

local Plots = workspace.Plots -- using the "workspace" global is much faster
local PlotsInUse = workspace.PlotsInUse
local StarterHouse = serverStorage:WaitForChild("Houses").StarterHouse:Clone()
-- uses "WaitForChild" because the "Houses" instance could possibly not load

local DFChildren = Plots:GetChildren() -- Returns a table

local function SetAsync(dataStore, key, value)
      local success, err = pcall(function()
         dataStore:SetAsync(key, value)
      end)

   if not success then
       warn(err) -- like the GetAsync function, tell you why something fails
   end
end

players.PlayerAdded:Connect(function(plr) -- not exactly sure why you had 2 player arguments
    -- "connect" is deprecated, you should use the PascalCase API

	local random = DFChildren[math.random(1, #DFChildren)]

    -- as Toidit said, don't use the parent argument
	local folder = Instance.new("Folder")
	folder.Name = "leaderstats"
    folder.Parent = plr

	local gems = Instance.new("IntValue")
	gems.Name = "House"
    gems.Parent = folder

	local cash = Instance.new("IntValue")
	cash.Name = "Cash"
    cash.Parent = folder

	local jb = Instance.new("IntValue")
	jb.Name = "jb"
	jb.Parent = folder

    local function GetAsync(dataStore, key)
       local success, err = pcall(function() -- this is a protected call
           return dataStore:GetAsync(key)
       end)

       if not success then
          warn(err) -- in case it fails, tell you why
          err = nil
       end

       return err
    end



	gems.Value = GetAsync(ds1, plr.UserId) or 0
	cash.Value = GetAsync(ds2, plr.UserId) or 0
	jb.Value = GetAsync(ds3, plr.UserId) or 0
	
	if folder.jb.Value == 0 then
		print("Never Joined Before")
		folder.House.Value = 1
		folder.Cash.Value = 10000
		folder.jb.Value = 1
	else
		print("Joined Before")
	end
	
	if folder.House.Value == 1 then
		StarterHouse.Parent = workspace
		StarterHouse:SetPrimaryPartCFrame(random.CFrame)
		random.Parent = PlotsInUse
	end
end)

local function PlayerRemoving(player)
   -- function for when the player leaves
   local ls = player:WaitForChild("leaderstats")
   local cash = ls.Cash
   local jb = ls.jb
   local gems = ls.House

   -- save everything
   SetAsync(ds1, plr.UserId, gems.Value)
   SetAsync(ds2, plr.UserId, cash.Value)
   SetAsync(ds3, plr.UserId, jb.Value)
end

players.PlayerRemoving:Connect(PlayerRemoving) -- detect if a player leaves

game:BindToClose(function()
   -- this saves everyone's data incase the server closes unexpectedly

   for _, plr in pairs(players:GetPlayers()) do
     PlayerRemoving(plr)
   end
end)

P.S. You should test data stores in a live server, not studio

They work fine in a Live Server.