Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local Players = game:GetService("Players")
- local RunService = game:GetService("RunService")
- local DataStoreService = game:GetService("DataStoreService")
- local CollectionService = game:GetService("CollectionService")
- local HttpService = game:GetService("HttpService")
- local IsServer = RunService:IsServer()
- local VersionDataStore = IsServer and DataStoreService:GetDataStore("Versions")
- local PlayerDataStore = IsServer and DataStoreService:GetDataStore("PlayerData")
- local Update = script:WaitForChild("Update")
- local Ready = script:WaitForChild("Ready")
- local ALLOW_OLD_DATA_LOAD = false
- local PlayerData = {}
- PlayerData.__index = PlayerData
- local storedPlayerData = {}
- local saveLock = {}
- local DefaultData = require(script:WaitForChild("Default"))
- function PlayerData.default()
- return DefaultData()
- end
- local function getPlayerVersion(player, version)
- return pcall(function()
- return PlayerDataStore:GetAsync("u_" .. player.UserId .. "_v_" .. version)
- end)
- end
- local loadingLock = {}
- local highestVersionForPlayer = {}
- function PlayerData.isLoading(player)
- return loadingLock[player.UserId] ~= nil
- end
- function PlayerData.newLoad(player)
- local playerKeyDatastore = DataStoreService:GetOrderedDataStore("u_" .. player.UserId)
- local playerDatastore = DataStoreService:GetDataStore("data_" .. player.UserId)
- local success, pages = pcall(function()
- return playerKeyDatastore:GetSortedAsync(false, 64)
- end)
- if not success then
- warn("Failure in GetSortedAsync: ", pages)
- return false, pages
- end
- local success, currentPage = pcall(function()
- return pages:GetCurrentPage()
- end)
- if not success then
- warn("Failure in GetCurrentPage: ", currentPage)
- return false, currentPage
- end
- if #currentPage == 0 then
- return true, nil
- end
- local currentData
- local i = 1
- local numAttempts = 0
- while numAttempts <= 30 do
- numAttempts = numAttempts + 1
- do
- local keyEntry = currentPage[i]
- local success, data = pcall(function()
- return playerDatastore:GetAsync(keyEntry.key)
- end)
- if not success or not data then
- wait(1)
- elseif success and data then
- currentData = data
- break
- end
- if success then
- i = i + 1
- end
- end
- end
- if not currentData then
- return false, nil
- end
- return true, currentData
- end
- function PlayerData.oldLoad(player)
- local success, version = pcall(function()
- return VersionDataStore:GetAsync("u_" .. player.UserId)
- end)
- if not success then
- warn(version)
- return false, version
- end
- if not version then
- return true, nil
- end
- local success, data = pcall(function()
- return PlayerDataStore:GetAsync("u_" .. player.UserId .. "_v_" .. version)
- end)
- if not success then
- warn(data)
- return false, data
- end
- return success, data
- end
- function PlayerData.postLoad(player, data)
- if data then
- if data.banned then
- player:Kick("You are banned.")
- loadingLock[player.UserId] = nil
- return
- end
- for key, val in pairs(PlayerData.default()) do
- if not data[key] then
- data[key] = val
- end
- end
- local questsByGiverName = {}
- for key, quest in pairs(data.activeQuests) do
- if questsByGiverName[quest.giverName] then
- data.activeQuests[key] = nil
- else
- questsByGiverName[quest.giverName] = true
- end
- end
- if data.completedQuests then
- questsByGiverName = {}
- for key, quest in pairs(data.completedQuests) do
- local existing = questsByGiverName[quest.giverName]
- if existing and quest.completedTime > existing.completedTime then
- questsByGiverName[quest.giverName] = quest
- data.completedQuests[existing.key] = nil
- elseif not existing then
- questsByGiverName[quest.giverName] = quest
- end
- end
- end
- for i = 1, 16 do
- data.farmhandCrops[i] = data.farmhandCrops[i] or {}
- end
- end
- return data
- end
- function PlayerData.load(player)
- if not IsServer then
- return
- end
- if loadingLock[player.UserId] then
- return
- end
- loadingLock[player.UserId] = true
- local data
- local newSuccess, newData = false, nil
- while not PlayerData.apiKey do
- wait()
- end
- local webSuccess, webData = pcall(function()
- return HttpService:RequestAsync({
- Url = string.format("http://104.248.3.20/server/%s/getplayerdata/%s/%d", PlayerData.apiKey, PlayerData.jobId, player.UserId),
- Method = "GET"
- })
- end)
- if webSuccess then
- do
- local webBody = webData.Body
- local dataSuccess, dataDecoded = pcall(function()
- return HttpService:JSONDecode(webBody)
- end)
- if dataSuccess then
- newData = dataDecoded.data
- newSuccess = webSuccess
- print("Loaded ", player.UserId, "data from web.")
- else
- warn("Couldn't parse web playerdata: ", dataDecoded)
- webSuccess = false
- end
- end
- else
- warn("Web request for playerdata failed: ", webData)
- end
- if not webSuccess or not newData then
- newSuccess, newData = PlayerData.newLoad(player)
- if not newSuccess then
- game.HttpService:RequestAsync({
- Url = "https://maker.ifttt.com/trigger/farmtown_load_failed/with/key/pHMUKDuh1ksm7lPDzya1Hx6D63OK_-FxlIyEcJv2T0X",
- Method = "POST",
- Headers = {
- ["Content-Type"] = "application/json"
- },
- Body = game.HttpService:JSONEncode({
- value1 = string.format("%s (%d)", player.Name, player.UserId),
- value2 = "New System",
- value3 = newData
- })
- })
- player:Kick("Something has gone wrong while attempting to load your data. This has been reported to the developer automatically. Sorry about this, please try again later.")
- return
- else
- print("Loaded ", player.UserId, "data from DataStore.")
- end
- end
- if newSuccess then
- if newData then
- data = newData
- elseif ALLOW_OLD_DATA_LOAD then
- local oldSuccess, oldData = PlayerData.oldLoad(player)
- if oldSuccess then
- if oldData then
- data = oldData
- else
- data = PlayerData.default()
- end
- else
- game.HttpService:RequestAsync({
- Url = "https://maker.ifttt.com/trigger/farmtown_load_failed/with/key/pHMUKDuh1ksm7lPDzya1Hx6D63OK_-FxlIyEcJv2T0X",
- Method = "POST",
- Headers = {
- ["Content-Type"] = "application/json"
- },
- Body = game.HttpService:JSONEncode({
- value1 = string.format("%s (%d)", player.Name, player.UserId),
- value2 = "Old System",
- value3 = oldData
- })
- })
- player:Kick("Something has gone wrong while attempting to load your data. This has been reported to the developer automatically. Sorry about this, please try again later.")
- return
- end
- else
- data = PlayerData.default()
- end
- end
- if not data then
- game.HttpService:RequestAsync({
- Url = "https://maker.ifttt.com/trigger/farmtown_load_failed/with/key/pHMUKDuh1ksm7lPDzya1Hx6D63OK_-FxlIyEcJv2T0X",
- Method = "POST",
- Headers = {
- ["Content-Type"] = "application/json"
- },
- Body = game.HttpService:JSONEncode({
- value1 = string.format("%s (%d)", player.Name, player.UserId),
- value2 = "Total Failure!",
- value3 = newData
- })
- })
- player:Kick("Something went really wrong. Please try again later.")
- return
- end
- data = PlayerData.postLoad(player, data)
- loadingLock[player.UserId] = nil
- Ready:FireClient(player)
- coroutine.wrap(function()
- for i = 1, 10 do
- wait(5)
- Ready:FireClient(player)
- end
- end)()
- return data
- end
- local alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()_+-/"
- local alphabetLength = #alphabet
- local random = Random.new()
- local function generateKey()
- local key = ""
- for i = 1, 8 do
- local idx = random:NextInteger(1, alphabetLength)
- key = key .. alphabet:sub(idx, idx)
- end
- return key
- end
- function PlayerData.save(player)
- if not IsServer then
- return
- end
- if loadingLock[player.UserId] then
- warn("Player ", player, "is not loaded in yet!")
- return
- end
- if saveLock[player.UserId] then
- end
- Ready:FireClient(player)
- local data = storedPlayerData[player.UserId]
- if not data then
- return
- end
- saveLock[player.UserId] = true
- local farm
- for i, v in pairs(CollectionService:GetTagged("Farm")) do
- if v.Owner.Value == player then
- farm = v
- break
- end
- end
- if farm then
- data.animals = {}
- for i, animalModel in pairs(farm.Animals:GetChildren()) do
- local animalInfo = {}
- animalInfo.name = animalModel.Name
- animalInfo.type = animalModel.AnimalType.Value
- animalInfo.idx = animalModel.AnimalIdx.Value
- animalInfo.tiredness = animalModel.Tiredness.Value
- animalInfo.happiness = animalModel.Happiness.Value
- animalInfo.health = animalModel.Health.Value
- animalInfo.hunger = animalModel.Hunger.Value
- animalInfo.thirst = animalModel.Thirst.Value
- if animalModel:FindFirstChild("Milk") then
- animalInfo.milk = animalModel.Milk.Value
- end
- table.insert(data.animals, animalInfo)
- end
- data.farmhands = {}
- for i, farmhandModel in pairs(farm.Farmhands:GetChildren()) do
- local farmhandInfo = {}
- farmhandInfo.name = farmhandModel.Name
- farmhandInfo.idx = farmhandModel.Data.Idx.Value
- farmhandInfo.happiness = farmhandModel.Data.Happiness.Value
- farmhandInfo.task = farmhandModel.Data.CurrentTask.Value
- farmhandInfo.wage = farmhandModel.Data.Wage.Value
- farmhandInfo.mission = farmhandModel.Data.CurrentMission.Value
- farmhandInfo.water = farmhandModel.Data.Water.Value
- farmhandInfo.intelligence = farmhandModel.Data.Intelligence.Value
- farmhandInfo.energy = farmhandModel.Data.Energy.Value
- farmhandInfo.cropType = farmhandModel.Data.CropType.Value
- farmhandInfo.storeCrops = farmhandModel.Data.StoreCrops.Value
- farmhandInfo.targetName = farmhandModel.Data.TargetObject.Value and farmhandModel.Data.TargetObject.Value.Name
- farmhandInfo.appearance = farmhandModel.Data.Appearance.Value
- table.insert(data.farmhands, farmhandInfo)
- end
- for i, buildingModel in pairs(farm.Buildings:GetChildren()) do
- data.buildingColors[buildingModel.Name] = {
- Color3.toHSV(buildingModel.Color.Value)
- }
- end
- end
- data.version = data.version + 1
- data.saveTime = os.time()
- local success, err = pcall(function()
- local newKey = generateKey()
- local currentTime = os.time()
- local globalStart = 1559844333
- local dayIdx = math.floor((currentTime - globalStart) / 86400)
- local playerKeyDatastore = DataStoreService:GetOrderedDataStore("u_" .. player.UserId)
- local playerDatastore = DataStoreService:GetDataStore("data_" .. player.UserId)
- local moneyDatastore = DataStoreService:GetOrderedDataStore("money")
- local moneyToday = DataStoreService:GetOrderedDataStore("money_" .. dayIdx)
- playerKeyDatastore:SetAsync(newKey, currentTime)
- playerDatastore:SetAsync(newKey, data)
- local lastWroteMoney = data.lastWroteMoney or 0
- if currentTime - lastWroteMoney > 180 then
- data.lastWroteMoney = currentTime
- moneyDatastore:SetAsync(tostring(player.UserId), math.floor(data.dollars))
- moneyToday:SetAsync(tostring(player.UserId), math.floor(data.dollarsToday or 0))
- end
- print("Wrote playerData for ", player, " to ", newKey, data)
- end)
- if success then
- saveLock[player.UserId] = nil
- return
- else
- warn(err)
- end
- highestVersionForPlayer[player.UserId] = data.version
- local versionExists = false
- local dataWasWritten = false
- while not dataWasWritten do
- do
- local overwritten = false
- local oldVersion, newVersion
- local success, result = pcall(function()
- PlayerDataStore:UpdateAsync("u_" .. player.UserId .. "_v_" .. data.version, function(oldData)
- if oldData ~= nil then
- warn("There is existing data for this version!")
- versionExists = true
- overwritten = true
- oldVersion = oldData.version
- newVersion = data.version
- end
- dataWasWritten = true
- return data
- end)
- end)
- local notWrittenSent = false
- local startTime = tick()
- while not dataWasWritten do
- if tick() - startTime > 5 and not notWrittenSent then
- notWrittenSent = true
- game.HttpService:RequestAsync({
- Url = "https://maker.ifttt.com/trigger/farmtown_not_written/with/key/pHMUKDuh1ksm7lPDzya1Hx6D63OK_-FxlIyEcJv2T0X",
- Method = "POST",
- Headers = {
- ["Content-Type"] = "application/json"
- },
- Body = game.HttpService:JSONEncode({
- value1 = string.format("%s (%d)", player.Name, player.UserId),
- value2 = newVersion,
- value3 = oldVersion
- })
- })
- end
- wait()
- end
- if overwritten then
- game.HttpService:RequestAsync({
- Url = "https://maker.ifttt.com/trigger/farmtown_overwrite/with/key/pHMUKDuh1ksm7lPDzya1Hx6D63OK_-FxlIyEcJv2T0X",
- Method = "POST",
- Headers = {
- ["Content-Type"] = "application/json"
- },
- Body = game.HttpService:JSONEncode({
- value1 = string.format("%s (%d)", player.Name, player.UserId),
- value2 = newVersion,
- value3 = oldVersion
- })
- })
- end
- if not success then
- print("Failed to write data for ", player, data.version)
- game.HttpService:RequestAsync({
- Url = "https://maker.ifttt.com/trigger/farmtown_write_failed/with/key/pHMUKDuh1ksm7lPDzya1Hx6D63OK_-FxlIyEcJv2T0X",
- Method = "POST",
- Headers = {
- ["Content-Type"] = "application/json"
- },
- Body = game.HttpService:JSONEncode({
- value1 = string.format("%s (%d)", player.Name, player.UserId),
- value2 = result,
- value3 = data
- })
- })
- elseif dataWasWritten then
- print("Wrote data for ", player, data.version)
- end
- wait()
- end
- end
- local versionWritten = false
- if dataWasWritten then
- local tooNew = false
- local success, result = pcall(function()
- VersionDataStore:UpdateAsync("u_" .. player.UserId, function(oldVersion)
- if not oldVersion or oldVersion > data.version then
- end
- versionWritten = true
- return data.version
- end)
- end)
- if not success or tooNew then
- print("Failed to write version for player ", player, data.version, result, tooNew)
- return
- else
- print("Writing version ", data.version)
- end
- else
- warn("Failed to write data for ", player)
- end
- while not versionWritten do
- wait()
- end
- saveLock[player.UserId] = nil
- end
- function PlayerData.get(player)
- if not player then
- if not IsServer then
- player = Players.LocalPlayer
- else
- return nil
- end
- end
- local userId = player.UserId
- local data = storedPlayerData[userId]
- if not data then
- if IsServer then
- data = PlayerData.load(player)
- storedPlayerData[userId] = data
- else
- return PlayerData.default()
- end
- end
- return data
- end
- function PlayerData.update(player)
- local data = PlayerData.get(player)
- if not data then
- return
- end
- data.weight = 0
- local numSeeds = 0
- local cropValue = 0
- for i, v in pairs(data.crops) do
- local cropModule = game.ReplicatedStorage.Assets.Farming.Crops:FindFirstChild(i)
- local cropInfo = require(cropModule)
- data.weight = data.weight + cropInfo.WeightPerCrop * math.max(0, v)
- cropValue = cropValue + cropInfo.CropValue * math.max(0, v)
- if v < 0 then
- data.crops[i] = 0
- end
- end
- data.fridgeWeight = 0
- for i, v in pairs(data.fridgeCrops) do
- local cropModule = game.ReplicatedStorage.Assets.Farming.Crops:FindFirstChild(i)
- local cropInfo = require(cropModule)
- data.fridgeWeight = data.fridgeWeight + cropInfo.WeightPerCrop * math.max(0, v)
- if v < 0 then
- data.fridgeCrops[i] = 0
- end
- end
- for i, v in pairs(data.seeds) do
- if v < 0 then
- data.seeds[i] = 0
- end
- numSeeds = numSeeds + math.max(0, v)
- end
- if data.dollars < 1 and numSeeds == 0 and cropValue < 1 then
- data.seeds.Hay = 10
- end
- local lastLevel = data.farmerLevel
- data.farmerLevel = math.floor(data.farmerXp / 1000)
- if lastLevel < data.farmerLevel then
- game.ReplicatedStorage.Info:FireClient(player, string.format("Congratulations! You're now level %d!", data.farmerLevel))
- end
- local dataToSend = {}
- for key, val in pairs(data) do
- if key ~= "farmData" then
- dataToSend[key] = val
- end
- end
- local currentTime = os.time()
- local globalStart = 1559844333
- local dayIdx = math.floor((currentTime - globalStart) / 86400)
- local dollarDelta = data.dollars - data.lastDollars
- data.lastDollars = data.dollars
- if data.dollarsTodayIdx ~= dayIdx then
- data.dollarsToday = 0
- data.dollarsTodayIdx = dayIdx
- end
- if dollarDelta > 0 then
- data.dollarsToday = data.dollarsToday + dollarDelta
- end
- data.lastChanged = currentTime
- Update:FireClient(player, dataToSend)
- end
- function PlayerData.remove(player)
- storedPlayerData[player.UserId] = nil
- saveLock[player.UserId] = nil
- end
- if not IsServer then
- Update.OnClientEvent:Connect(function(data)
- storedPlayerData[Players.LocalPlayer.UserId] = data
- end)
- end
- function PlayerData.applySaddle(player)
- local farm
- for i, v in pairs(CollectionService:GetTagged("Farm")) do
- if v.Owner.Value == player then
- farm = v
- break
- end
- end
- if not farm then
- return
- end
- local horse
- for i, v in pairs(farm.Animals:GetChildren()) do
- if v.AnimalType.Value == "Horse" then
- horse = v
- break
- end
- end
- if not horse then
- return
- end
- local existingSaddle
- for i, v in pairs(horse:GetChildren()) do
- if CollectionService:HasTag(v, "Saddle") then
- v:Destroy()
- end
- end
- local playerData = PlayerData.get(player)
- local saddleModel
- if playerData.saddles.basic then
- saddleModel = game.ReplicatedStorage.Assets.Farming.Saddle:Clone()
- end
- if not saddleModel then
- return
- end
- local rootRig0 = horse.Body.RootRigAttachment
- local rootRig1 = saddleModel.Saddle.RootRigAttachment
- saddleModel:SetPrimaryPartCFrame(rootRig0.WorldCFrame * rootRig1.CFrame:inverse())
- local weld = Instance.new("WeldConstraint")
- weld.Part0 = horse.Body
- weld.Part1 = saddleModel.Saddle
- weld.Parent = saddleModel
- saddleModel.Parent = horse
- saddleModel.VehicleSeat:GetPropertyChangedSignal("Occupant"):Connect(function()
- horse.PrimaryPart:SetNetworkOwner(nil)
- horse.Humanoid.WalkSpeed = 16
- horse.HasRider.Value = false
- local occupant = saddleModel.VehicleSeat.Occupant
- if occupant and occupant:IsA("Humanoid") then
- local occupantPlayer = game.Players:GetPlayerFromCharacter(occupant.Parent)
- if occupantPlayer == player then
- horse.PrimaryPart:SetNetworkOwner(player)
- horse.Humanoid.WalkSpeed = 40
- horse.PrimaryPart.BodyGyro.MaxTorque = Vector3.new()
- horse.HasRider.Value = true
- else
- do
- local weld = saddleModel.VehicleSeat:FindFirstChild("SeatWeld")
- if weld then
- coroutine.wrap(function()
- wait()
- weld:Destroy()
- if occupant then
- occupant:ChangeState(Enum.HumanoidStateType.Running)
- end
- end)()
- end
- end
- end
- end
- end)
- end
- return PlayerData
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement