SKSE DLL eklentilerinin versiyondan bağımsız olmasını kolaylaştırmak için başlık dosyası ve bir veritabanı içerir.
Önemli! Bu şimdi iki sürüme ayrılmıştır: özel baskı (1.5.x) ve yıldönümü baskısı (1.6.x). Adreslere işaret eden kimlikler bu iki sürüm arasında eşleşmeyecek (oyun yürütülür şeyleri eşleşemeyecek kadar farklıdır ve bu işlevlerdeki kodla eşleşmeler bile farklıdır).AçıklamaSıradan mod kullanıcıları için: Dosya bölümünden "bütünleştirilmiş" paketi indirin ve yükleyin. Mod yöneticisini kullanabilir veya manuel olarak yapabilirsiniz. . bin dosyası buraya gitmelidir:
Veri/SKSE/Eklentiler/Bunların geri kalanını okumanıza gerek yok.
SKSE DLL eklentisi yazarları için:Bu bir modder kaynağıdır (bir başlık dosyası). Ofsetleri depolayan bir veritabanı yükleyebilirsiniz, böylece dll eklentisinizin yeniden derlenmesi gerekmeden sürümden bağımsız olabilir. Başlık dosyası, dosyanın isteğe bağlı bölümünden indirilebilir. Yıldönümü versiyonu için başlık dosyası versiyonb.h yerine versiyonlibdb.h adı verilir! Eğer commonlib kullanıyorsanız, bütün bunlar zaten yerleştirilmiştir ve buradan hiçbir şeye ihtiyacınız yok.
Nasıl kullanılırEn hızlı yol:
Spoiler:
Göstermek
# "versiyonb.h" içerir
void * myadress = NULL
İmzalanmamış uzun uzun myoffset = 0;
bool InitializeOffsets ()
{
Bu işlevi çıktığımızda boşaltılacak şekilde yığında tahsis edin.
//Tüm veritabanının yüklenmesine ve belleğin nedensiz kullanılmasına gerek yok.
Sürüm db db
//Veritabanını geçerli yürütülebilir sürümle yükleyin.
if (! db.Load ())
{
_FATALERROR ("geçerli yürütülebilir veritabanı için sürüm veritabanı yüklenemedi!");
}
Başka bir şey
{
//"SkyrimSE.exe", "1.5.97.0"
_MESSAGE("% s versiyonun% s. yüklenmiş veritabanı ", db.GetModuleName (). c_str (), db.GetLoadedVersionString (). c_str ());
}
//Bu adres zaten modülün temel adresini içerir, böylece adresi doğrudan kullanabiliriz.
Myadress=db.findadressbyid(123);
if (myadress== NULL)
{
_FATALERROR ("adres bulunmadı!");
Yanlış iade et;
}
//Bu ofset temel adresi içermez. Gerçek adres modül tabanı + mioffset olacak.
if (! db.FindOffsetById(123, MyOffset))
{
_FATALERROR ("benim şeyimin ofseti bulunmadı!");
}
//Her şey başarılı oldu.
Gerçeği geri dönün;
}
Şimdi şu 123 değerinin ne olduğunu merak ediyorsunuz. Bu bir adresin kimliği. Farklı sürüm veritabanları bir adres için aynı kimliğe sahiptir, ancak farklı değerlere işaret edebilir. Belirli bir sürüm için tüm kimlik ve değer çiftlerinin bir listesini almak için şunu yapın:
Spoiler:
Göstermek
# "versiyonb.h" içerir
Boole döküm SpecificVersion ()
{
Sürüm db db
//Yürütülebilir sürümü çalıştığına bakılmaksızın 1.5.62.0 sürümünün veritabanını yüklemeye çalışın.
if (! db.Load(1,5,62,0))
{
_FATALERROR ("1.5.62.0 için veritabanı yüklemedim!");
Yanlış iade et;
}
//offsets-1.5.62.0.txt adlı bir dosya yazın, burada her satır kimlik ve ofsettir.
db.Dump ("ofsets-1.5.62.0.txt");
_MESSAGE("1.5.62.0 için boşaltılmış ofset ");
Gerçeği geri dönün;
}
1,5,62,0 yerine tersine çevirdiğiniz ve bildiğiniz sürümü koyun. Önce/Data/SKSE/plugins dizininde karşılık gelen veritabanı dosyasına sahip olmalısınız.
Bunu çağırdıktan sonra ana skyrim dizininde "offsets-1.5.62.0.txt" adlı yeni bir dosya veya dosya adı olarak koyduğunuz her neyse olmalısınız. Her satırın formatında olacak:
Ondalık kimlik<tab>Altıcı ofset<newline>
Örneğin, 1.5.62.0'da sürümü bağımsız hale getirmek istediğiniz 142f4def8 (oynatıcı karakteri statik işaretçisi) adresiniz varsa, bunu yaparsınız:
1. ofset dosyasında 2f4def8'i arayın. Çünkü bu taban 140000000 olmadan ofset
2. Kimliğin 517014 olduğunu görün (ondalık!)
3.Bu adresi çalışma zamanında dll'de istiyorsanız şunu yapın:
void*adressof142f4def8=db.findadressbyid(517014);
İşte orada.
Versiondb yapısının aşağıdaki işlevleri vardır:
Spoiler:
Göstermek
bool Dump (const std:: string & path); //Şu anda yüklenen veritabanını dosyaya dökün
Bool yükleri (int major, int minor, int revize, int build); //db-major-minor-revision-build.bin data/SKSE/plugins dizininde varsa, belirli bir sürüm yükleyin
Bool yük (); //Geçerli uygulamanın sürümünü yükleyin
void Clear (); //Şu anda yüklenen veritabanını temizleyin
void GetLoadedVersion (int & major, int & minor, int & revision, int & build) const; //Şu anda yüklediğimiz veritabanı dosyasının sürümünü alın
bool GetExecutableVersion (int & major, int & minor, int & revision, int & build) const; //Şu anda yürütülen uygulamanın sürümünü alın
const std:: string & GetModuleName () const; //Şu anda yüklenen veritabanı modülünün adını alın, bu "SkyrimSE.exe" gösterilmelidir
const std:: string & GetLoadedVersionString () const; //Şu anda yüklenen sürümü dize olarak alın, örneğin "1.5.62.0"
const std:: harita<unsigned long long, unsigned long long>& GetOffsetMap () const; //Manuel olarak yinelemeniz gerekiyorsa, ofset edilecek kimlik haritasını alın
void* FindAddressById (imzasız uzun uzun id) const; //adresi kimliğe göre bulun, bu zaten temel ve doğru adresi içerecektir. Bulunmazsa boş dönür!
bool FindOffsetById (imzalandırılmamış uzun uzun kimlik, imzalandırılmamış uzun uzun & sonuç) const; //kimliğe göre ofset bulun, bu sadece tabanı içermeden ofset edilir.
Bool findidbyadress (void*ptr, imzalandırılmamış uzun uzun & sonuç) const; //adrese göre kimliği bulun, bu adresi kimliğe dönüştürmek için ters arama deneyecektir
bool FindIdByOffset (imzalandırılmamış uzun uzun ofset, imzalandırılmamış uzun uzun & sonuç) const; //ofsetle kimliği bulun, bu ofseti kimliğe dönüştürmek için ters arama deneyecektir
Bilmeniz ve hatırlamanız gereken şeyler:
1.Eklentisinizle herhangi bir veritabanı dosyasını (veya tümünü) ekleyebilirsiniz, ancak dosya boyutunu (yaklaşık 2.5 mb) büyük ölçüde artırabilir. Şimdiye kadar bu modu bir bağımlılık olarak işaretlemek yaygındır.
2.Veritabanını başlatıldığında her zaman sadece bir kez yüklemelisiniz, ihtiyacınız olan adresleri başlatmalısınız/önbelleğe almalısınız ve boşaltmasına izin vermelisiniz. Boşaltma sadece sürüm yapısının silineceği veya kaybolacağı anlamına gelir (yığında tahsis edilirseniz). Bu, oyun çalışma zamanında gereksiz bellek kullanmadığınızdan emin olacaktır. Oyun oynaması sırasında veritabanını yüklemeye gerek yok. Commonlib kullanırsanız bu tartışmalı bir noktadir çünkü her dll yerine yalnızca bir kez yükler.
3.Veritabanı işlevlerin adreslerini, genel değişkenleri, RTTI, vtables ve başka herhangi bir referansı olabilecek herhangi bir adresi içerir. İşlevlerin ortasında veya küreselin ortasında olan adresler içermez. Fonksiyonun ortasında bir adrese ihtiyacınız varsa, fonksiyon temel adresini aramalı ve ekstra ofset eklemelisiniz. Ayrıca işlev etrafında hizalama gibi işe yaramaz şeyler içermez (rdata'da atıfta bulunulur), pdata bölümü atılır ve derleyici tarafından rdata'dan oluşturulan bazı seh bilgileri atılır.
4.Veritabanının başarıyla yüklendiğinden emin olmak için sonuçları her zaman kontrol etmelisiniz (bool yükleme gerçek döndürüldü) ve sorgulanan adreslerin gerçekten geçerli bir sonuç döndürdüğünden emin olmalısınız (null değil). Eğer yüklenemezse, dosyanın en büyük olasılıkla veya yanlış sürümü eksik olduğu anlamına gelir (örneğin, ae'de se başlığını kullanmaya çalışmak). Sorgu başarısız olursa, adresin bu sürümde bulunamadığı anlamına gelir. Bu, oyun kodunun adresin o sürüm için artık geçerli olmayacağı yeterince değiştiği veya veritabanının kendisi doğru adresi tespit edemediği anlamına gelebilir. Bu şeylerin herhangi biri gerçekleşirse, skse'ye doğru yüklenmediğinizi bildirmek için eklentiyi başlatmayı başarısız etmelisiniz. Ya da hata mesajını manuel olarak görüntüleyin.
5. Dll eklentisinizi yayınlamadan önce adresin oyunun tüm sürümlerinde olduğundan emin olmanızı kontrol ederseniz en iyisidir. Bunu yapmak için veritabanı dosyasının her sürümünü yükleyin ve varlığından emin olmak için her birinde aynı adres kimliğini sorgulayın:
Spoiler:
Göstermek
Bool yük (std:: vektör<VersionDb*>& Tüm)
{
Statik int versiyonları [] = {3, 16, 23, 39, 50, 53, 62, 73, 80, 97, -1};
Için (int i=0; sürüm[i] > = 0; i ++)
{
VersionDb * db = new VersionDb ();
if (! db-> yük (1, 5, versiyonlar [i], 0))
{
Db sil;
Yanlış iade et;
}
all.push_back (db);
}
Gerçeği geri dönün;
}
Bool existensinall (std:: vektör<VersionDb*>& Tüm, İmzasız Uzun Uzun Kimlik)
{
İmzalanmamış uzun uzun sonuç = 0;
{
if (! db-> FindOffsetById(id, result))
}
Gerçeği geri dönün;
}
void FreeAll (std:: vektör<VersionDb*>& Tüm)
{
for (otomatic db: all)
Db sil;
all.clear ();
}
Boolean IsOk ()
{
std:: vektör<VersionDb*>Hepsi;
if (! LoadAll (tüm))
{
_FATALERROR ("Geçerli yürütülür için bir veya daha fazla sürüm veritabanı yüklenemedi!");
Özgür (tüm);
Yanlış iade et;
}
if (! Existensinall (all, 517014))
{
_FATALERROR ("517014 veritabanının tüm sürümlerinde yok!");
}
Özgür (tüm);
//Tamam!
Gerçeği geri dönün;
}
Bu şekilde, dll modunuzun tüm sürümlerde çalışacağından emin olabilirsiniz veya bazı sürümlerde çalışmazsa, bunu mod sayfasınıza yazabilirsiniz.
6.Bazen çalışan oyun sürümlerine göre farklı şeyler yapmanız gerekir. Bunu bu kod parçasıyla yapabilirsiniz:
Spoiler:
Göstermek
int major = 0, minor = 0, revize = 0, build = 0;
if (! db.GetExecutableVersion(major, minor, revize, build))
{
_FATALERROR ("bir şey yanlış gitti!");
Yanlış iade et;
}
//Çalışan oyun 1.5.x ve en az 1.5.39.0 sürümü
if (büyük == 1 & & küçük == 5 & & revize > = 39)
{
Şeyler...?
}
7. Lütfen unutmayın: skse dll'inizi hata ayıklama modunda derlerseniz veritabanının yükleme süresi yaklaşık 14 saniye olabilir! Serbest bırakma modunda bu yaklaşık 0.2 saniye. Bunun nedeni, standart kütüphane kaplarının bu modda çok yavaş olmasıdır (std haritası).
İzinlerNe istersen yap.