| 1 |
-- Data saving monstrocity |
| 2 |
-- Andrew Bereza |
| 3 |
local Saving = require(game.ServerScriptService.Saving) |
| 4 |
local Utl = require(game.ServerScriptService.Utl) |
| 5 |
local function SaveData(Player) |
| 6 |
pcall(function() |
| 7 |
Utl.CheckPasses(Player) |
| 8 |
end) |
| 9 |
local PlayerData = Utl.GetPlayerData(Player.userId) |
| 10 |
if Player:FindFirstChild("DataLoaded") and PlayerData ~= nil then |
| 11 |
PlayerData.Inventory = PlayerData.Inventory |
| 12 |
PlayerData.BaseData = PlayerData.BaseData |
| 13 |
PlayerData.Emblems = PlayerData.Emblems |
| 14 |
PlayerData.Storage = PlayerData.Storage |
| 15 |
PlayerData.XP = (Player:FindFirstChild("XP") and math.ceil(Player.XP.Value)) |
| 16 |
PlayerData.Level = (Player:FindFirstChild("Level") and Player.Level.Value) |
| 17 |
PlayerData.Pickaxe = (Player:FindFirstChild("Pickaxe") and Player.Pickaxe.Value) |
| 18 |
PlayerData.Mute = (Player:FindFirstChild("Mute") and Utl.BoolToInt(Player.Mute.Value)) |
| 19 |
PlayerData.Gold = (Player:FindFirstChild("Gold") and Player.Gold.Value) |
| 20 |
PlayerData.DiscordAward = (Player:FindFirstChild("DiscordAward") and Player.DiscordAward.Value) |
| 21 |
PlayerData.Crystals = (Player:FindFirstChild("Crystals") and Player.Crystals.Value) |
| 22 |
PlayerData.LastGift = (Player:FindFirstChild("LastGift") and Player.LastGift.Value) |
| 23 |
PlayerData.Emblem = (Player:FindFirstChild("Emblem") and Player.Emblem.Value) |
| 24 |
PlayerData.Tutorial = (Player:FindFirstChild("Tutorial") and Player.Tutorial.Value) |
| 25 |
PlayerData.GoldQuest = (Player:FindFirstChild("GoldQuest") and Player.GoldQuest.Value) |
| 26 |
PlayerData.EventStatus = (Player:FindFirstChild("EventStatus") and Player.EventStatus.Value) |
| 27 |
-- Use difference from when they joined and now to record total playtime |
| 28 |
if PlayerData.TimeStamp and PlayerData.TimeStamp > 0 then |
| 29 |
PlayerData.TotalPlaytime = PlayerData.TotalPlaytime + (PlayerData.TimeStamp - os.time()) |
| 30 |
end |
| 31 |
-- aaand reset TimeStamp |
| 32 |
PlayerData.TimeStamp = os.time() |
| 33 |
PlayerData.LifetimeOreTotal = PlayerData.LifetimeOreTotal |
| 34 |
local Success, Error = Saving.SaveData(Player, PlayerData) |
| 35 |
print("Saving Results") |
| 36 |
print(Success, Error) |
| 37 |
-- Attempt to save their billboard data, but don't let it interfere with important data |
| 38 |
spawn(function() |
| 39 |
pcall(function() |
| 40 |
local Leaderboard = game:GetService("DataStoreService"):GetOrderedDataStore("TopMiner"..tostring(Utl.CurrentDay())) |
| 41 |
Leaderboard:IncrementAsync(Player.userId, Player.OreMined.Value) |
| 42 |
PlayerData.LifetimeOreTotal = PlayerData.LifetimeOreTotal + Player.OreMined.Value |
| 43 |
Player.OreMined.Value = 0 |
| 44 |
end) |
| 45 |
end) |
| 46 |
return Success, Error |
| 47 |
end |
| 48 |
end |
| 49 |
local function LoadData(Player, RequestedTime) |
| 50 |
if game.ServerStorage.WorthlessGarbage:FindFirstChild(Player.Name) then |
| 51 |
game.ServerStorage.WorthlessGarbage:FindFirstChild(Player.Name):Destroy() |
| 52 |
end |
| 53 |
pcall(function() |
| 54 |
Utl.CheckPasses(Player) |
| 55 |
end) |
| 56 |
local Success, PlayerData, Error, TimeStamp = Saving.LoadData(Player) |
| 57 |
TimeStamp = TimeStamp or 0 |
| 58 |
if not Success then |
| 59 |
return Success, Error |
| 60 |
elseif RequestedTime and RequestedTime > 1 then |
| 61 |
if (RequestedTime - 1) >= (TimeStamp) then |
| 62 |
return false, "Waiting for newer data" |
| 63 |
end |
| 64 |
end |
| 65 |
PlayerData.DiscordAward = PlayerData.DiscordAward or 0 |
| 66 |
PlayerData.LifetimeOreTotal = PlayerData.LifetimeOreTotal or 0 |
| 67 |
PlayerData.TotalPlaytime = PlayerData.TotalPlaytime or 0 |
| 68 |
PlayerData["Inventory"] = PlayerData["Inventory"] or {} |
| 69 |
PlayerData["Storage"] = PlayerData["Storage"] or {} |
| 70 |
PlayerData["BaseData"] = PlayerData["BaseData"] or {} |
| 71 |
PlayerData["Emblems"] = PlayerData["Emblems"] or {} |
| 72 |
PlayerData["Pickaxes"] = PlayerData["Pickaxes"] or {} |
| 73 |
PlayerData.TimeStamp = os.time() |
| 74 |
for i,Pickaxe in pairs(game.ReplicatedStorage.Pickaxes:GetChildren()) do |
| 75 |
PlayerData.Pickaxes[Pickaxe.Name] = PlayerData.Pickaxes[Pickaxe.Name] or false |
| 76 |
end |
| 77 |
if PlayerData.Pickaxe ~= nil then |
| 78 |
PlayerData.Pickaxes[PlayerData.Pickaxe] = true |
| 79 |
end |
| 80 |
for i,Ore in pairs(game.ReplicatedStorage.Ores:GetChildren()) do |
| 81 |
PlayerData.Inventory[Ore.Name] = PlayerData.Inventory[Ore.Name] or 0 |
| 82 |
PlayerData.Storage[Ore.Name] = PlayerData.Storage[Ore.Name] or 0 |
| 83 |
end |
| 84 |
for i,Item in pairs(game.ServerStorage.BaseParts:GetChildren()) do |
| 85 |
PlayerData.BaseData[Item.Name] = PlayerData.BaseData[Item.Name] or 0 |
| 86 |
end |
| 87 |
for i,Emblem in pairs(game.ReplicatedStorage.Emblems:GetChildren()) do |
| 88 |
PlayerData.Emblems[Emblem.Name] = PlayerData.Emblems[Emblem.Name] or false |
| 89 |
end |
| 90 |
Utl.NewPlayerData(Player, PlayerData) |
| 91 |
--Temp value for storing ore counts every session |
| 92 |
local OreMined = Instance.new("IntValue") |
| 93 |
OreMined.Name = "OreMined" |
| 94 |
OreMined.Value = 0 |
| 95 |
OreMined.Parent = Player |
| 96 |
--Value for gold quest |
| 97 |
-- EVENT CLAUSE |
| 98 |
local GoldQuest = Instance.new("StringValue") |
| 99 |
GoldQuest.Name = "GoldQuest" |
| 100 |
if PlayerData.GoldQuest ~= "Done" and PlayerData.GoldQuest ~= "Started" and PlayerData.GoldQuest ~= "Awarded" then |
| 101 |
PlayerData.GoldQuest = "" |
| 102 |
end |
| 103 |
GoldQuest.Value = PlayerData.GoldQuest or "" |
| 104 |
GoldQuest.Parent = Player |
| 105 |
local Tag = Instance.new("BoolValue") |
| 106 |
Tag.Name = "Loading" |
| 107 |
Tag.Parent = Player |
| 108 |
local Emblem = Instance.new("StringValue") |
| 109 |
Emblem.Name = "Emblem" |
| 110 |
Emblem.Value = PlayerData["Emblem"] or "" |
| 111 |
Emblem.Parent = Player |
| 112 |
local XP = Instance.new("NumberValue") |
| 113 |
XP.Name = "XP" |
| 114 |
XP.Value = PlayerData["XP"] or 0 |
| 115 |
XP.Parent = Player |
| 116 |
local Level = Instance.new("IntValue") |
| 117 |
Level.Name = "Level" |
| 118 |
Level.Value = PlayerData["Level"] or 1 |
| 119 |
Level.Parent = Player |
| 120 |
local Gold = Instance.new("NumberValue") |
| 121 |
Gold.Name = "Gold" |
| 122 |
Gold.Value = PlayerData["Gold"] or 50 |
| 123 |
Gold.Parent = Player |
| 124 |
local DiscordAward = Instance.new("IntValue") |
| 125 |
DiscordAward.Name = "DiscordAward" |
| 126 |
DiscordAward.Value = PlayerData["DiscordAward"] or 0 |
| 127 |
DiscordAward.Parent = Player |
| 128 |
local Crystals = Instance.new("NumberValue") |
| 129 |
Crystals.Name = "Crystals" |
| 130 |
Crystals.Value = PlayerData["Crystals"] or 0 |
| 131 |
Crystals.Parent = Player |
| 132 |
local LastGift = Instance.new("IntValue") |
| 133 |
LastGift.Name = "LastGift" |
| 134 |
LastGift.Value = PlayerData["LastGift"] or 0 |
| 135 |
LastGift.Parent = Player |
| 136 |
local Pickaxe = Instance.new("StringValue") |
| 137 |
Pickaxe.Name = "Pickaxe" |
| 138 |
Pickaxe.Value = PlayerData["Pickaxe"] or "Stone" |
| 139 |
Pickaxe.Parent = Player |
| 140 |
local Mute = Instance.new("BoolValue") |
| 141 |
Mute.Name = "Mute" |
| 142 |
Mute.Value = Utl.IntToBool(PlayerData["Mute"]) or false |
| 143 |
Mute.Parent = Player |
| 144 |
local Tutorial = Instance.new("IntValue") |
| 145 |
Tutorial.Name = "Tutorial" |
| 146 |
if Level.Value > 4 then |
| 147 |
Tutorial.Value = -1 -- ya youre done |
| 148 |
elseif PlayerData["BaseData"]["Teleporter"] > 0 and PlayerData["Tutorial"] and PlayerData["Tutorial"] == 0 then |
| 149 |
Tutorial.Value = 1 |
| 150 |
else |
| 151 |
Tutorial.Value = PlayerData["Tutorial"] or 0 |
| 152 |
end |
| 153 |
Tutorial.Parent = Player |
| 154 |
-- not related to data |
| 155 |
local TPPad = Instance.new("ObjectValue") |
| 156 |
TPPad.Name = "TPPad" |
| 157 |
TPPad.Parent = Player |
| 158 |
XP.Changed:connect(function() |
| 159 |
local RealLevel = game.ReplicatedStorage.Levels:FindFirstChild(Level.Value) |
| 160 |
if RealLevel and RealLevel:FindFirstChild("AdvanceXP") then |
| 161 |
if XP.Value >= RealLevel.AdvanceXP.Value then |
| 162 |
Level.Value = Level.Value + 1 |
| 163 |
XP.Value = XP.Value - RealLevel.AdvanceXP.Value |
| 164 |
end |
| 165 |
end |
| 166 |
end) |
| 167 |
Level.Changed:connect(function() |
| 168 |
if Player.Character and Player.Character:FindFirstChild("PlayerBillboard") then |
| 169 |
local RealLevel = game.ReplicatedStorage.Levels:FindFirstChild(Level.Value) |
| 170 |
if RealLevel then |
| 171 |
Player.Character.PlayerBillboard.Username.TextColor3 = RealLevel.Color.Value |
| 172 |
end |
| 173 |
end |
| 174 |
end) |
| 175 |
local Tycoon = Utl.GetEmptyTycoon() |
| 176 |
Tycoon.Owner.Value = Player |
| 177 |
if Player:FindFirstChild("Loading") then |
| 178 |
Player.Loading:Destroy() |
| 179 |
end |
| 180 |
local SuccessTag = Instance.new("BoolValue") |
| 181 |
SuccessTag.Name = "DataLoaded" |
| 182 |
SuccessTag.Parent = Player |
| 183 |
game.ServerStorage.PlayerLoaded:Fire(Player) |
| 184 |
spawn(function() |
| 185 |
wait(1) |
| 186 |
local success = pcall(function() |
| 187 |
if Player.Character then |
| 188 |
Player.Character:Destroy() |
| 189 |
Player.Character = nil |
| 190 |
end |
| 191 |
Player:LoadCharacter() |
| 192 |
end) |
| 193 |
if not success then |
| 194 |
wait() |
| 195 |
Player.Character = nil |
| 196 |
Player:LoadCharacter() |
| 197 |
end |
| 198 |
wait(1) |
| 199 |
-- game.ReplicatedStorage.ShowSplash:FireClient(Player,1) |
| 200 |
game.ReplicatedStorage.Announce:FireClient(Player,"Welcome back!",3,Color3.new(0,0.7,0.7)) |
| 201 |
end) |
| 202 |
-- Autosave |
| 203 |
spawn(function() |
| 204 |
local WaitAmount = 180 |
| 205 |
while wait(WaitAmount) do |
| 206 |
if Player and Player.Parent == game.Players and not ShuttingDown then |
| 207 |
local Success = SaveData(Player) |
| 208 |
if Success then |
| 209 |
if WaitAmount == 3 then |
| 210 |
game.ReplicatedStorage.Announce:FireClient(Player,"Data autosaved successfully!",2,Color3.new(0.7,0.7,0.7)) |
| 211 |
end |
| 212 |
WaitAmount = 180 |
| 213 |
elseif Success == nil then |
| 214 |
game.ReplicatedStorage.Announce:FireClient(Player,"Could not locate save data. AutoSave disabled.",30,Color3.new(1,0.5,0.5)) |
| 215 |
break |
| 216 |
elseif Success == false then |
| 217 |
if WaitAmount == 180 then |
| 218 |
game.ReplicatedStorage.Announce:FireClient(Player,"AutoSave failed. Re-trying...",5,Color3.new(1,0.7,0.7)) |
| 219 |
WaitAmount = 3 |
| 220 |
else |
| 221 |
game.ReplicatedStorage.Announce:FireClient(Player,"AutoSave failed again. ROBLOX servers may be down.",7,Color3.new(1,0.7,0.7)) |
| 222 |
WaitAmount = 180 |
| 223 |
end |
| 224 |
end |
| 225 |
else |
| 226 |
break |
| 227 |
end |
| 228 |
end |
| 229 |
end) |
| 230 |
return true |
| 231 |
end |
| 232 |
function game.ReplicatedStorage.LoadData.OnServerInvoke(Player, RequestedTime) |
| 233 |
if Player:FindFirstChild("Loading") == nil and Player:FindFirstChild("DataLoaded") == nil then |
| 234 |
local Tag = Instance.new("BoolValue") |
| 235 |
Tag.Name = "Loading" |
| 236 |
Tag.Parent = Player |
| 237 |
local Success, Error = LoadData(Player, RequestedTime) |
| 238 |
return Success,Error |
| 239 |
end |
| 240 |
end |
| 241 |
--[[ |
| 242 |
game.Players.PlayerAdded:connect(LoadData) |
| 243 |
for i,Player in pairs(game.Players:GetPlayers()) do |
| 244 |
LoadData(Player) |
| 245 |
end |
| 246 |
]] |
| 247 |
function game.ReplicatedStorage.GetData.OnServerInvoke(Player) |
| 248 |
return Utl.GetPlayerData(Player.userId) |
| 249 |
end |
| 250 |
local function PlayerLeaving(Player) |
| 251 |
local Success = SaveData(Player) |
| 252 |
-- TODO: PlayerLeaving fo real |
| 253 |
--wipe data on server |
| 254 |
local Tycoon = Utl.GetTycoon(Player) |
| 255 |
if Tycoon then |
| 256 |
Tycoon.Owner.Value = nil |
| 257 |
end |
| 258 |
local Datafile = game.ServerStorage.PlayerData:FindFirstChild(tostring(Player.userId)) |
| 259 |
if Datafile then |
| 260 |
Datafile:Destroy() |
| 261 |
end |
| 262 |
return Success |
| 263 |
end |
| 264 |
game.Players.PlayerRemoving:connect(PlayerLeaving) |
| 265 |
game.OnClose = function() |
| 266 |
if game:GetService("RunService"):IsRunMode() then |
| 267 |
return false |
| 268 |
end |
| 269 |
ShuttingDown = true |
| 270 |
for i,Player in pairs(game.Players:GetPlayers()) do |
| 271 |
game.ReplicatedStorage.Announce:FireClient(Player,"SERVER RESTARTING FOR UPDATE. REJOIN AFTER SHUTDOWN",30,Color3.new(0.9,0.8,0.2)) |
| 272 |
game.ReplicatedStorage.Announce:FireClient(Player,"Your data is being saved.",30,Color3.new(0.5,0.9,0.2)) |
| 273 |
local Success = PlayerLeaving(Player) |
| 274 |
if Success then |
| 275 |
game.ReplicatedStorage.Announce:FireClient(Player,"Data saved successfully, feel free to go!",3,Color3.new(0.5,0.9,0.2)) |
| 276 |
else |
| 277 |
game.ReplicatedStorage.Announce:FireClient(Player,"Data failed to save!",10,Color3.new(1,0.5,0.2)) |
| 278 |
end |
| 279 |
end |
| 280 |
local e = 1 |
| 281 |
for i=1,5000 do |
| 282 |
e = e + 3 |
| 283 |
wait() |
| 284 |
end |
| 285 |
end |
Комментарии