-- Cozy Creek: Roblox Starter Kit -- Paste each script into the locations shown. This is a minimal, working skeleton for a garden/idle game. -- Read the README section below before pasting. README ====== 1) Open Roblox Studio and create a new place. 2) In Explorer create these containers: - ReplicatedStorage - ServerScriptService - StarterPlayer > StarterPlayerScripts - StarterGui - ServerStorage - Workspace > Gardens (Folder) - StarterPack (optional tools) 3) Create RemoteEvents in ReplicatedStorage: - RemoteEvents > PlantSeed - RemoteEvents > HarvestCrop - RemoteEvents > RequestGardenData - RemoteEvents > GiftItem 4) Create ModuleScripts in ReplicatedStorage > Modules: - Modules > CropModule - Modules > DataStoreModule 5) Add scripts (below) into ServerScriptService, StarterPlayerScripts, and StarterGui. 6) Create simple parts/models for crops in ServerStorage > CropModels and add a template object named "CropTemplate". 7) Test in PLAY and adjust. -- FILE: ReplicatedStorage/Modules/CropModule (ModuleScript) local CropModule = {} -- Simple crop definitions CropModule.Definitions = { Tomato = { growTime = 60, -- seconds modelName = "TomatoModel", sellValue = 5, }, Sunflower = { growTime = 120, modelName = "SunflowerModel", sellValue = 12, } } function CropModule.GetDefinition(name) return CropModule.Definitions[name] end return CropModule -- FILE: ReplicatedStorage/Modules/DataStoreModule (ModuleScript) local DataStoreService = game:GetService("DataStoreService") local PlayersData = DataStoreService:GetDataStore("CozyCreek_PlayerData_v1") local DataStoreModule = {} function DataStoreModule.Load(player) local key = "player_"..player.UserId local success, data = pcall(function() return PlayersData:GetAsync(key) end) if success and data then return data else -- default data return { coins = 0, gardens = {}, lastOnline = os.time() } end end function DataStoreModule.Save(player, data) local key = "player_"..player.UserId local success, err = pcall(function() PlayersData:SetAsync(key, data) end) if not success then warn("Failed to save: ", err) end end return DataStoreModule -- FILE: ServerScriptService/GameServer (Script) local ReplicatedStorage = game:GetService("ReplicatedStorage") local ServerStorage = game:GetService("ServerStorage") local Players = game:GetService("Players") local CropModule = require(ReplicatedStorage.Modules.CropModule) local DataStore = require(ReplicatedStorage.Modules.DataStoreModule) local Remote = ReplicatedStorage:WaitForChild("RemoteEvents") local PlantSeed = Remote:WaitForChild("PlantSeed") local HarvestCrop = Remote:WaitForChild("HarvestCrop") local RequestGarden = Remote:WaitForChild("RequestGardenData") local GardensFolder = workspace:FindFirstChild("Gardens") or Instance.new("Folder", workspace) GardensFolder.Name = "Gardens" -- Utility to create a crop instance in workspace local function spawnCropForPlayer(player, cropName, position, plantedTime) local def = CropModule.GetDefinition(cropName) if not def then return end local modelTemplate = ServerStorage:FindFirstChild("CropModels") and ServerStorage.CropModels:FindFirstChild(def.modelName) if not modelTemplate then -- fallback: simple part local part = Instance.new("Part") part.Size = Vector3.new(2,2,2) part.Anchored = true part.Position = position part.Name = cropName part.Parent = GardensFolder return {instance = part, plantedTime = plantedTime or os.time(), cropName = cropName} end local clone = modelTemplate:Clone() clone.Parent = GardensFolder clone:SetPrimaryPartCFrame(CFrame.new(position)) return {instance = clone, plantedTime = plantedTime or os.time(), cropName = cropName} end -- When a player joins, load data and spawn their saved crops Players.PlayerAdded:Connect(function(player) local data = DataStore.Load(player) player:SetAttribute("Coins", data.coins or 0) player:SetAttribute("LastOnline", data.lastOnline or os.time()) -- offline growth: calc earnings while offline local now = os.time() local offlineSeconds = now - (data.lastOnline or now) for _, g in pairs(data.gardens or {}) do -- for simplicity assume each garden entry is {cropName, pos, plantedTime} local def = CropModule.GetDefinition(g.cropName) if def then local finishTime = (g.plantedTime or now) + def.growTime if finishTime <= now then -- crop matured while away; grant sellValue player:SetAttribute("Coins", (player:GetAttribute("Coins") or 0) + def.sellValue) else -- spawn unfinished crop spawnCropForPlayer(player, g.cropName, Vector3.new(unpack(g.pos or {0,5,0})), g.plantedTime) end end end -- save player data on leave player.AncestryChanged:Connect(function(_, parent) if not parent then local saveData = { coins = player:GetAttribute("Coins") or 0, gardens = {}, lastOnline = os.time() } -- collect plants in GardensFolder belonging to player? (Add ownership in production) DataStore.Save(player, saveData) end end) end) -- Plant handler (server authoritative) PlantSeed.OnServerEvent:Connect(function(player, cropName, position) local def = CropModule.GetDefinition(cropName) if not def then return end -- Basic validation local planted = spawnCropForPlayer(player, cropName, position, os.time()) -- In a real game you'd store ownership and data print(player.Name .. " planted " .. cropName) end) -- Harvest handler HarvestCrop.OnServerEvent:Connect(function(player, cropInstance) -- cropInstance could be an instance id reference. For simplicity assume player passes instance if not cropInstance or not cropInstance.Parent then return end local cropName = cropInstance.Name local def = CropModule.GetDefinition(cropName) if not def then return end -- Check time -- For this skeleton we'll give the reward local current = player:GetAttribute("Coins") or 0 player:SetAttribute("Coins", current + def.sellValue) cropInstance:Destroy() print(player.Name .. " harvested " .. cropName) end) -- Garden data request (send basic attributes) RequestGarden.OnServerEvent:Connect(function(player) local data = { coins = player:GetAttribute("Coins") or 0, } Remote:FindFirstChild("SendGardenData"):FireClient(player, data) end) -- FILE: StarterPlayer/StarterPlayerScripts/ClientMain (LocalScript) local ReplicatedStorage = game:GetService("ReplicatedStorage") local Players = game:GetService("Players") local player = Players.LocalPlayer local Remote = ReplicatedStorage:WaitForChild("RemoteEvents") local PlantSeed = Remote:WaitForChild("PlantSeed") local HarvestCrop = Remote:WaitForChild("HarvestCrop") local RequestGarden = Remote:WaitForChild("RequestGardenData") -- Simple example: plant a tomato where the player is pointing when they press E local UserInputService = game:GetService("UserInputService") UserInputService.InputBegan:Connect(function(input, processed) if processed then return end if input.KeyCode == Enum.KeyCode.E then local mouse = player:GetMouse() local pos = mouse.Hit.p PlantSeed:FireServer("Tomato", pos) end end) -- Request initial data RequestGarden:FireServer() -- Handle server response local SendGardenData = Remote:WaitForChild("SendGardenData") SendGardenData.OnClientEvent:Connect(function(data) print("Coins:", data.coins) end) -- FILE: ReplicatedStorage/RemoteEvents (Folder + RemoteEvents) -- Create RemoteEvents with these exact names: -- PlantSeed, HarvestCrop, RequestGardenData, SendGardenData, GiftItem -- FILE: StarterGui/MainGui (ScreenGui + LocalScript) -- Add a ScreenGui called MainGui to StarterGui. Inside, add a TextLabel named CoinsLabel. -- LocalScript inside MainGui (Client GUI updater) local ReplicatedStorage = game:GetService("ReplicatedStorage") local player = game.Players.LocalPlayer local gui = script.Parent local coinsLabel = gui:WaitForChild("CoinsLabel") local Remote = ReplicatedStorage:WaitForChild("RemoteEvents") local RequestGarden = Remote:WaitForChild("RequestGardenData") local SendGardenData = Remote:WaitForChild("SendGardenData") RequestGarden:FireServer() SendGardenData.OnClientEvent:Connect(function(data) coinsLabel.Text = "Coins: " .. tostring(data.coins) end)