Semua artikel

31 Oktober 2026 · 2 menit baca

Jangan percaya client: cara mengamankan RemoteEvent di Roblox

Exploiter bisa mengirim apa saja lewat RemoteEvent. Ini cara memvalidasi di server agar koin, item, dan hadiah tidak bisa dicurangi.

Semua yang berjalan di perangkat pemain bisa diubah oleh exploiter, termasuk LocalScript dan data yang dikirim lewat RemoteEvent. Karena itu aturan pertama keamanan game Roblox sederhana: server tidak boleh percaya apa pun yang dikirim client.

Kesalahan yang paling sering

Contoh yang berbahaya: client mengirim BuyItem:FireServer("sword", 100) lalu server mengurangi koin sebesar angka yang dikirim. Exploiter cukup mengganti 100 menjadi 0, atau angka negatif, dan item jadi gratis.

1. Hitung semua nilai penting di server

Harga, hadiah, damage, dan jumlah koin harus ditentukan oleh server. Client cukup mengirim niat (misalnya ID item yang ingin dibeli), bukan angkanya.

2. Validasi tipe dan isi setiap argumen

Parameter pertama OnServerEvent selalu pemain yang mengirim, dan itu tidak bisa dipalsukan. Argumen setelahnya bisa berisi apa saja, jadi cek tipenya dengan typeof dan pastikan nilainya ada di daftar yang diizinkan.

3. Batasi frekuensi

Exploiter bisa memanggil remote ratusan kali per detik. Simpan waktu panggilan terakhir per pemain dan abaikan panggilan yang terlalu rapat.

4. Cek konteks dunia

Untuk aksi seperti membuka peti atau memukul musuh, pastikan karakter pemain memang berada cukup dekat dengan targetnya, misalnya dengan membandingkan jarak posisi keduanya.

Contoh lengkap

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local BuyItem = ReplicatedStorage:WaitForChild("BuyItem")
local PRICES = { sword = 100, shield = 150 }
local lastCall = {}

BuyItem.OnServerEvent:Connect(function(player, itemId)
	-- Validasi tipe dan isi: hanya ID yang dikenal server.
	if typeof(itemId) ~= "string" or PRICES[itemId] == nil then
		return
	end

	-- Batasi frekuensi: maksimal sekali per 0,5 detik.
	local now = os.clock()
	if lastCall[player] and now - lastCall[player] < 0.5 then
		return
	end
	lastCall[player] = now

	-- Harga diambil dari server, bukan dari client.
	local stats = player:FindFirstChild("leaderstats")
	local coins = stats and stats:FindFirstChild("Coins")
	if not coins or coins.Value < PRICES[itemId] then
		return
	end

	coins.Value -= PRICES[itemId]
	-- Berikan item dari server di sini.
end)

Players.PlayerRemoving:Connect(function(player)
	lastCall[player] = nil
end)

5. Hati-hati dengan RemoteFunction

Hindari RemoteFunction:InvokeClient dari server. Client bisa tidak pernah membalas sehingga thread server menunggu selamanya. Untuk komunikasi server ke client, pakai RemoteEvent.

Penutup

Anti-exploit yang baik bukan deteksi yang rumit, melainkan server yang menjadi satu-satunya sumber kebenaran. Butuh sistem yang aman sejak awal? Lihat layanan Scripting & Sistem.

Punya ide game? Kita bangun bareng.

Ceritakan idemu lewat formulir brief. Tim kami membalas dengan estimasi dalam 2 hari kerja.