Menu
CoddyTech

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

שיעור 7 מתוך 18 בקורס משחק 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

אתגר

בינוני

ב־PetServer, בתחילת המטפל של Hit, יש לבצע return בלי לפגוע כאשר:

  1. הערימה אינה Instance בתוך piles,
  2. אין לשחקן דמות, או שה־HumanoidRootPart שלו נמצא במרחק של יותר מ־Settings.Reach studs מהערימה,
  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 = {} -- כל ערימה -> המקום שבו היא נמצאת

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)
	hitPile(player, pile)
end)
quiz iconבחנו את עצמכם

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

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