i see youve got it to work, looks really good
Hmm, I can’t get it to work
My script (changed it so it’s only one server script):
-- Services
local DataStoreService = game:GetService("DataStoreService")
local recordStore = DataStoreService:GetDataStore("RecordStore")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
-- Constants
local MAX_CHUNK_SIZE = 500000 -- Define a safe chunk size well below 4MB
-- Variables
local Possessions = {}
local replaying = false
local recording
local regionSize = Vector3.new(50, 50, 50)
local Tracked = {}
-- Unique ID generator
local function generateUniqueId()
return tostring(math.random(100000, 999999))
end
-- Function to save blocks and players in an area
local function saveBlocksAndPlayersAroundCheater(player)
local position = player.Character.HumanoidRootPart.Position
local region = Region3.new(position - (regionSize / 2), position + (regionSize / 2))
local parts = workspace:FindPartsInRegion3(region, nil, math.huge)
local frameData = { blocks = {}, players = {} }
for _, part in ipairs(parts) do
if part:IsA("BasePart") then
if not Tracked[part] then
Tracked[part] = true
end
part:SetAttribute("UniqueId", part:GetAttribute("UniqueId") or generateUniqueId())
table.insert(frameData.blocks, {
uniqueId = part:GetAttribute("UniqueId"),
name = part.Name,
size = {part.Size.X, part.Size.Y, part.Size.Z},
position = {part.Position.X, part.Position.Y, part.Position.Z},
rotation = {part.Orientation.X, part.Orientation.Y, part.Orientation.Z},
color = part.BrickColor.Name,
material = part.Material.Name,
transparency = part.Transparency,
reflectance = part.Reflectance
})
end
if part.Parent:FindFirstChild("Humanoid") then
local playerName = part.Parent.Name
if not table.find(frameData.players, playerName) then
table.insert(frameData.players, playerName)
end
end
end
return frameData
end
-- Function to disable joints and anchor parts
local function disableJoints(rig)
for _, v in pairs(rig:GetDescendants()) do
if v:IsA("JointInstance") then
if v.Part0.Parent ~= rig or v.Part1.Parent ~= rig then
continue
end
v.Enabled = false
elseif v:IsA("BasePart") and v.Parent == rig then
v.Anchored = true
v.CanCollide = false
end
end
end
-- Function to start replay
local function startReplay(currentPossession)
if recording or replaying or currentPossession > #Possessions then
return
end
replaying = true
local Models = {}
local tb = Possessions[currentPossession]
for part, _ in pairs(Tracked) do
part.Archivable = true
local rig = part:Clone()
rig.Parent = workspace
disableJoints(rig)
part.Archivable = false
Models[part.Name] = rig
end
for _, gotPossession in pairs(tb) do
for character, bodyParts in pairs(gotPossession) do
if typeof(bodyParts) == "CFrame" then
Models[character].CFrame = bodyParts
else
for i, v in pairs(bodyParts) do
Models[character][i].CFrame = v
end
end
end
wait()
end
for _, v in pairs(Models) do
v:Destroy()
end
Models = nil
replaying = false
end
-- Function to start recording
local function startRecording(player)
if replaying then return end
if recording then
recording:Disconnect()
recording = nil
print("Recording stopped")
return
end
Possessions[#Possessions + 1] = {}
print("Recording started")
local time = 0
recording = RunService.Heartbeat:Connect(function()
local frameData = saveBlocksAndPlayersAroundCheater(player)
Possessions[#Possessions][time] = frameData
time += 1
end)
end
-- Function to split data into chunks for DataStore
local function splitIntoChunks(data)
local jsonData = game:GetService("HttpService"):JSONEncode(data)
local chunks = {}
for i = 1, #jsonData, MAX_CHUNK_SIZE do
local chunk = jsonData:sub(i, math.min(i + MAX_CHUNK_SIZE - 1, #jsonData))
table.insert(chunks, chunk)
end
return chunks
end
-- Function to save the recording to DataStore in chunks
local function saveRecording(name)
local success, err = pcall(function()
local chunks = splitIntoChunks(Possessions)
-- Save each chunk with a unique key
for i, chunk in ipairs(chunks) do
recordStore:SetAsync(name .. "_Chunk_" .. i, chunk)
end
-- Save the number of chunks
recordStore:SetAsync(name .. "_Meta", { chunkCount = #chunks })
end)
if success then
print("Recording saved as", name)
else
warn("Error saving recording:", err)
end
end
-- Function to load the recording from DataStore in chunks
local function loadRecording(name)
local success, data = pcall(function()
local meta = recordStore:GetAsync(name .. "_Meta")
if not meta then
warn("No metadata found for recording:", name)
return nil
end
local chunks = {}
for i = 1, meta.chunkCount do
local chunk = recordStore:GetAsync(name .. "_Chunk_" .. i)
if chunk then
table.insert(chunks, chunk)
end
end
-- Concatenate all chunks and decode JSON
local jsonData = table.concat(chunks)
return game:GetService("HttpService"):JSONDecode(jsonData)
end)
if success then
Possessions = data or {}
print("Recording loaded:", name)
else
warn("Error loading recording:", data)
end
end
-- Chat commands for saving and loading
Players.PlayerAdded:Connect(function(player)
player.Chatted:Connect(function(message)
local command, arg = string.match(message, "/(%w+)%s?(.*)")
if command == "saverecording" then
saveRecording(arg)
elseif command == "loadrecording" then
loadRecording(arg)
elseif command == "startrecording" then
startRecording(player)
elseif command == "stoprecording" then
if recording then
recording:Disconnect()
recording = nil
print("Recording stopped")
end
end
end)
end)
Thanks!
Forgot to say the error, It prints everything (to record, stop, save, load), but it never loads and plays the thing recorded @makeitxx
This is a horrible idea lol. Really popular games on Roblox just run basic server sided checks on objectives in your game that need to be protected. You can narrow your anti cheat down to something as basic as a player having too much of an item or a statistic which is always 1000% trackable. This is just totally unnecessary. Example: Instead of recording a video of a cheater using fly hacks in an obby with 1000 checkpoints, you can just check how long it took them to finish the 1000 checkpoints and if they completed it too quickly you can kick and/or ban them.
It’s because it’s a better way to make sure there’s no false positives. I wish roblox had cursing
i was replying to his post based on his concept. its obvious im already aware of all that lol. i would do it that way as well
Just so you all know I’m still going to use an anti cheat, I’m making this so I can check if they were actually cheating. Also It’s for inappropriate/rule breaking people in my game not just hackers.
@targetframed @makeitxx I made it!!! It still has issues and I’m going to add these features
- Include all instances
- Make gui
- Add the anti cheat into it (or make it so I can call it in anti cheat)
- Add delete/library system
please suggest more ideas
https://youtu.be/ukP3wYiWTfY
This is great, I love the idea of it I’m working on a anti cheat myself for my new game and I had some struggles with ideas and I saw this post this would help me a lot and it’s actually pretty smart as well but in terms of performance etc I’m just worried about that
It should not be impacting performance at all. Stuff like citadel and chickynoid is going to impact performance because it is doing something totally unnecessary. That is ultimately Roblox’s job to prevent those things from occurring. Our jobs as developers is to protect what we need to. You should ask yourself what is the main objective of the game? That is what you need to be worried about. You can detect fly, noclip, walkspeed, infinite jump, but remember, all it takes is 1 of those cheats to work for them to gain an advantage. If your main objective is to kill a boss with 1 million HP, how long would it take a legitimate player to kill that boss? Sure, exploiter can fly around and infinite jump, but guess what? All of it is completely useless if you kick players who beat it too quickly… so all you have to do is protect your main objective and protect the data stores in your game, and let exploiters do as they wish! There’s nothing to be afraid about them doing those things as it won’t help them or benefit them even in the slightest. Whether they use 1 cheat, or 100 cheats, those cheats should not be helping them gain an advantage whatsoever, but it will if you choose citadel or chickynoid because those are not protecting anything important and only preventing cheats from occurring. So they could practically beat the game in 2 seconds and win instead of being kicked for that.
I mean yeah your right, it wouldn’t affect the performance and protecting your games main objectives is true as well, only reason I’d implement this would be for farming or botting
I learned how to do this from a friendly developer who took a 12 week, full time paid opportunity to become a software engineer at Roblox. All you have to do is set up a leaderboard that detects the statistics of players and ban the ones whose statistics are suspicious. You can always put your discord and ask them to contact you there for further investigation. You set up a remote event logging history that logs how quickly each player fires remote events, and in your investigation if you find the player appealing fired remote events in a way that doesn’t align with legitimate players, you politely tell them why they got banned and then ban them from your discord server and keep them banned from the Roblox game and investigate any potential alt accounts they may be linked to.
citadel in no way prevents injection or execution via garbage collection
It’s detects injections, I saw someone do it and I sent a hacker message in their discord
i’m NOT going to bypass citadel just to know what it’s using for detections
???
what are you babbling about
Obsidian is the owner of citadel anti cheat. Obsidian wasn’t saying it doesn’t detect SOME injections, rather was saying it doesn’t detect SOME injections through garbage collection. It does detect SOME of them but not the way you might think and Obsidian doesn’t want people trying to make false claims as to how it works.