Contient un fichier d'en-tête et une base de données pour rendre les plugins DLL SKSE facilement indépendants de la version.
Important! Celui-ci est désormais divisé en deux versions: Special Edition (1.5.x) et Anniversaire Edition (1.6.x). Les identifiants pointant vers les adresses ne correspondent pas entre ces deux versions (les exécutables du jeu sont trop différents pour correspondre, et même s'ils le font, le code dans ces fonctions est différent).DescriptionPour les utilisateurs mod réguliers: Téléchargez et installez le paquet « tout-en-un » dans la section Fichiers. Vous pouvez le faire en utilisant le gestionnaire de mod ou manuellement. Le fichier. bin devrait être placé ici:
Données/SKSE/Plug-ins/Vous n'avez pas besoin de lire le reste.
Pour l'auteur du plugin SKSE DLL:Il s'agit d'une ressource modder (fichier en-tête). Vous pouvez charger une base de données qui stocke les décalages, de sorte que vos plugins DLL deviennent indépendants de la version sans avoir à recompiler. Les fichiers d'en-tête peuvent être téléchargés à partir d'une partie facultative du fichier. Pour l'édition anniversaire, le fichier d'en-tête s'appelle versionlibdb.h et non versiondb.h! Si vous utilisez CommonLib, alors tout cela est déjà intégré et vous n'avez pas besoin de rien ici.
Comment utiliserLe moyen le plus rapide:
Spoiler:
Show
# Inclut "versiondb.h"
void*MyAddress=NULL
Non signé long long MyOffset=0;
bool InitializeOffsets ()
{
//Allocation sur la pile de sorte que lorsque nous quittons cette fonction, elle sera déchargée.
//Il n’est pas nécessaire de charger toute la base de données et de manquer de mémoire sans raison.
Base de données de version;
//Charge la base de données avec la version exécutable actuelle.
if (! db.Load ())
{
_FATALERROR("Impossible de charger la base de données des versions de l'exécutable actuel! ");
}
else
{
//"SkyrimSE.exe", "1.5.97.0"
_MESSAGE("Base de données chargée avec %s version %s ", db.GetModuleName (). c_str (), db.GetLoadedVersionString (). c_str ());
}
//Cette adresse contient déjà l'adresse de base du module, nous pouvons donc utiliser cette adresse directement.
MyAddress=db.FindAddressById(123);
if(MyAddress==NULL)
{
_FATALERROR("Adresse introuvable! ");
Retourne false;
}
//Ce décalage n'inclut pas l'adresse de base. L'adresse physique sera ModuleBase+MyOffset.
if(!db.FindOffsetById(123,MyOffset))
{
_FATALERROR("L'offset de mon objet n'a pas été trouvé! ");
}
//Tout a marché bien.
Retourne true;
}
Maintenant, vous voulez savoir quelle est la valeur de "123" là-bas. C'est l'identification d'une adresse. Différentes versions de la base de données auront le même ID d'adresse, mais il peut pointer vers des valeurs différentes. Pour obtenir une liste de toutes les paires d'identifiants et de valeurs pour une version spécifique:
Spoiler:
Show
# Inclut "versiondb.h"
Décharge booleenne SpecificVersion ()
{
Base de données de version;
//Essayez de charger la version 1.5.62.0 de la base de données, quelle que soit la version exécutable en cours d'exécution.
If (! db.Load(1, 5, 62, 0))
{
_FATALERROR("Impossible de charger la base de données pour 1.5.62.0! ");
Retourne false;
}
//Écrivez un fichier appelé offsets-1.5.62.0.txt où chaque ligne est l'ID et l'offset.
db.Dump("offsets-1.5.62.0.txt ");
_MESSAGE("Décalage de dump pour 1.5.62.0 ");
Retourne vrai;
}
N'utilisez pas 1, 5, 62, 0, mais utilisez la version que vous inversez et que vous connaissez. Vous devez d'abord avoir le fichier de base de données correspondant dans le répertoire /Data/SKSE/Plugins.
Après l'appel, vous devriez avoir un nouveau fichier appelé "offsets-1.5.62.0.txt" ou n'importe quel nom de fichier que vous avez entré dans le répertoire principal de Skyrim. Le format de chaque ligne est le suivant:
ID décimal
Décalage hexagonal
Par exemple, si vous avez une adresse 142F4DEF8 (pointeur statique du personnage du joueur) dans la version 1.5.62.0 et que vous souhaitez la rendre indépendante de la version, vous pouvez le faire comme suit:
1. Recherchez 2F4DEF8 dans le fichier offsets. Parce que c'est un décalage sans base 140000000
2. Voir que l'ID est 517014 (décimal!)
3. Si vous voulez inclure cette adresse dans la DLL au moment d'exécution, procédez comme suit:
void*adressof 142f4def8=db.FindAddressById(517014);
Maintenant, vous l'avez.
La structure VersionDb possède les fonctions suivantes:
Spoiler:
Show
Dump booléen (constante std::chaîne et chemin); //Décharger la base de données actuellement chargée dans un fichier
Bull chargement (int major, int minor, int revision, int build); //Charger une version spécifique si db-major-minor-revision-build.bin est présent dans le répertoire Data/SKSE/Plugins
bool Load (); //Charger la version de l'application actuelle
void Clear (); //Effacer la base de données actuellement chargée
void GetLoadedVersion(int&major, int&minor, int&revision, int&build) constante; //Obtenir la version du fichier de base de données que nous chargeons maintenant
bool GetExecutableVersion(int&major, int&minor, int&revision, int&build) constantes; //Obtenir la version de l'application en cours d'exécution
const std::string & GetModuleName () const; //Obtient le nom du module de base de données actuellement chargé, qui devrait afficher "SkyrimSE.exe"
const std::string & GetLoadedVersionString () const; //Obtient la version actuellement chargée sous la forme d'une chaîne, par exemple "1.5.62.0"
const std::mapConstante & GetOffsetMap (); //Si vous devez itérer manuellement, obtenez le mappage de l'ID vers l'offset
void*FindAddressById (id long sans signe) constante; //Recherche l'adresse par ID, qui inclut déjà l'adresse de base et est la bonne adresse. S'il n'est pas trouvé, il retournera NULL!
bool FindOffsetById (unsigned long id, unsigned long & result) constante; //Recherche le décalage par ID, ce sera juste le décalage qui n'inclut pas la base.
bool FindIdByAddress(void * ptr, unsigned long long & result) constante; //Trouver un ID par adresse, ce qui essaiera de trouver l'inverse pour traduire l'adresse en un ID
bool FindIdByOffset (décalage de longueur unsigned, longueur unsigned & result) constante; //Trouver l'ID par offset, qui essaiera d'inverser la recherche pour convertir l'offset en ID
Ce que vous devriez savoir et vous rappeler:
1. Vous pouvez inclure n'importe quel (ou tous) fichiers de base de données dans le plugin, mais cela peut augmenter considérablement la taille du fichier (environ 2,5 Mo). Jusqu'à présent, il était courant de marquer ce mod comme une dépendance.
2. Vous devez toujours charger la base de données une seule fois au démarrage, initialiser/mettre en cache l'adresse dont vous avez besoin et laisser la décharger. La désinstallation signifie simplement que la structure VersionDb est supprimée ou perdue (si vous l'avez allouée sur la pile). Cela vous garantira que vous n'utilisez pas de mémoire inutile pendant que le jeu est en cours d'exécution. Il n'est pas nécessaire de garder la base de données chargée pendant le jeu. Ceci est controversé si vous utilisez CommonLib, car il n'est chargé qu'une seule fois et non pour chaque DLL.
3. La base de données contient les adresses des fonctions, des variables globales, des RTTI, des vtables et tout autre contenu qui pourrait y faire référence. Il ne contient pas d'adresses situées au milieu de la fonction ou au milieu global. Si vous avez besoin d'une adresse au milieu d'une fonction, vous devriez rechercher l'adresse de base de la fonction et ajouter vous-même un décalage supplémentaire. Il ne contient pas non plus de choses inutiles comme l'alignement autour des fonctions (référencées dans rdata), la partie pdata est éliminée et certaines informations SEH générées par le compilateur à partir de rdata sont éliminées.
4. Vous devez toujours vérifier les résultats pour vous assurer que la base de données a été chargée avec succès (bool Load retourne vrai) et que l'adresse interrogée retourne effectivement un résultat valide (et non NULL). S'il ne SE charge pas, cela signifie que le fichier est probablement manquant ou mal versionné (par exemple, en essayant d'utiliser un en-tête SE dans AE). Si la requête échoue, cela signifie que l'adresse ne peut pas être trouvée dans cette version. Cela peut signifier que le code du jeu a changé suffisamment pour que l'adresse ne soit plus valide pour cette version, ou que la base de données elle-même n'a pas réussi à détecter l'adresse correcte. Si l'une ou l'autre de ces situations se produit, vous devriez laisser l'initialisation du plugin échouer et faire savoir à SKSE que vous n'avez pas chargé correctement. Ou afficher manuellement le message d'erreur.
5. Il est également préférable de vérifier que l'adresse est présente dans toutes les versions du jeu avant de publier le plugin DLL. Pour ce faire, chargez chaque version du fichier de base de données et interrogez le même ID d'adresse dans chaque version pour s'assurer de son existence:
Spoiler:
Show
bool LoadAll(std::vector& all
{
static int versions [] = {3, 16, 23, 39, 50, 53, 62, 73, 80, 97, -1};
Pour (int i=0; version[i] > = 0; i++)
{
VersionDb*db=newversionDB ();
if (! db- > Load(1, 5, version[i],0))
{
Supprimer la base de données;
Retourne false;
}
all.push_back (db);
}
Retourne true;
}
bool ExistsInAll(std::vector& all, id long non signé
{
Résultat de longueur non signée = 0;
{
if(!db->FindOffsetById(id, result))
}
Retourne true;
}
void FreeAll(std::vector& all
{
Pour (base de données automatique: tous)
Supprimer la base de données;
All. clear ();
}
Boolean IsOk ()
{
std::vectorTous;
if (! LoadAll(all))
{
_FATALERROR("Impossible de charger une ou plusieurs versions de la base de données de l'exécutable actuel! ");
FreeAll (Tous);
Retourne false;
}
if(!ExistsInAll(all,517014))
{
_FATALERROR("517014 n'existe pas dans toutes les versions de la base de données! ");
}
FreeAll (Tous);
//D'accord!
Retourne true;
}
De cette façon, vous pouvez vous assurer que votre mod DLL fonctionne dans toutes les versions, ou si cela ne fonctionne pas dans certaines versions, vous pouvez écrire sur votre page mod.
6. Parfois, vous devez faire des choses différentes en fonction de la version du jeu en cours d'exécution. Vous pouvez le faire en utilisant le fragment de code suivant:
Spoiler:
Show
Int majeur = 0, minor = 0, revision = 0, build = 0;
if(!db.GetExecutableVersion(major, minor, revision, build))
{
_FATALERROR("Quelque chose s'est mal passé! ");
Retourne false;
}
//Le jeu en cours d'exécution est 1.5.x et au moins 1.5.39.0
Si (majeur ==1&&mineur ==5&&révision > =39)
{
//Quelque chose...?
}
7. Rappelez-vous: si vous compilez votre DLL SKSE en mode débogage, le temps de chargement de la base de données peut être d'environ 14 secondes! En mode libération, cela est d'environ 0,2 seconde. Ceci est dû au fait que le conteneur de la bibliothèque standard est très lent dans ce mode (std map).
Autorisations
Faites ce que vous voulez.