Envanter yönetimi, Roblox'taki RPG ve hayatta kalma oyunlarının temelidir. Zayıf mimari eşya çoğaltma açıklarına ve mobil cihazlarda gecikmelere yol açar.
Sunucu yetkili durum makineleri, modüler veri yapıları ve ProfileService oturum kilidi ile binlerce oyuncu için güvenli ve akıcı envanterler tasarlanabilir.
1. Envanter Modelleri: Sabit Slot vs. Izgara vs. Ağırlık Limiti
Oyun dinamiğine en uygun yapının seçilmesi:
- Sabit Slot Mimarisi: Belirli sayıda hücreden oluşan klasik model. O(1) erişim hızı ve kolay kayıt imkanı.
- Mekansal Izgara (Tetris): Diablo tarzı çok hücreli eşyalar. 2D çarpışma matrisi gerektirir.
- Ağırlık ve Aşırı Yük Bütçesi: Eşyaların toplam kütlesi sınırı aştığında yürüme hızı cezaları uygulanır.
2. Sunucu Otoritesi ve İyimser (Optimistic) UI
Güvenlikten ödün vermeden anında tepki sağlama:
- İyimser UI Tahmini: Eşya sürüklendiğinde sunucu cevabını beklemeden simge anında yeni yerine geçer.
- Sunucu Doğrulaması: Ağırlık, slot sınırları ve mülkiyet doğrulanarak işlem onaylanır.
- Geri Alma (Rollback): Geçersiz bir işlemde simge pürüzsüzce eski konumuna geri döner.
3. Veri Yapıları ve İstifleme Optimizasyonu
Luau ile dinamik ve statik verilerin ayrıştırılması:
- Temel Veri vs. Özel Örnek: Ad ve temel ağırlık ReplicatedStorage'da, UUID ve dayanıklılık oyuncuda tutulur.
- İstif Birleştirme Formülü: Hedef slotun boş kapasitesi hesaplanarak atomik transfer yapılır.
- DataStore Tasarrufu: 4MB sınırını aşmamak için boş slotlar kayıttan çıkarılır.
-- Sunucu Yetkili Envanter Yöneticisi
local InventoryManager = {}
InventoryManager.__index = InventoryManager
local ItemDatabase = require(game.ReplicatedStorage.ItemDatabase)
function InventoryManager.new(player, maxSlots, maxWeight)
local self = setmetatable({}, InventoryManager)
self.Player = player
self.MaxSlots = maxSlots or 30
self.MaxWeight = maxWeight or 100
self.Slots = table.create(self.MaxSlots, false)
self.CurrentWeight = 0
self.IsLocked = false
return self
end
function InventoryManager:AddItem(itemId, amount)
if self.IsLocked then return false, "INVENTORY_LOCKED" end
local itemData = ItemDatabase[itemId]
if not itemData then return false, "INVALID_ITEM" end
local addedWeight = itemData.Weight * amount
if self.CurrentWeight + addedWeight > self.MaxWeight then
return false, "OVER_ENCUMBERED"
end
for slotIndex = 1, self.MaxSlots do
local slot = self.Slots[slotIndex]
if slot and slot.Id == itemId and slot.Count < itemData.MaxStack then
local space = itemData.MaxStack - slot.Count
local toAdd = math.min(space, amount)
slot.Count = slot.Count + toAdd
amount = amount - toAdd
self.CurrentWeight = self.CurrentWeight + (itemData.Weight * toAdd)
if amount <= 0 then return true end
end
end
for slotIndex = 1, self.MaxSlots do
if not self.Slots[slotIndex] then
self.Slots[slotIndex] = {
UUID = game:GetService("HttpService"):GenerateGUID(false),
Id = itemId,
Count = amount,
Durability = itemData.MaxDurability
}
self.CurrentWeight = self.CurrentWeight + (itemData.Weight * amount)
return true
end
end
return false, "INVENTORY_FULL"
end
return InventoryManager
4. Eşya Kopyalama (Dupe) Koruması ve Oturum Kilidi
Bağlantı kopması ve takas açıklarının önlenmesi:
- MemoryStore Oturum Kilidi: Eşya transferi sırasında çift harcamayı önleyen geçici kilit.
- Atomik Takas Sistemi: Her iki oyuncunun envanteri aynı sunucu karesinde güncellenir veya tamamen iptal edilir.
- İstek Sıklığı Sınırı: Paket saldırılarını önlemek için hareketler arasına 100ms bekleme süresi konur.
5. Mobil Dokunmatik Deneyimi ve Ölçeklendirme
Akıllı telefon ve tabletlerde konforlu kullanım:
- En Az 44px Dokunma Alanı: Küçük ekranlarda yanlış dokunmaları önlemek için dinamik UIScale.
- Uzun Basma Dairesel Menüsü: Dokunmatik ekranlarda sağ tık yerine açılan kullan/böl/at menüsü.
- Dokunsal Titreşim (Haptics): HapticService ile eşya takıldığında hafif geri bildirim.
Frequently Asked Questions
Envanter mantığı neden kesinlikle sunucuda çalışmalıdır?
İstemci tarafındaki kontroller sahte eşya üretimine ve kopyalama hilelerine zemin hazırlar. Sunucu güvenliği esastır.
İyimser UI gecikmeyi nasıl ortadan kaldırır?
Eşya ekranda hemen hareket eder; sadece sunucu reddederse eski yerine geri çekilir.
Oturum kilidi (Session Locking) ne işe yarar?
Aynı anda iki sunucunun oyuncu verisini değiştirmesini engelleyerek kopma açıklarını kapatır.
Mobilde sürükleme sorunları nasıl çözülür?
Parmağın altında hafif bir geçici kopya yürütülür ve hedef slot sadece parmak bırakıldığında taranır.