I was really unhappy with my messy data storage system which had a lot of repeated code and adding new stats was overly complicated forcing you to add 4+ lines for every single stat. Idk why but I just feel like this could be improved. I am going to make it store versions of your data just in case. But anyway’s I tried making it a bit more performant by just removing some junk code but anyway’s here it is
Roast me hard for the code XD I coded this live in like 3 hours. Without sleep ;(
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local DataStorage = game:GetService("DataStoreService")
local Datastore = DataStorage:GetDataStore("Game_Data_01")
local DataTable = {}
local HttpService = game:GetService("HttpService")
local WebHook = ""
local days = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}
local months = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}
local function LogMessage(Message, Player, ScriptName)
if Player then
Player = tostring(Player)
else
Player = "Server"
end
if not ScriptName then
ScriptName = "Not Specified"
end
local Time = os.date("*t", os.time())
if Time.sec < 10 then
Time.sec = "0" .. Time.sec
end
if Time.min < 10 then
Time.min = "0" .. Time.min
end
if Time.hour < 10 then
Time.hour = "0" .. Time.hour
end
local Data = {
["content"] = tostring("```ini" .. "\n" .. "[Sent by:] " .. Player .. "\n" .. "[Date:] " .. Time.year .. ", " .. months[Time.month] .. ", " .. days[Time.wday] .. " " .. Time.hour .. ":" .. Time.min .. ":" .. Time.sec .. "\n" .. "[Script Location:] " .. ScriptName .. "\n" .. "[Message:] " .. tostring(Message) .. "```")
}
Data = HttpService:JSONEncode(Data)
HttpService:PostAsync(WebHook, Data)
end
local function LoadDataIndexes(Player)
local Stats = Player.Data
local success, PlayerData = pcall(function() return Datastore:GetAsync(Player.UserId) end)
if success then
if PlayerData then
for i,v in pairs(PlayerData) do
if typeof(v[2]) == "table" then
local Stat = Stats:FindFirstChild(v[1])
if Stat then
Stat.Value = Vector3.new(v[2][1], v[2][2], v[2][3])
end
else
local Stat = Stats:FindFirstChild(v[1])
if Stat then
Stat.Value = v[2]
end
end
end
else
return
end
else
Player:Kick("Data failed to load!")
LogMessage(PlayerData, Player.Name, script.Parent:GetFullName())
end
end
local function SaveDataIndexes(Player)
local Stats = Player.Data
local DataFile = {}
for i,v in pairs(DataTable[Player.Name]) do
local Stat = Stats:FindFirstChild(v[1])
if Stat then
if Stat:IsA("Vector3Value") then
table.insert(DataFile, {v[1], {Stat.Value.X, Stat.Value.Y, Stat.Value.Z}})
else
table.insert(DataFile, {v[1], Stat.Value})
end
end
end
Datastore:SetAsync(Player.UserId, DataFile)
return
end
local function AddNonSaveDataIndex(Player, Name, TypeOfData, Value)
local Stats = Player.Data
local success = pcall(function()
local IndexObject = Instance.new(TypeOfData, Stats)
IndexObject.Name = Name
IndexObject.Value = Value
return
end)
if not success then
print("Something's wrong there chief with the index : " .. Name .. " | The TypeOf is " .. TypeOfData)
end
end
local function AddDataIndex(Player, Name, TypeOfData, Value)
local Stats = Player.Data
local success = pcall(function()
local IndexObject = Instance.new(TypeOfData, Stats)
IndexObject.Name = Name
IndexObject.Value = Value
return
end)
if success then
local Index = {Name, TypeOfData, Value}
table.insert(DataTable[Player.Name], Index)
else
print("Something's wrong there chief with the index : " .. Name .. " | The TypeOf is " .. TypeOfData)
end
end
local function CreateDataFile(Player)
local Stats = Instance.new("Folder", Player)
Stats.Name = "Data"
local Data = {}
DataTable[Player.Name] = Data
return(DataTable[Player.Name])
end
local function LoadData(Player)
local DataFile = CreateDataFile(Player)
AddDataIndex(Player, "Yen", "IntValue", 0)
AddDataIndex(Player, "Physical_Resistance", "IntValue", 0)
AddDataIndex(Player, "Physical_Strength", "IntValue", 0)
AddDataIndex(Player, "Mental_Strength", "IntValue", 0)
AddDataIndex(Player, "Mental_Resistance", "IntValue", 0)
AddDataIndex(Player, "Reaction_Speed", "IntValue", 0)
AddDataIndex(Player, "Endurance", "IntValue", 0)
AddDataIndex(Player, "Flexibility", "IntValue", 0)
AddDataIndex(Player, "LastPosition", "Vector3Value", Vector3.new(0,0,0))
AddDataIndex(Player, "LastRotation", "Vector3Value", Vector3.new(0,0,0))
AddNonSaveDataIndex(Player, "UseDebounce", "BoolValue", false)
LoadDataIndexes(Player)
end
local function UpdatePlayerLastPosition(Player)
local Stats = Player:FindFirstChild("Data")
local HumanoidRootPart = Player.Character:FindFirstChild("HumanoidRootPart")
if Stats and HumanoidRootPart then
local LastPosition = Stats:FindFirstChild("LastPosition")
LastPosition.Value = HumanoidRootPart.Position
local LastRotation = Stats:FindFirstChild("LastRotation")
LastRotation.Value = HumanoidRootPart.Rotation
end
end
game.Players.PlayerAdded:Connect(function(Player)
local GroupRank = Player:GetRoleInGroup(5019006)
if GroupRank == nil or GroupRank == "Supporter" then
Player:Kick("Sorry closed for testing")
return
else
LoadData(Player)
local Data = Player:WaitForChild("Data")
local LastPosition = Data:WaitForChild("LastPosition")
local LastRotation = Data:WaitForChild("LastRotation")
local Character = game.Workspace:WaitForChild(Player.Name)
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
HumanoidRootPart.CFrame = CFrame.Angles(math.rad(LastRotation.Value.X), math.rad(LastRotation.Value.Y), math.rad(LastRotation.Value.Z)) + CFrame.new(LastPosition.Value.X, LastPosition.Value.Y, LastPosition.Value.Z).p
end
end)
game.Players.PlayerRemoving:Connect(function(Player)
if #game.Players:GetPlayers() ~= 1 then
UpdatePlayerLastPosition(Player)
SaveDataIndexes(Player)
end
end)
game:BindToClose(function()
for each,Player in pairs(game.Players:GetPlayers()) do
UpdatePlayerLastPosition(Player)
SaveDataIndexes(Player)
end
end)
while wait(60) do
for each,Player in pairs(game.Players:GetPlayers()) do
UpdatePlayerLastPosition(Player)
SaveDataIndexes(Player)
end
end