Jump to content

[Résolu] Problème avec mon carshop


Recommended Posts

Salut, j'ai eu l'idée de faire mon carshop RP mais j'ai un problème au niveau de la sauvegarde des véhicules, j'explique: j'ai créer une commande permettant de sauvegarder le véhicule dans lequel nous sommes dans un fichier xml, c'est ici que l'erreur se produit, la sauvegarde ne s'effectue pas (mais je n'ai aucunes erreurs dans le debugscript niveau 3) mais pourtant lorsque je met manuellement un véhicule dans le xml (plutôt long à faire) celui spawn sans problèmes, bref, voici un aperçu de la scène du crime:

function saveVehicule(veh) 
        local file = xmlLoadFile("cars/stock.xml") 
        local child = xmlCreateChild(file, "vehicle") 
        -- GET VEHICLE -- 
        local vehName = getVehicleName(veh) 
        local lights = getVehicleOverrideLights(veh) 
        local r1, g1, b1, r2, g2, b2, r3, g3, b3, r4, g4, b4 = getVehicleColor(veh, true) 
        local paint = getVehiclePaintjob(veh) 
        local plate = getVehiclePlateText(veh) 
        local engine = getVehicleEngineState(veh) 
        local lock = isVehicleLocked(veh) 
        local id = getVehicleModelFromName(vehName) 
        local x, y, z = getElementPosition(veh) 
        local rx, ry, rz = getElementRotation(veh) 
        local howner = getElementData(veh, "owner") 
        local fuel = getElementData(veh, "fuel") 
        local price = getElementData(veh, "price") 
        local dist = getElementData(veh, "distance") 
        local brake = isElementFrozen(veh) 
        local motor = getElementData(veh, "motorS") 
        -- SAVE VEHICLE -- 
        xmlNodeSetAttribute(child, "name", vehName) 
        xmlNodeSetAttribute(child, "id", tostring(id)) 
        xmlNodeSetAttribute(child, "r1", tostring(r1)) 
        xmlNodeSetAttribute(child, "g1", tostring(g1)) 
        xmlNodeSetAttribute(child, "b1", tostring(b1)) 
        xmlNodeSetAttribute(child, "r2", tostring(r2)) 
        xmlNodeSetAttribute(child, "g2", tostring(g2)) 
        xmlNodeSetAttribute(child, "b2", tostring(b2)) 
        xmlNodeSetAttribute(child, "paint", tostring(paint)) 
        xmlNodeSetAttribute(child, "lights", tostring(lights)) 
        xmlNodeSetAttribute(child, "plate", plate) 
        xmlNodeSetAttribute(child, "engine", tostring(engine)) 
        xmlNodeSetAttribute(child, "lock", tostring(lock)) 
        xmlNodeSetAttribute(child, "x", tostring(x)) 
        xmlNodeSetAttribute(child, "y", tostring(y)) 
        xmlNodeSetAttribute(child, "z", tostring(z)) 
        xmlNodeSetAttribute(child, "rot", tostring(rz)) 
        xmlNodeSetAttribute(child, "owner", howner) 
        xmlNodeSetAttribute(child, "fuel", fuel) 
        xmlNodeSetAttribute(child, "price", price) 
        xmlNodeSetAttribute(child, "distance", dist) 
        xmlNodeSetAttribute(child, "brake", tostring(brake)) 
        xmlNodeSetAttribute(child, "motor", motor) 
        xmlSaveFile(file) 
        xmlUnloadFile(file) 
end 
  
addCommandHandler("saveVehicle", 
    function (playerSource, cmd, price) 
        if (price) then 
            local veh = getPedOccupiedVehicle(playerSource) 
            if (veh) then 
                local data = setElementData(veh, "price", tostring(price)) 
                local save = saveVehicule(veh) 
                if (data) and (save) then 
                    outputChatBox("Véhicule sauvegardé avec succès !", playerSource, 255, 0, 255, false) 
                elseif not (data) then 
                    outputChatBox("Erreur lors de la sauvegarde du véhicule. (data)", playerSource, 255, 0, 255, false) 
                elseif not (save) then 
                    outputChatBox("Erreur lors de la sauvegarde du véhicule. (save)", playerSource, 255, 0, 255, false) 
                end 
            end 
        end 
    end 
) 

Comme on peut le voir, j'ai bien mis ce qu'il faut pour sauvegarder

xmlSaveFile(file) 

mais j'ai cette erreur:

outputChatBox("Erreur lors de la sauvegarde du véhicule. (save)", playerSource, 255, 0, 255, false) 

Pour plus de précisions, je dirais que mon *.lua est à la racine de la resource et que le xml "stock.xml" est bien dans le fichier "cars" (j'en suis certain puisque comme dit plus haut, les véhicules sauvegardés "à la main" se chargent très bien. J'ajoute aussi que la ligne ne s'ajoute pas au fichier xml. J'en suis allé au point de lister le xml dans le meta

<file src="cars/stock.xml" /> 

mais bien sûre cela n'a pas marché :P

Merci d'avance pour autre aide est bone journée (ou soirée tout dépend du moment ou vous lisez :D )

EDIT: Si je met ce script en client, les véhicules se sauvegardent mais ils ne spawnent pas comme si le script était côté server

Edited by Guest
Link to comment
  • Moderators

Hmmmm ça me paraît bizarre en effet ...

Déjà première chose, ta fonction saveVehicule ne retournant rien, ta variable save vaudra toujours nil et t'affichera ton erreur dans la chatbox même si la sauvegarde a fonctionnée.

Corrige ta fonction à la fin comme ceci:

return xmlSaveFile(file) and xmlUnloadFile(file) 

Ta variable save vaudra true si les 2 fonctions ont renvoyées toutes les deux true, false si au moins l'une des deux a renvoyée false ou nil.

Du coup la question stupide mais qui peut s'avérer être correcte si tu ne t'es basé que sur ton message d'erreur: Es-tu bien sûr qu'aucune ligne supplémentaire n'a été ajouté à ton fichier xml ? Regarde bien parce qu'au moment de la sauvegarde, une nouvelle ligne n'est pas obligatoirement sauvegardée à la fin (et n'est donc pas forcément le dernier tag de la liste.

Autre test à faire, c'est d'essayer de rajouter un tag avec juste un attribut pour tester:

1 - Commente tous tes xmlNodeSetAttribute

2 - Ajoute juste cette ligne (après celles commentées):

xmlNodeSetAttribute(child, "test", "dfigfjf") 

3 - Essaye de sauvegarder un véhicule (en checkant le debugscript 3, ta chatbox pour tes messages et ton xml).

Sinon essaye de mettre ta ressource dans le groupe Admin dans l'ACL (normalement y a pas besoin mais vu comme c'est partit, ça ne coûte rien d'essayer).

Et oui le tag file dans la meta sert à marquer les fichiers qui doivent être téléchargés par le client.

J'attends le retour de tes tests.

Cordialement,

Citizen

Link to comment

Merci pour la réponse, en ce qui concerne de mettre la resource en admin, j'ai déjà mis toutes mes resources en admin avec un "resources.*".

Ensuite pour la vérification que le véhicule soit au bon emplacement, c'est pas compliqué, sur deux véhicules dans mon fichier xml, je n'ai pas de 3ème qui s'ajoute (mais comme dit dans l'edit, côté client, il s'ajoute mais il ne spawn pas tandis que les véhicules ajoutés "à la main" spawn correctement.

Pour y remédier j'ai essayé de copier (via xmlCopyFile) le fichier en server mais il ne se copiait pas (ou plutôt il ne se sauvegardait pas ^^).

Pour finir, il me faut juste faire le test mais cela me semble tout de même bizzare que seul les véhicules sauvegardés via le script ne spawn pas (pourtant j'ai comparé le véhicule que j'ai mis moi-même avec celui sauvegardé via le script, tout est correct).

J'ai eu une hypothèse qui est que seul les véhicules enregistrés côté server spawnent, c'est d'ailleurs pour ça que j'ai essayé de faure des auto-copies du xml client pour avoir une copie server mais comme dit en haut la sauvegarde de la copie ne marche pas...

Link to comment
  • Moderators

Si tu sauvegardes le xml du côté client, le xml est stocké sur le PC du joueur qui run le script en question. Hors ton système de chargement est du côté serveur et spawn les véhicules en chargeant le fichier xml dans le dossier cars de la ressource qui elle est sur le serveur. Si tu veux transférer un fichier côté client vers le serveur, il faut que le client ouvre le fichiers, transfert son contenu via un ou plusieurs triggerServerEvent que tu réceptionnes côté serveur pour ensuite écrire ce contenu dans un fichier que le serveur aura créé et ouvert en écriture. Mais je te déconseille fortement de faire ça car le client pourrait envoyer n'importe quoi via une version custom du jeu trafiqué et surtout tu pourrait avoir des conflits si des clients t'envois au même moment 2 versions de ce fichier modifié.

C'est aussi pourquoi les sauvegardes dans un fichier .xml sont déconseillés bien que rapide et simple à mettre en place.

Il faudrait que tu vérifies également si tu appelles bien un xmlUnloadFile après le chargement des véhicules.

Link to comment

c'est ce que j'ai fait avec un triggerServerEvent

client

function createFile(startedResource) 
    local file = xmlLoadFile("cars/stock.xml") 
    if not (file) then 
        local file = xmlCreateFile("cars/stock.xml", "vehicles") 
        xmlSaveFile(file) 
        xmlUnloadFile(file) 
    end 
    local file = xmlLoadFile("cars/stock.xml") 
    triggerServerEvent("onCopyVehicles", resourceRoot, file) 
end 
addEventHandler("onClientResourceStart", getResourceRootElement(getThisResource()), createFile) 

server

function copyVehicles(file) 
    local file = xmlCopyFile(file, "stock.xml") 
    xmlSaveFile(file) 
    xmlUnloadFile(file) 
end 
addEvent("onCopyVehicles", true) 
addEventHandler("onCopyVehicles", resourceRoot, copyVehicles) 

Par contre l'erreur peut peut-être venir de "resourceRoot" parceque je ne suis pas sûre que ce soit ça...

Link to comment
  • Moderators

Nan ce code ne fait pas ce que j'ai dit. Ton code de transfert ouvre le xml côté client via un xmlLoadFile. Cette fonction va te charger que le node racine et ne va jamais charger l'intégralité du fichier (imagine un .xml de 4Go sur un serveur qui n'a que 2Go de RAM ... C'est le crash assuré). Et c'est à chaque fois que tu demanderas de lire ou écrire que le système va lire le fichier (mais toujours de façon à ne pas tout charger).

Et comme c'est des types d’éléments spéciaux relatifs au PC qui le fait tourner (il contient des données internes comme l'emplacement du fichier sur l'ordinateur et qui n'est bien évidement pas copiable car le chemin ne correspondra à rien du côté serveur).

Ce qu'il faut faire c'est ouvrir le fichier avec fileOpen, le lire morceaux par morceaux (ouai toujours l'histoire du cas où le fichier ferait 4Go, tu ne veux pas charger l'intégralité du fichier d'un coup).

C'est exactement ce que fait l'exemple du wiki:

local hFile = fileOpen("test.txt", true)       -- attempt to open the file (read only) 
if hFile then                                  -- check if it was successfully opened 
    local buffer 
    while not fileIsEOF(hFile) do              -- as long as we're not at the end of the file... 
        buffer = fileRead(hFile, 500)          -- ... read the next 500 bytes... 
        outputConsole(buffer)                  -- ... and output them to the console 
    end 
    fileClose(hFile)                           -- close the file once we're done with it 
else 
    outputConsole("Unable to open test.txt") 
end 

Bon lui il lit des morceaux (buffer) de 500 Octets, tu peux te permettre plus que ça, genre 5Ko par 5Ko (5Ko = 5 * 1024 Octets).

C'est le contenu de buffer que tu dois envoyer à ton serveur via un triggerServerEvent car il contient réellement le texte de ton fichier (enfin un morceau seulement).

Donc au lieu du outputChatBox, tu utilises ton trigger.

Du côté serveur, un premier trigger doit te dire de se préparer à recevoir des données en créant et ouvrant un fichier (fileCreate/fileOpen) en mode écriture, tu envois un trigger au client pour dire qu'il est prêt à recevoir et tu attends les morceaux via les triggers.

A chaque trigger de l'event, tu fileWriteles morceaux que le client t'envois.

Le client termine par envoyer un trigger pour dire que c'est finit, à ce moment là tu fileSaveet fileUnload.

Mais je le répète, ne fait pas ça pour ton système de carshop.

Sinon ... qu'a donné le test ?

Link to comment

Merci, j'avais pas bien compris. Et puis pour le test, il marche bien, et quelque chose d'étrange est arrivé, lorsque j'ai décommenté mes lignes (j'avais fait un simple bloc avec "--[[...]] ") et que j'ai commenté la ligne du test, le script s'est mis à marcher sans plus de problèmes. J'éspère que sa vas durer et je trouve ça très étrange que le script ne marchait pas avant le test.

En tout cas merci pour l'aide et l'ex-problème resteras toujours un mystère pour moi :D

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...