Dosya Tabanlı Depolama

Giriş

Veri Depolama (Data Storage), verilerin harita değişiklikleri ve sunucu yeniden başlatmaları boyunca kalıcı olmasını istediğimizde kullandığımız yöntemdir.

Veri konusunda istemciye asla güvenmeyin. Verileri yalnızca sunucudan depolayın, kaydedin, değiştirin ve yükleyin. İstemciye veri vermeniz gerekirse, sunucuda bir yedeğini tuttuğunuzdan emin olun!

Garry's Mod'da veri depolamanın birden çok yolu vardır. Bu eğitimde, Dosya Tabanlı Depolama'yı (File Based Storage) ele alacağız.

Veri işleme kuralları

Herhangi bir veriyi işlerken uymamız gereken bazı kurallar vardır:

  • Asla istemci tarafından işlenmiş verilere güvenmeyin. Tüm verileri sunucuda yedekli tutun, çünkü verilerin orijinal olduğundan emin olmanın tek yolu budur. Diyelim ki istemcilerin paralarını takip etmelerine izin vermeye başladık; sonuna birkaç sıfır eklemelerini ne engelleyebilir ki?

  • Daima istemcinin manipüle edemeyeceği bir kimlik bilgisi kullanın. Bir istemcinin çıkış yaptığında canını kaydetmek isteseydik ve kimlik olarak Steam adlarını kullansaydık, bir sonraki girişlerinden önce bunu değiştirmelerini ne engelleyebilir? Hiçbir şey. Bu yüzden Player:SteamID gibi, istemci tarafından asla değiştirilemeyecek kimlik bilgileri kullanmalıyız.

Fark etmediyseniz, burada kapsayıcı bir tema var: İstemciye asla güvenme.

Ne yazık ki, Garry's Mod sunucuları öngörülebilir değildir - uyarı vermeden kolayca çökebilir veya aşırı yüklenebilirler. Bu nedenle, veriyi kaybetmemek için mümkün olduğunca çabuk işlemelisiniz. Oyuncunun oynarken kazandığı jeton sayısını kaydetmek için oyundan ayrılmasını beklemeyin, çünkü sunucu o zamandan önce ölümcül bir çökme yaşayabilir. Ayrıca, verileri GM:ShutDown hook'u sırasında kaydetmemelisiniz, çünkü bazı oyuncular geçersiz hale geleceği ve değerli jeton sayılarının kaybolacağı için veri kaydetmeye başlamak için çok geç olabilir. Ancak, bunu okuyor olabilirsiniz ve verilerinizin en son anda kaydedilmesi gerektiğini veya her değiştirildiğinde kaydedilecek kadar önemli olmadığını düşünebilirsiniz - bu durumda, GM:ShutDown hook'unu riski size ait olmak üzere kullanabilirsiniz!

Hakkında

Metin dosyaları, veri depolamanın basit bir yoludur. Dosya Tabanlı Depolama, yalnızca file kütüphanesine dayandığı ve oldukça basit olduğu için herhangi bir harici modül gerektirmez. Bu nedenlerden dolayı, yeni başlayanlar için önerilen yöntemdir.

Tabloları depolama - util.TableToJSON

Bu, belki de Color veya Vector gibi veri türlerini dönüştürürken yaşanan hayal kırıklığını önleyecek, yeni başlayanlar için en kolay yöntemdir, bu yüzden önce bu yöntemle başlayacağız.

Tabloları metin dizisine (string) dönüştürme

Bir metin dosyası temel olarak bir karakter dizisidir. Bu, tüm verilerimizi bir karakter dizisine dönüştürmemiz gerektiği anlamına gelir...

util.TableToJSON, bir Lua tablosunu JSON formatına dönüştürecek bir fonksiyondur. JSON, (Lua tabloları gibi) belirli verileri metin olarak temsil etmek için popüler bir formattır; bu metin bir dosyaya kaydedilebilir ve daha sonra aynı veriye geri dönüştürülebilir.

util.TableToJSON'ı nasıl kullanabileceğimize dair bir örnek:

-- Here we have a generic table, containing different types of data that we wish to save into a file: local storeOwnerData = { pos = Vector(1000,20,3), rot = Angle(0,90,0), col = Color(255,0,0,20), text = "Dave - Store Owner" } -- Let's see what util.TableToJSON is going to give us to work with: print(util.TableToJSON(storeOwnerData))

Çıktı:

{"text":"Dave - Store Owner","rot":"{0 90 0}","pos":"[1000 20 3]","col":{"r":255.0,"b":0.0,"a":20.0,"g":0.0}}

Color, Angle ve Vector yapılarının nasıl ayırt edilebilir metin yapılarına dönüştürüldüğüne dikkat edin. Bu benzersiz formatlar, tersine çevirme fonksiyonu olan util.JSONToTable'ın formatları orijinal veri yapılarına geri dönüştürmesine olanak tanır.

Dosyayı okurken gerçekleşmesi gereken tersine çevirme sürecini görebilmemiz için biraz daha kod yazalım.

-- JSONData now stores the Lua table "storeOwnerData" in JSON format. local JSONData = util.TableToJSON(storeOwnerData) local converted = util.JSONToTable(JSONData) PrintTable(converted)

Çıktı:

col: a = 20 b = 0 g = 0 r = 255 pos = 1000.000000 20.000000 3.000000 rot = 0.000 90.000 0.000 text = Dave - Store Owner

Gördüğünüz gibi, JSON metni tekrar bir tablo formatına dönüştürüldü. Ayrıca, converted.pos ile isvector ve converted.rot ile isangle kullanarak veri türlerinin orijinal formatlarına döndüğünü kontrol edebiliriz, bu da bize onların tekrar bir Vector ve Angle'a dönüştürüldüğünü söyler. Ne yazık ki, converted.col'u IsColor'a geçirmek, onun doğru bir şekilde Color yapısına dönüştürülmediğini gösterir. Neyse ki, daha sonra onu normale döndürmek için kod yazabiliriz.

JSON verisini kaydetme

Artık bir tabloyu depolanabilir bir formata nasıl dönüştüreceğimizi ve depolanan formatı normal bir Lua tablosuna nasıl geri çevireceğimizi öğrendiğimize göre, şimdi dosyaları nasıl okuyup/yazacağımızı ve JSON verisini nasıl kaydedeceğimizi öğrenebiliriz.

İster inanın ister inanmayın, veriyi bir dosyaya kaydetmek yalnızca tek bir fonksiyon gerektirir: file.Write. Dokümantasyona baktığımızda yalnızca iki şeye ihtiyacı olduğunu öğreniyoruz:

  • Bir dosya adı
  • Kaydedilecek veri Öyleyse devam edelim ve storeOwnerData tablosunu storedata.json adlı bir dosyaya kaydetmeyi tamamlamak için biraz kod yazalım:
local storeOwnerData = { pos = Vector(1000,20,3), rot = Angle(0,90,0), col = Color(255,0,0,20), text = "Dave - Store Owner" } -- Let's put it in a function so that when we next change the table, we can just call this function again function SaveStoreData() local converted = util.TableToJSON(storeOwnerData) file.Write("storedata.json", converted) end SaveStoreData()

İşte bu kadar, dosya kaydedildi!

Dosyayı kendi gözlerinizle görmek isterseniz, garrysmod/data klasörüne gidebilirsiniz; dosyanın adı "storedata.json" olacaktır.

Eylül 2019'dan beri dosyalar JSON (.json) formatında kaydedilebilmektedir.

Dosyalardan JSON verisini okuma ve tekrar tabloya dönüştürme

JSON verisini okumak da, anahtar fonksiyonun tek bir argüman alan file.Read olmasıyla aynı derecede kolaydır... Dosya Adı. Burada ayrıca renk verisi içeren tabloyu da bir Color yapısına dönüştüreceğiz:

local storeOwnerData = {} function ReadStoreData() -- Make sure you use the same filename as the one in file.Write! local JSONData = file.Read("storedata.json") -- JSONData is currently a JSON string - let's convert that into a table: storeOwnerData = util.JSONToTable(JSONData) -- Remember how the col value does not get converted into a Color structure? Let's fix that: local oldCol = storeOwnerData.col storeOwnerData.col = Color(oldCol.r, oldCol.g, oldCol.b, oldCol.a) end

storeOwnerData değişkeni artık tüm verileri içeriyor ve col değeri artık bir Color!

Tablolar dışındaki veri türlerini yazma

Yukarıdaki yöntem tabloları depolamak için mükemmeldir, peki ya sadece bir sayı veya metin (string) depolamak istersek?

Bu senaryoda özellikle farklı olan bir şey yok, sadece artık util fonksiyonlarına ihtiyacımız yok:

Metni (string) kaydetme

local myString = "This is a string that I want to save!" function SaveString() -- We are saving the contents of myString into a file called "stringdata.txt" file.Write("stringdata.txt", myString) end SaveString()

Metni (string) yükleme

local myString = "" function LoadString() myString = file.Read("stringdata.txt") end LoadString()

Hiç de o kadar zor değil, değil mi?

Dosya tabanlı depolamaya alternatifler

Diyelim ki bir oyuncunun para miktarını takip etmemiz gerekiyor. O zaman, oyuncu her ayrıldığında veya para miktarı güncellendiğinde dosyaya kaydetmemiz gerekir ve bu nedenle, 1.000 satırlık (hatta daha fazla!) bir dosyanın okunması, değiştirilmesi ve ardından tamamen yeni verilerle üzerine yazılması gerekecektir. Bu yavaştır ve bir dosyada verisi depolanan oyuncu sayısı arttıkça çok daha yavaş hale gelecektir.

Bu nedenle, bir alternatife ihtiyacımız var.

Belki de Garry's Mod'da büyük miktarda veri depolamanın en verimli yöntemi SQL'dir. Ne yazık ki, SQL'i öğrenmek dosya tabanlı depolama kadar kolay değildir, ancak öğrenmeye karar verirseniz kesinlikle buna değer.

PData artık dahili olarak Player:SteamID64 kullanıyor, bu da çakışan veri olmaması gerektiği ve 19 Temmuz 2024 itibarıyla kullanımının güvenli olduğu anlamına geliyor.

Tüm sunucular · GmodTR Launcher · Rehber · GMod Wiki · GmodTR nedir? · Sunucu ekle · Discord