JeuxOnLineForumsPlusConnectés : 165 (sites) | 413 (forums)Créer un compte
Forum jeux-vidéo>Neverwinter Nights
Maskado
Les forums JOL > Forum jeux-vidéo > Neverwinter Nights > NWN - Maskado > [PHP] Gestion des fichiers 2DA RSS
   
Répondre
Partager Outils Rechercher
Avatar de Ia~
Ia~
Alpha & Oméga
 
Avatar de Ia~
 

[PHP] Gestion des fichiers 2DA

Code PHP:
//:://///////////////////////////////////////
//:: Classe : C2DA
//:://///////////////////////////////////////
//:: Par    : CdN
//:: Le     : 15 juin 2003
//:://///////////////////////////////////////
/*
    Classe de lecture et travail sur les
    fichiers 2DA de Neverwinter Nights.
*/
//:://///////////////////////////////////////
class C2DA {
    
//:: Variables
    
var $LineLen,            // Longueur des lignes
        
$HeadLine,            // Ligne des entêtes
        
$nNumCols,            // Nombre de colones
        
$arColsLen,            // Longueur des colones
        
$arColsHead,        // Entête des colones
        
$ar2DA,                // Tableau du contenu du 2DA
        
$nNumItems,            // Nombre d'entrées dans le 2DA
        
$sHeaders;            // Entêtes du fichier
    //:: Constructeur
    // $s2DAFile    => Fichier 2DA à travailler
    
function C2DA($s2DAFile) {
        
// Ouverture du 2DA
        
$fp fopen($s2DAFile"r");
        
// Lecture des entêtes
        
$this->sHeaders trim(fgets($fp8192));
        
// Lecture du vide
        
$maxlen strlen(fgets($fp8192)) + 1;
        
$this->LineLen $maxlen;
        
// Lecture des entêtes de colones
        
$cols fgets($fp,$maxlen);
        
$this->HeadLine $cols;
        
$tbl $this->spacexplode(ltrim($cols));
        
// Enregistrement du nombre de colones
        
$this->nNumCols count($tbl);
        
// Enregistrement des entêtes et des longueurs
        
for($i=0$i<count($tbl); $i++) {
            
$this->arColsHead[$i+1] = trim($tbl[$i]);
            
$this->arColsLen[$i+1] = strlen($tbl[$i]);
        }
        
// Calcul de la longueur de la colonne de numerotation
        
$numlen=0; while($cols[$numlen] == " "$numlen++;
        
$this->arColsHead[0] = "";
        
$this->arColsLen[0] = $numlen;
        
// Scan du tableau du 2DA
        
$i 0;
        while(!
feof($fp)) {
            
$line trim(fgets($fp,$maxlen));
            if(
strlen($line)>0$this->ar2DA[$i] = preg_split("/\s+/"$line);
            
$i++;
        }
        
//Fermeture du 2DA
        
fclose($fp);
    }
    
//:: Fonction : spacexplode
    // FONCTION PRIVEE : Fait un explode special sur une chaine.
    // $texte        => Texte a exploser
    
function spacexplode($texte) {
        for (
$i=0,$mod 0;$i<strlen($texte);$i++) if (ereg("[[:space:]]",substr($texte,$i,1))) { $mod=1$act.=substr($texte,$i,1); } else { if (!$mod$act.=substr($texte,$i,1); else { $mod=0$act.="\",\"".substr($texte,$i,1);    } }
         eval(
"\$tabl = array(\"".$act."\");");
         return 
$tabl;
    }
    
//:: Fonction : Display2DA
    // Affiche le fichier 2DA dans un tableau HTML.
    // $table_class    => Classe CSS de la balise <table>
    // $tr_class    => Classe CSS de la balise <tr>
    // $td_class    => Classe CSS de la balise <td>
    
function Display2DA($table_class ""$tr_class ""$td_class "") {
        
// Définition d'un buffer de retour vide
        
$rBuffer "";
        
// Début du tableau
        
$rBuffer .= "<table";
        if(
strlen($table_class)>0$rBuffer .= " class=\"".$table_class."\">"; else $rBuffer .= ">";
        
// Ajout des entêtes
        
$rBuffer .= "<tr";
        if(
strlen($tr_class)>0$rBuffer .= " class=\"".$tr_class."\">"; else $rBuffer .= ">";
        for(
$i=0;$i $this->nNumCols;$i++) {
            
$rBuffer .= "<td";
            if(
strlen($td_class)>0$rBuffer .= " class=\"".$td_class."\">"; else $rBuffer .= ">";
            
$rBuffer .= $this->arColsHead[$i];
            
$rBuffer .= "</td>";
        }
        
$rBuffer .= "</tr>";
        
// Ajout des lignes
        
for($i=0;$i<count($this->ar2DA);$i++) {
            
$rBuffer .= "<tr";
            if(
strlen($tr_class)>0$rBuffer .= " class=\"".$tr_class."\">"; else $rBuffer .= ">";
            for(
$j=0;$j<$this->nNumCols;$j++) {
                
$rBuffer .= "<td";
                if(
strlen($td_class)>0$rBuffer .= " class=\"".$td_class."\">"; else $rBuffer .= ">";
                
$rBuffer .= $this->ar2DA[$i][$j];
                
$rBuffer .= "</td>";
            }
            
$rBuffer .= "</tr>";
        }
        
// Fin du tableau
        
$rBuffer .= "</table>";
        echo 
$rBuffer;
    }
    
//:: Fonction : Get2DAString
    // Agit comme la fonction Get2DAString de NWN, sans passage en argument du fichier 2DA (puisque chargé dans l'objet)
    // $col        => Nom de la colone (si $col est défini sous la forme Nx ou x est un nombre quelconque, $col devient le numéro de la colone et non plus sa designation. Cette particularité n'est pas présente dans NWN.)
    // $id        => ID de la ligne visée
    
function Get2DAString($col,$id) {
        
// Récupération du numéro de la colone ciblée
        
if($col[0] == "N" && is_numeric(substr($col,1))) $nCol substr($col,1);
        else 
$nCol array_search($col,$this->arColsHead);
        if(
$nCol === FALSE || $nCol == 0) return "";    // Colonne non trouvée
        // Renvoit de la valeur
        
for($i=0;$i<count($this->ar2DA);$i++) if($this->ar2DA[$i][0] == $id) return str_replace("****","",$this->ar2DA[$i][$nCol]);
        return 
"";    // Ligne non trouvée
    
}
    
//:: Fonction : Set2DAString
    // Défini la valeur dans le fichier 2DA mais SANS LA SAUVEGARDER ! Cette fonction ne change que l'objet, il faut appeller la fonction Save2DA pour affecter le fichier.
    // $col        => Nom de la colone (si $col est défini sous la forme Nx ou x est un nombre quelconque, $col devient le numéro de la colone et non plus sa designation. Cette particularité n'est pas présente dans NWN.)
    // $id        => ID de la ligne visée
    // $value    => Valeur à assigner (attention, les espaces seront supprimés, et si la longueur est excessive, elle sera coupée)
    
function Set2DAString($col,$id,$value) {
        
// Récupération du numéro de la colone ciblée
        
if($col[0] == "N" && is_numeric(substr($col,1))) $nCol substr($col,1);
        else 
$nCol array_search($col,$this->arColsHead);
        if(
$nCol === FALSE || $nCol == 0) return "";    // Colonne non trouvée
        // Test de la validité de la valeur
        
$value trim($value);
        if(
strlen($value)>$this->arColsLen[$nCol]-1$value substr($value,0,$this->arColsLen[$nCol]-1);
        
$value str_replace(" ","",$value);
        
// Ecriture à la bonne ligne
        
for($i=0;$i<count($this->ar2DA);$i++) if($this->ar2DA[$i][0] == $id) { $this->ar2DA[$i][$nCol] = $value; return; }
        
// La ligne n'existe pas encore, hum... Et bien on la crée.
        
$this->nNumItems++;
        
$this->ar2DA[][0] = $id;
        
// Et écriture !
        
for($i=0;$i<count($this->ar2DA);$i++) if($this->ar2DA[$i][0] == $id$this->ar2DA[$i][$nCol] = $value;
    }
    
//:: Fonction : Save2DA
    // Enregistre le fichier 2DA modifié
    // $file    => Chemin du fichier où sauver le 2DA (ce fichier est remplacé si déjà existant) /!\ ATTENTION : Ce fichier doit posséder les droits en écriture (CHMOD777).
    
function Save2DA($file) {
        
// Définition du caractère de fin de ligne
        
$endline "\n";
        
// Effacage si existant
        
if(file_exists($file)) unlink($file);
        
// Ouverture du fichier
        
$fp fopen($file,"a+");
        
// Ecriture des entêtes
        
fputs($fp,$this->sHeaders);
        
// Ecriture des blancs
        
for($i=0;$i<$this->LineLen-strlen($this->sHeaders)-2;$i++) $blanc .= " ";
        
fputs($fp,$blanc.$endline);
        
// Ecriture d'une ligne de blancs
        
for($i=0;$i<$this->LineLen-2;$i++) $blanc2 .= " ";
        
fputs($fp,$blanc2.$endline);
        
// Ecriture de la ligne des entêtes
        
fputs($fp,$this->HeadLine);
        
// Ecriture du tableau
        
for($i=0;$i<count($this->ar2DA);$i++) {
            
// Chaque ligne
            
$towrite "";
            for(
$j=0;$j<count($this->ar2DA[$i]);$j++) {
                
// Chaque colonne
                
$curwrite $this->ar2DA[$i][$j];
                while(
strlen($curwrite) < $this->arColsLen[$j]) $curwrite .= " ";
                
$towrite .= $curwrite;
            }
            if(
strlen(trim($towrite))>0fputs($fp,substr($towrite,0,strlen($towrite)-1).$endline);
        }
        
// Fermeture du fichier
        
fclose($fp);
    }
}
//:: MODE D'EMPLOI
/*
    Généralités sur la Programmation Orientée Objet (POO, ou OOP en anglais) en PHP :
        [url]http://ch.php.net/manual/fr/language.oop.php[/url]
        
    Cet objet charge à son initialisation le fichier en mémoire. Si celui-ci est modifié par un
    élément externe durant l'execution du script, cette modification ne sera pas prise en compte.
    
    Exemple d'initialisation : */
$MonObjet = new C2DA("baseitems.2da");    // Charge le fichier "baseitems.2da" se trouvant au même
                                        //  endroit que le script.
/*    
    Une fois l'objet initialisé, celui-ci répond à plusieures fonctions :
      - Display2DA($table_class = "", $tr_class = "", $td_class = "")
         Cette fonction affiche le contenu du 2DA dans un tableau HTML. Vous pouvez lui passer
        en argument les classes CSS que vous souhaitez utiliser pour les différents éléments
        du tableau. Par défaut, le tableau ne possède aucun élément, et est donc compatible
        XHTML.
        Exemple : */
$MonObjet->Display2DA();                // Affiche le contenu entier du 2DA et
echo "<br /><br />";                    //  revient à la ligne deux fois
/*      - Get2DAString($col,$id)
          Cette fonction travaille exactement de la même manière que le Get2DAString de Neverwinter
        Nights, exception faite qu'elle travaille sur le 2DA chargé dans l'objet, et non pas directement
        sur un fichier. Cela se ressent au niveau des temps CPU : Le Get2DAString de NWN est beaucoup
        plus lent, car le fichier est chargé à chaqune de ses executions (ce qui est soit dit en passant
        complètement abérant, passons).
        L'argument $col est un peu spécial, il peut être le nom de la colonne choisie (case sensitive,
        comme dans NWN) ou son numéro, si son 1er caractère est N. Par exemple, "ColonneDeTest" ira 
        chercher la colonne nommée ainsi, et "N9" prendra la 9ème colonne quelque soit sa désignation.
        Exemple : */
echo $MonObjet->Get2DAString("label","31")."<br />";    // Affiche la 31ème ligne de la colonne "label" de l'objet.
echo $MonObjet->Get2DAString("N2","31")."<br />";        // Affiche la même chose, car la 2ème colonne de baseitems.2da est la colonne "label"
/*      - Set2DAString($col,$id,$value)
          Cette fonction sert à modifier l'OBJET du 2DA en cours, et non pas le fichier. L'argument $col
        travaille de la même façon que dans la fonction Get2DAString.
        L'argument $value est soumis à certains critères. Sa longueur doit correspondre au maximum
        (variable) de la colonne en cours, sinon il sera coupé. Tous ses espaces seront également effacés.
        Exemple : */
$MonObjet->Set2DAString("label","31","trucmuche");        // Défini la valeur de la colonne "label" à la 31ème ligne de l'objet en cours et...
echo $MonObjet->Get2DAString("label","31")."<br />";    //  l'affiche.
/*      - Save2DA($file)
        Cette fonction enregistre l'objet en cours dans un fichier 2DA du choix de l'utilisateur. Si
        le fichier existe déjà, il sera effacé.
        Exemple : */
$MonObjet->Save2DA("newbaseitems.2da");        // Enregistre l'objet en cours dans le fichier "newbaseitems.2da", dans le même
unset($MonObjet);                            //  répertoire que le script, et détruit l'objet.
/*    J'espère que cet objet saura vous être utile, et vous souhaite une fort agréable utilisation.

    Merci de bien vouloir reporter les bugs de ce script à l'adresse suivante :
        - [email]cdn@gmx.ch[/email]
    En spécifiant dans le sujet la mension [Classe PHP - C2DA]
    
    Programmateusement,
    -- CdN
*/ 
Lien direct vers le message - Vieux
Avatar de Taern
Taern
Alpha & Oméga
 
Avatar de Taern
 


Magnifique ! Couplé à Get2DAString, cette bibliothèque ("classe" ? ) va nous permettre de modifier toutes les options et les réglages personnalisés d'un serveur externe, grâce à une interface html

Merciiiiii
Lien direct vers le message - Vieux
Avatar de Mastokk
JOL Mastokk
Alpha & Oméga
 
Avatar de Mastokk
 
heuu ça sert à quoi ?
Lien direct vers le message - Vieux
Avatar de Ia~
Ia~
Alpha & Oméga
 
Avatar de Ia~
 
Citation:
Provient du message de Taern
cette bibliothèque ("classe" ? )
Objet
Citation:
Merciiiiii
Mais c'est un plaisir.
Citation:
Provient du message de Mastokk
heuu ça sert à quoi ?
En gros, à :
- Afficher un fichier 2DA sur une page HTML;
- Récupérer une valeur précise dans un 2DA;
- Modifier une valeur précise dans un 2DA;
- Créer un nouveau 2DA.
Lien direct vers le message - Vieux
Avatar de Ormus
Ormus
Roi
 
Avatar de Ormus
 
Désolé de mon ignorance mais...le 2DA doit se trouver où ? Il peut-être dans un hakpak ?

Enfin bravo, ça a vraiment l'air d'être du bon boulot

P.S.: Je me trompe peut-être mais j'ai l'impression que c'est la première fois que tu postes ici, alors bienvenue !
Lien direct vers le message - Vieux
Avatar de Skanzo Sylan
Skanzo Sylan
Empereur
 
Avatar de Skanzo Sylan
 
Hep hep!
Je suis nouveau aussi!

...
Ha flûte marche pô


Et bien donc, bienvenue CdN ou bon retour au cas où nous ferions un excès d'amnésie

En tout cas bon boulot, le script me semble impeccable
Mais à mon avis (qui est aussi celui d'Ormus), le 2DA ne se trouve nul part pendant que le serveur tourne, à part dans son hak-pack... à moins d'utiliser l'override
Tu dis que le script charge le fichier en mémoire, où?
Lien direct vers le message - Vieux
Avatar de Ia~
Ia~
Alpha & Oméga
 
Avatar de Ia~
 
Merci pour l'accueil

Le script charge le 2DA en RAM lors de son execution (sous forme de tableaux bidimensionnels, $obj->ar2DA pour le contenu, $obj->arColsHead pour les entête et $obj->arColsLen pour les longueurs).

Il ouvre un fichier 2DA qui doit se trouver dans un endroit non-compressé (je pensais à l'override en faisant ça ainsi).

On peut toutefois imaginer incorporer un autre module PHP qui sortirait les 2DA d'un HakPak pour les y remettre après modification, mais je ne sais pas trop comment réagirait NWN si le Hak était modifié en cours de route.

Y a-t-il une mise en cache du HakPak ? Et du répertoire d'override ? A tester, si au moins un des deux n'est pas préchargé, on peut imaginer modifier un 2DA en temps réel alors que le serveur tourne. C'est d'ailleurs pour ça que j'ai conçu le script à la base.

Pour ne rien vous cacher, va s'en suivre - très bientôt, j'ai quasiment terminé - une fonction Set2DAString pour le NWScript .
Lien direct vers le message - Vieux
Avatar de Skanzo Sylan
Skanzo Sylan
Empereur
 
Avatar de Skanzo Sylan
 
En effet, ça m'a l'air pô mal joué

Quand à savoir si le hakpack et l'override sont mis en cache, j'en ai aucune idée.
En fait la personne la mieux disposée à te répondre me semble bien être toi-même
Lien direct vers le message - Vieux
Sire Pom-pom
Roi
 
Les 2da utilisés par NWN sont en cache je crois (à vrai dire ça tient de l'intime conviction ). Tu peux les modifier en cours de route ça ne changera pas le jeu (ça fait un moment que je l'ai pas fait, parce que NWN devient de plus en plus tatillon ). Quand aux autres fichiers du hak, ils sont en "mémoire" mais gérés par l'OS non je pense?
En revanche Get2daString lit directement depuis le fichier, à chaque fois, donc pour ça ton script marchera très bien je pense.
Lien direct vers le message - Vieux
Avatar de Ia~
Ia~
Alpha & Oméga
 
Avatar de Ia~
 
C'est en couple avec la fonction Get2DAString que je pensais utiliser la fonction. Reste à savoir quel fichier 2DA cette fonction lit. Je présume que c'est comme pour le reste, à savoir dans cet ordre :

- HakPak
- Override
- 2da.bif

Me trompe-je quelque part?
Lien direct vers le message - Vieux
Sire Pom-pom
Roi
 
C'est une bonne question ça . Je suppose que oui...
Lien direct vers le message - Vieux
Avatar de Taern
Taern
Alpha & Oméga
 
Avatar de Taern
 
D'après ce que j'ai compris, la fameuse fonction de script va directement lire les fichiers sur le dur (d'où la parcimonie conseillée lors de son utilisation). Donc normalement y devrait pas y avoir d'histoire avec le hak/mémoire/cache/truc/machin

En fait, la vraie question c'est : où est-ce qu'il va chercher le 2da ? Les 2da du jeu sont contenus dans les .bif il me semble, donc peut-être qu'ils créeront un nouveau dossier 2da, ou alors y'en a déja un que j'ai pas vu ("2da source", je me demande à quoi il sert celui-là).

Quoiqu'il en soit, merchi bcp
Lien direct vers le message - Vieux
Avatar de Ia~
Ia~
Alpha & Oméga
 
Avatar de Ia~
 
Après quelques tests :

- Toutes les fonctions utilisant des données stockées dans des 2DA (j'ai testé avec GetItemACValue, aucune raison que les autres diffèrent) excepté Get2DAString ne sont pas modifiées par un changement du 2DA ni dans le HakPak, ni dans l'Override, ni dans le BIF en cours de jeu.

=> DONC : Les 2DAs sont chargés en cache au lancement du serveur.

- La fonction Get2DAString vérifie l'existence du 2DA dans le HakPak, puis dans l'Override, et si elle ne le trouve toujours pas, elle prend celui du BIF.
Cette fonction charge le 2DA à chaque exécution (et - sic - pas une seule fois par 2DA par script, malheureusement, ça aiderait 'achement).

=> DONC : On peut passer des données au jeu sans down via un 2DA personnalisé se trouvant - par exemple - dans l'override du serveur, via la commande Get2DAString.

Lien direct vers le message - Vieux
Avatar de Taern
Taern
Alpha & Oméga
 
Avatar de Taern
 
Et c'est ça qui est super ! La palette de réglages que l'on peut choisir en cours de jeu devient infinie !
Du truc classique, genre fermer le serveur, réduire le nombre de places, réserver des places aux MJs, à des trucs plus tordus, comme par exemple restreindre des zones du module à certains moments, en ouvrir d'autres, modifier des réglages en tout genre sans avoir à recompiler ni à créer un système de paramétrage ingame bien lourd (cf. HCR) etc.

Bref, que du bonheur

Par contre, dommage pour les 2da. J'aime pas trop toucher à mon override, simple réaction instinctive
Lien direct vers le message - Vieux
Avatar de Ormus
Ormus
Roi
 
Avatar de Ormus
 
A noter que les derniers .2da se trouvent dans patch.bif et non 2da.bif.
Lien direct vers le message - Vieux
Répondre
Les forums JOL > Forum jeux-vidéo > Neverwinter Nights > NWN - Maskado > [PHP] Gestion des fichiers 2DA
   

Outils Rechercher
Rechercher:

Recherche avancée

Les vidéos de Neverwinter Nights RSS
  • Aucune vidéo pour le moment...
Thème visuel : Fuseau horaire GMT +1. Il est actuellement 07h48.
   

© JeuxOnLine, le site des MMO, MMORPG et MOBA. Tous droits réservés. - Conditions générales d'utilisation - Conditions d'utilisation des forums - Traitement des données personnelles - ! Signaler un contenu illicite