Menu
CoddyTech

클라이언트를 절대 믿지 마세요

Coddy의 Roblox 게임: 펫 시뮬레이터 코스 레슨. 18개 중 7번째.

플레이어는 자신의 기기를 제어하므로, 악용자는 원하는 만큼 빠르게 어디서든 무엇이든 보내 어떤 원격 이벤트든 실행할 수 있습니다. 맵 반대편에서 Hit:FireServer(pile)을 초당 100번 호출하면 게임의 모든 더미가 비워집니다.

그러므로 서버는 요청을 처리하기 전에 모두 확인합니다:

  • 실제 더미인지 (workspace.Piles 안의 Instance인지),
  • 플레이어가 더미에서 Settings.Reach 이내에 있는지,
  • 그리고 플레이어가 마지막으로 타격한 지 최소 Settings.HitCooldown초가 지났는지.
if typeof(pile) ~= "Instance" or pile.Parent ~= piles then
	return
end

Check를 누르면 테스트에서 악용자가 할 법한 동작을 수행합니다. 작성하는 모든 원격 이벤트의 원칙은 다음과 같습니다. 클라이언트가 요청하고, 서버가 결정합니다.

challenge icon

챌린지

중급

PetServer에서 Hit 처리기의 시작 부분에 다음의 경우 공격하지 않고 반환하세요:

  1. 더미가 piles에 있는 Instance가 아닌 경우,
  2. 플레이어에게 캐릭터가 없거나, HumanoidRootPart가 더미에서 Settings.Reach 스터드보다 더 멀리 있는 경우,
  3. Settings.HitCooldown초가 지나기 전에 공격한 경우(위쪽 가까이에 local lastHit = {}를 두고, 공격이 허용될 때 time()을 기록하세요).

Play를 누른 다음 Check를 누르세요. 검사가 악용자를 플레이합니다.

직접 해보기

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Settings = require(game.ReplicatedStorage.Settings)

local remotes = game.ReplicatedStorage.Remotes
local piles = workspace.Piles
local pileSpot = {} -- 각 pile -> 해당 pile이 놓인 spot

print("A Meadow pile gives " .. Settings.PileValue .. " coins")

-- 모든 플레이어는 리더보드에 Coins를 받습니다
Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local coins = Instance.new("IntValue")
	coins.Name = "Coins"
	coins.Parent = leaderstats
end)

-- spot에 놓인 코인 더미: ServerStorage.CoinPile의 복사본이며 체력은
-- 가치와 함께 속성으로 저장됩니다
local function spawnPile(spot)
	local pile = ServerStorage.CoinPile:Clone()
	pile.Position = spot.Position
	pile:SetAttribute("MaxHealth", Settings.PileHealth)
	pile:SetAttribute("Health", Settings.PileHealth)
	pile:SetAttribute("Value", Settings.PileValue)
	pileSpot[pile] = spot
	pile.Parent = piles
	return pile
end

-- 한 번 타격할 때마다 더미의 체력이 1 감소합니다;
-- 체력이 0이 되면 더미가 부서지고 해당 가치만큼 코인을 지급합니다
local function hitPile(player, pile)
	local health = pile:GetAttribute("Health") - 1
	if health > 0 then
		pile:SetAttribute("Health", health)
		return
	end
	player.leaderstats.Coins.Value += pile:GetAttribute("Value")
	local spot = pileSpot[pile]
	pileSpot[pile] = nil
	pile:Destroy()
	-- 몇 초 후 같은 spot에 새 더미가 생성됩니다
	task.delay(Settings.RespawnTime, spawnPile, spot)
end

-- Meadow의 모든 spot에 더미를 하나씩 생성합니다
for _, spot in workspace.Zones.Meadow.Spawns:GetChildren() do
	spawnPile(spot)
end

-- 클라이언트가 더미를 타격하도록 요청합니다
remotes.Hit.OnServerEvent:Connect(function(player, pile)
	hitPile(player, pile)
end)
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

Roblox 게임: 펫 시뮬레이터의 모든 레슨