[English is not my main language so I am sorry if there are any grammatical mistakes]
So I am making a sandbox-style farming game. In this case, there’s an item named ‘Farmland’ which is used to harvest crops. So I wanted to make it so that whenever a player leaves the game, the harvesting continues. There’s a module script which has the crop information used by a script which makes a datastore in which it saves the current time and when it is supposed to be completed. I have made a system where it creates an Id which is then used to the data store. I wanted to know if I could optimise the code by any means or make any little improvements at all
--Module script
local cropInfo = {}
local crops = {
["Wheat"] = {
["Time"] = .12; -- 120 seconds
["Crop"] = "Wheat";
["CostInCash"] = 15;
["CostInCoin"] = 0
}
}
cropInfo.ReturnCrop = function(cropName)
local cropInfo = crops[cropName]
return cropInfo
end
return cropInfo
//////////////////////////////////////////////////
-- Main script
local DataStore = game:GetService("DataStoreService")
local ItemIdDS = DataStore:GetDataStore("ItemId")
local ItemFnDS = DataStore:GetDataStore("ItemFunctions")
local Event = game.ReplicatedStorage.Events.HarvestingTriggered
local cropModule = require(game.ReplicatedStorage.Modules.Crops)
Event.OnServerEvent:Connect(function(Player, Item, CropName, Cost, Currency)
if Item == script.Parent then
if Currency == "Money" then
Player.mainFolder.Money.Value = Player.mainFolder.Money.Value - Cost
else
Player.mainFolder.Coins.Value = Player.mainFolder.Coins.Value - Cost
end
local playerKey = Player.UserId
local cropInfo = cropModule.ReturnCrop(CropName)
if cropInfo then
local timeWait = cropInfo["Time"]
local ItemId = ItemIdDS:IncrementAsync(playerKey .. script.Parent.Name, 1) -- script.Parent.Name means item's name so the Id is given for every individual item
local CurrentTime = os.time()
local itemTable = {
["timeWait"] = timeWait
["currentTime"] = CurrentTime
["Crop"] = CropName
}
local success, err = pcall(function()
ItemFnDS:SetAsync(playerKey .. script.Parent.Name .. tostring(ItemId), itemTable)
end)
if not success then
warn("Unable to save data " .. err)
end
script.Parent.ItemProperties.ItemId.Value = ItemId -- when a player leaves their itemId gets saved in this
end
end
end)
local function PerformItemFunction(time, timeWait, cropName)
local currentTime = os.time()
while true do
wait()
if (time - currentTime)/3600 >= timeWait then
for i,v in pairs (script.Parent:GetChildren()) do
if v.Name == "plot" then
local crop = v:FindFirstChild(cropName .. "5") -- this means the stage of crop, just a cosmetic
local crop2 = v:FindFirstChild(cropName .. "4")
for i,v in pairs (crop:GetChildren()) do
v.Transparency = 0
end
for i,v in pairs (crop2:GetChildren()) do
v.Transparency = 1
end
break -- break, then script determines if the process is finished or not
end
end
elseif (time - currentTime)/3600 >= timeWait/4 then
for i,v in pairs (script.Parent:GetChildren()) do
if v.Name == "plot" then
local crop = v:FindFirstChild(cropName .. "2")
local crop2 = v:FindFirstChild(cropName .. "1")
for i,v in pairs (crop:GetChildren()) do
v.Transparency = 0
end
for i,v in pairs (crop2:GetChildren()) do
v.Transparency = 1
end
end
end
elseif (time - currentTime)/3600 >= timeWait/3 then
for i,v in pairs (script.Parent:GetChildren()) do
if v.Name == "plot" then
local crop = v:FindFirstChild(cropName .. "3")
local crop2 = v:FindFirstChild(cropName .. "2")
for i,v in pairs (crop:GetChildren()) do
v.Transparency = 0
end
for i,v in pairs (crop2:GetChildren()) do
v.Transparency = 1
end
end
end
elseif (time - currentTime)/3600 >= timeWait/2 then
for i,v in pairs (script.Parent:GetChildren()) do
if v.Name == "plot" then
local crop = v:FindFirstChild(cropName .. "4")
local crop2 = v:FindFirstChild(cropName .. "3")
for i,v in pairs (crop:GetChildren()) do
v.Transparency = 0
end
for i,v in pairs (crop2:GetChildren()) do
v.Transparency = 1
end
end
end
else
for i,v in pairs (script.Parent:GetChildren()) do
if v.Name == "plot" then
local crop = v:FindFirstChild(cropName .. "1")
for i,v in pairs (crop:GetChildren()) do
v.Transparency = 0
end
end
end
end
end
script.Parent.ItemProperties.Finished.Value = true -- means that the process is finished and the player can collect the crops
end
script.Parent.ItemProperties.ItemId.Changed:Connect(function() -- ItemId changes when a player joins and the item was already making crops or when players triggers harvesting crop
if script.Parent.ItemProperties.ItemId.Value ~= 0 then -- 0 means item is at rest and there's no harvesting happening
local ItemId = script.Parent.LevelProperties.ItemId.Value
local Data
local playerKey = script.Parent.Parent.Parent.Plot.Owner.Value.UserId
local success, err = pcall(function()
local Data = ItemFnDS:GetAsync(playerKey .. script.Parent.Name .. tostring(script.Parent.ItemProperties.ItemId.Value))
end)
if success then
PerformItemFunction(Data.currentTime, Data.timeWait, Data.Crop)
else
print("Not Found")
end
end
end)
There’s one more script which sets ID to 0 when the player collects the crops it’s pretty straight forward, so I am not including that in this post. [Making it 0 will mean the item is at rest and it’s not harvesting]
Let me know if you have any questions about how something works, I will try my best to answer!