Anti exploits using humanoid.floormaterial?

Hi, How can I go about making server side anti fly using humanoid.floormaterial?

4 Likes

Sounds pretty specific, but;

--We'll be using RunService to run code every frame
local RunService = game:GetService("RunService")

--Using Players service to get all players in the server
local Players = game:GetService("Players")

--A list of information about a player; where they were last on the ground and
--how long they've been in the air
local PlayerInfos = {}

--How long someone can be in the air without being rubberbanded (teleported back)
local MaxAirborneTime = 5

--Connect to Heartbeat to run code after every physics step (60 times a second)
RunService.Heartbeat:Connect(function(Delta)
	for _, Player in pairs(Players:GetPlayers()) do --Go through each player
		local Character = Player.Character
		
		if not Character then --Do they have a character? If not, ignore this player
			continue
		end
		
		local Humanoid:Humanoid = Character:FindFirstChild("Humanoid")
		
		if not Humanoid then --Do they have a humanoid? If not, ignore this player
			continue
		end
		
		local Info = PlayerInfos[Player.Name] --Get info
		
		if not Info then --If the server hasn't started monitoring this player
			PlayerInfos[Player.Name] = { --Set default info
				LastCFrameOnGround = Character:GetPivot(), --Their current location
				TimeAirborne = 0
			}
			
			continue
		end
		
		if Humanoid.FloorMaterial == Enum.Material.Air then --Are they in the air?
			--Increase the counter for how long they've been in the air
			PlayerInfos[Player.Name].TimeAirborne += Delta
			
			--Have they been in the air for too long (longer than MaxAirboneTime)?
			if PlayerInfos[Player.Name].TimeAirborne > MaxAirborneTime then
				PlayerInfos[Player.Name].TimeAirborne = 0
				--Move them back to when they were last on the ground
				Character:PivotTo(Info.LastCFrameOnGround)
			end
		else --Player is on the ground
			PlayerInfos[Player.Name].TimeAirborne = 0
			--Set the last on ground location to be their current one
			PlayerInfos[Player.Name].LastCFrameOnGround = Character:GetPivot()
		end
	end
end)

This should be put in a server-script, preferable inside ServerScriptService, and you can test this out by running the following in the command bar in Client view in Studio and holding the jump/space key:

while true do
 if not game.Players.LocalPlayer.Character then
  task.wait() 
  continue
 end 
 game.Players.LocalPlayer.Character:WaitForChild("Humanoid"):ChangeState(Enum.HumanoidStateType.Swimming)
 task.wait()
end

In this case, 5 seconds is pretty excessive.

Obligatory “This is heavily dependent on your game”.

4 Likes

Hope this is not too much to ask, could you explain every part of the script?

I have added comments to the code.

Might be wrong, but floor material might be exploitable, use raycasts instead if it is

make sure they cant fall off very tall buildings and get twleported

humanoid.floormaterial doesn’t replicate from client to server, and its only readable, so it’s safe.

humanoid.floormaterial casts 9 rays to check for material.

Check this thread out for the facts.

1 Like

udont know , maybe by chance they can use getrawmetatable to change it

woah okay

I think you better make that the antifly works after a few seconds

actually, humanoid.JumpPower/4 i think

Yeah but maybe you better use Humanoid:GetState() if it returns Enum.HumanoidStateType.Flying or Enum.HumanoidStateType.None the client is mostly flying

no because thats exploitable and known

It’s not replicated, as the linked thread shows. It’s like saying the client can access ServerScriptService through some metatable magic, which is completely false since it’s never replicated to the client. Likewise, the client cannot fake FloorMaterial since, when it accessed by a server script, the raycasts are done on the spot by the server, which is also mentioned in the FloorMaterial replication update post.

i guasse this is the best way to fix it