Menu
CoddyTech

לעולם אל תסמכו על הלקוח

שיעור 7 מתוך 20 בקורס משחק Roblox: סימולטור חיות מחמד של Coddy.

השחקן שולט במכשיר שלו, ולכן מי שמנצל פרצות יכול לגרום לו להפעיל כל אירוע מרוחק, עם כל דבר, מכל מקום ובאיזו תדירות שירצה. Hit:FireServer(pile) מכל מקום במפה, מאה פעמים בשנייה, ירוקן כל ערימה במשחק.

לכן השרת בודק כל בקשה לפני שהוא פועל:

  • זו ערימה אמיתית (Instance בתוך workspace.Piles),
  • השחקן נמצא במרחק של עד Settings.Reach ממנה,
  • והפגיעה האחרונה שלו הייתה לפני Settings.HitCooldown שניות לפחות.
if typeof(pile) ~= "Instance" or pile.Parent ~= piles then
	return
end

כשלוחצים על Check, הבדיקות מתנהגות כפי שמי שמנצל פרצות היה מתנהג. הכלל לכל אירוע מרוחק שכותבים: הלקוח מבקש, השרת מחליט.

challenge icon

אתגר

בינוני

גרמו לשרת לדחות פגיעות ששחקן הוגן לא יכול היה לבצע.

  1. בתחילת המטפל של Hit, חזרו אלא אם pile הוא Instance שה־Parent שלו הוא piles.
  2. חזרו אם ה־HumanoidRootPart שלהם חסר או נמצא במרחק גדול מ־Settings.Reach studs מהערימה.
  3. השאירו את local lastHit = {}; חזרו אם הם פגעו לפני פחות מ־Settings.HitCooldown שניות, אחרת שמרו את time().

לחצו על "שחק" ולחצו על ערימה מרחוק: שום דבר לא קורה. לאחר מכן לחצו על "בדיקה".

נסו בעצמכם

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 = {} -- כל ערימה -> המקום שעליו היא עומדת

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)

-- ערימת מטבעות במקום מסוים: עותק של 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()
	-- ערימה חדשה באותו מקום, כמה שניות אחר כך
	task.delay(Settings.RespawnTime, spawnPile, spot)
end

-- ערימה בכל מקום ב-Meadow
for _, spot in workspace.Zones.Meadow.Spawns:GetChildren() do
	spawnPile(spot)
end

-- הלקוח מבקש לפגוע בערימה
remotes.Hit.OnServerEvent:Connect(function(player, pile)
	-- כאן נכנס שיעור 7: לעולם אל תסמכו על הלקוח
	hitPile(player, pile)
end)

כל השיעורים ביחידה משחק Roblox: סימולטור חיות מחמד

תרגלו בעצמכם: Roblox אונליין