Aller au contenu

Photo

nwnx - loading external data to nwn


  • Veuillez vous connecter pour répondre
28 réponses à ce sujet

#1
Valgav

Valgav
  • Members
  • 64 messages

As we all know nwnx string is the only way to feed nwn with external data. Dosen't matter if you're using sockets, sql, text files you'll always end with nwnx string.

 

My question is how effective it is for large structures? Doing many things outside nwn using object orientated languages is much simpler(it would be even simpler if i could call nwn functions to give parameters, but I have no idea how to hook main loop to call them on fly) and then use method toString() to forward it to nwn. 

 

But then I have to parse the whole string to structure or load it in sequential order during running algorithm in nwn.

 

What are best practices to work with that kind of data flow? What if i have multiple sources at the same time(sockets won't work because you have to send message and then listen for correct one)



#2
henesua

henesua
  • Members
  • 3 863 messages

can you provide a more concrete example? are you talking about retrieving data from a DB which you've stored as a custom object that you need to convert into an NWN object?

 

i wouldn't bother which such stuff. I think its easier just to store and retrieve NWN objects.

 

or do you have a need of a very complex persistent data model for all your custom systems? or something else?



#3
Valgav

Valgav
  • Members
  • 64 messages

Problem with storing objects (as for example blobs) is that you can't get info about it any other way than using nwn. You have sword but you don't know what kind of sword. So you should store object and meta and there's no easy way to parse dat data outside nwn(even inside it's terrible, how to store that it has enchanment +2 and 1d6 against undeads when you always work on effects represented by consts.)

 

Also storing other informations like spawns. You cans simply create object or database structure for spawn which contains 5 kobolds with resref kobold_01 two shamans with resref kobold_shaman etc.

 

Then you can load erfs and add info to database to have complete info about objects on your server available from nwn and outside of it.

 

I know that for most people that kind of staff is overkill but it's crucial for modules that have many custom systems and want to maintain flexibility. Using database or external files to feed logic with parameters is best and most universal way to keep all those systems simple.



#4
henesua

henesua
  • Members
  • 3 863 messages

I understand what you are saying, but you have not given a concrete use case, and you have also overstated the problem. There are ways to read the binary files outside of NWN. You may need to custom code things yourself, or glue existing apps together with NWNX using a scripting language like ruby or perl, but you can read GFFs and ERFs outside of NWN.

 

I believe you are probably somewhat limited with NWNX and other community tools since windows is your preferred server (if I heard you right). But even then you've got resources to use.



#5
Valgav

Valgav
  • Members
  • 64 messages
I'm not sure if there's a method to parse object to gff or refer to corresponding uti file. Also one more question. Does resref=filename?

#6
Shadooow

Shadooow
  • Members
  • 4 468 messages

Does resref=filename?

Resref is always lowercase while filename may have some uppercase letters. At least thats the case for vanilla content.

 

This is not a problem on windows, but might be on linux.



#7
meaglyn

meaglyn
  • Members
  • 807 messages

A BLOB to YML and back tool would be pretty cool.  I have no idea what format the stored object is in though. I don't believe it's a GFF file since it's a representation of the in memory object. But I could be wrong...  I don't seem to have any objects persisted at the moment to look at.



#8
Proleric

Proleric
  • Members
  • 2 346 messages
Does this need to be in real time?

moneo is a great tool for reading and updating the uti files etc, but it edits the module, not the current session.

#9
meaglyn

meaglyn
  • Members
  • 807 messages

Those tools and the YML ones I prefer work on GFF files.  Do you know that the stored object (SCO/RCO) format is actually also a GFF format?  I suppose it could still be GFF but these are not uti files.  If it is still GFF then it could be pulled out of MYSQL and modified and replaced. 


  • henesua aime ceci

#10
Valgav

Valgav
  • Members
  • 64 messages
In fact nwnx_dynres and nwnx_data have functions for converting objects to files. Dynres converts creatures to utc, data to bic and both convert items to uti.

So we can parse whole objects to database using nwn library.

Then we can probably use html gui to create new objects and parse them to uti or utc files. Including texts from dialog.tlk and relations between item properties we can reproduce creating items on fly.

That allows us to create new crafting resources on fly, assign them to drops and give them parameters for crafting.

It makes nwn much more modular and dynamic from builder perspective.

#11
meaglyn

meaglyn
  • Members
  • 807 messages

In fact nwnx_dynres and nwnx_data have functions for converting objects to files. Dynres converts creatures to utc, data to bic and both convert items to uti.

Cool. I did not know it would do that. That could do the trick although you'd have to persist it differently than SCORCO.

 

Edit: Those are both windows plugins aren't they? I don't see them in the linux tree.



#12
KMdS!

KMdS!
  • Members
  • 189 messages

You can also export the blob to file. I keeps it's gff format. You can then use any gff reader/editor program, like the Leto program, to actualy look at the file, modify it as needed, then save the file. If you are familiar with moneo, you can use that to modify the item file as well.That same file can then be imported into the database using SQL from with in nwn->nwnx, or with a script from the whatever program you use to evaluate your database directly. From there you can reinsert it into the running game using the retrieve object function in NWNX.

 

That would be platform independant.


  • henesua et meaglyn aiment ceci

#13
meaglyn

meaglyn
  • Members
  • 807 messages

So the blob is GFF?  That makes it pretty straight forward then... I'll have to poke at that.

 

Edit: Coolio.  the blob is indeed just a gff formatted file. In my persisted chest case its a utc.  nwn-lib was perfectly happy with it. That'll be fun to play with. So many things to hack on so little time... :)



#14
KMdS!

KMdS!
  • Members
  • 189 messages

Poke, Poke...... Is it dead yet? :ph34r:



#15
Valgav

Valgav
  • Members
  • 64 messages

@meaglyn yes they're windows plugins.

 

The approach with blob is nice but it's not what i want.

 

I want to be able to load objects(especially items) to gui(html form?) in form that user will understand. So properties showed not as numbers but e.g.. 1d6 fire dmg.

Then i can edit them create copies with other parameters etc.

 

There are to possible approaches. Full database and db + yaml. In both cases i would store in db resref, instances, owner of instances etc.

 

In full db approach main problem is to parse between yaml and db in both directions. Also I would need additional tables to store values of parameters for every instance which could lead to very big tables.

 

Advantage of that approach is that we're separated from nwn logic, any tool can import data from db and load it back. Yaml is simpel but it has to be yaml that yml2gff will understand. Potentially it would allow to create objects on fly without toolset. We'are able to identify single instance of object by table id stored on item as variable.

 

 Another approach is to use yaml files to store properties. Parser is between yaml and gui so we can work straight on files which sound much easier. Disadvantage is that we're still tied to nwn technology also we have to store multiple files if instances are different which lead as to multiple resrefs etc. But it's easier to get object back to game.

 

 

Any thoughts?



#16
henesua

henesua
  • Members
  • 3 863 messages

One word: nwn-lib



#17
meaglyn

meaglyn
  • Members
  • 807 messages

nwn-lib works on GFF files. Still not convinced the BLOB stored by SCORCO into mysql is a GFF file (but as I said, I could be wrong about that).   But nwn-lib by itself is not a solution to what was asked. What you really want is the toolset, it sounds like.   Aenea  had an player item build module which players used to create special items then export as erfs which AD would arrange to make available to the PC in game.  That way they had full access to the hak content and the 2das and the user interface.   Just a (stolen) idea...



#18
henesua

henesua
  • Members
  • 3 863 messages

My bad then.

 

I assumed the OP was talking about creating a web interface for editing assets in an external database or just folders on the server.



#19
meaglyn

meaglyn
  • Members
  • 807 messages

Nothing bad. I love nwn-lib :)    The user friendly names and such makes it different though.  The SCORCO thing is my thing because I think it would be cool to be able to modify the persisted objects. But the OP did talk about exporting to/importing from nwnx strings so I was just extending that to NWNX persisted objects as a possible way to get around converting to string to pass the data into NWN and then parsing the string to figure out itemprops etc in nwscript to create the new item.  Using SCORCO, assuming you could modify/create the BLOB externally could make that a lot simpler.  nwn-lib could certainly be a part of a solution... (again assuming the blobs are GFF).



#20
Valgav

Valgav
  • Members
  • 64 messages
I'm the one to be blamed for chaos in this thread. There are two problems. One is about parsing complicated logic to nwn. The other is outsourcing it to external calls which developed over the discussion.

Item example is a good one. We can use nwn approach and we have to parse all parameters like appearance, properties, item type etc. in game and provide them as String not structure. Other approach is to built object outside and just pass the name of files to call resman/dynres to load it and create object from palette.

Sorry for making it complicated but I have habit to change and develop problems during the discussion ;)

So currently doing as much logic outside nwn sounds like a better idea. I know about nwn-lib but there's still problem with parsing yaml to something easier to understand by human. Also I'm not sure for now if gff/yaml contain variables stored on object

#21
meaglyn

meaglyn
  • Members
  • 807 messages

Any non-object variables should be there in the GFF file.   You could export the blob to gff, put that into a build module, tweak as desired, export erf, crack it open pull out the gff and insert/update it back into mysql.  I know that is not a web interface but it gives you all the human readable parts. The toolsset is more or less a fancy gff file editor after all.



#22
KMdS!

KMdS!
  • Members
  • 189 messages

Still not convinced the BLOB stored by SCORCO into mysql is a GFF file (but as I said, I could be wrong about that).

I have done the testing. While the file exported by the database has the *.txt extension, the format remains GFF. Changing the extension of the fie to *.gff/uti, etc, will allow a specific editor read the file if the specific extension is required by the editor being used. ;) .  If you think about it, the gff structure must be preserved if you are going to "GetObject" the file data back into the server. NWNx does not interpret the file exorted, nor does it interpret the returning blob.

 

I now understand the request of the owner of the thread. You effectively want the toolset object editor in a web based gui. I am sorry to say that I am not aware of an actual GUI interface for RUBY. It would be a wonderful thing. I have an idea of what and how it might be done using php/moneo-nwnxleto/MySql, but it would be a bit of work. If it already exists, someone shine a light.



#23
Baaleos

Baaleos
  • Members
  • 1 329 messages

nwn-tools.jar : allows the conversion of gff to xml.

XML can then be edited, and then recompiled back into gff for use in the game.

It seems that quite alot of people are using this approach in continuous integrations for deploying their module/pw.

Eg: They generate their module.ifo dynamically from the contents of their areas folder. etc

 

Eg:

<!-- This file was generated by the NWNTools GFF to XML writer.
     http://nwntools.sf.net/
     ** Do not hand edit unless you know what you are doing. **
 -->
<gff name="module.ifo" type="IFO " version="V3.2" >
    <struct id="-1" >
        <element name="Mod_ID" type="13" value="byte[16][1e][d6][9d][21][65][85][ac][e9][e9][41][4f][99][cd][33][32][7e]" />
        <element name="Mod_MinGameVer" type="10" value="1.69" />
        <element name="Mod_Creator_ID" type="5" value="2" />
        <element name="Mod_Version" type="4" value="3" />
        <element name="Expansion_Pack" type="2" value="3" />
        <element name="Mod_Name" type="12" value="-1" >
            <localString languageId="0" value="MyModule" />
        </element>
        <element name="Mod_Tag" type="10" value="MODULE" />
        <element name="Mod_Description" type="12" value="-1" />
        <element name="Mod_IsSaveGame" type="0" value="0" />
        <element name="Mod_CustomTlk" type="10" value="cep260" />
        <element name="Mod_Entry_Area" type="11" value="area001" />
        <element name="Mod_Entry_X" type="8" value="39.0" />
        <element name="Mod_Entry_Y" type="8" value="34.0" />
        <element name="Mod_Entry_Z" type="8" value="0.0" />
        <element name="Mod_Entry_Dir_X" type="8" value="0.0" />
        <element name="Mod_Entry_Dir_Y" type="8" value="1.0" />
        <element name="Mod_Expan_List" type="15" />
        <element name="Mod_DawnHour" type="0" value="7" />
        <element name="Mod_DuskHour" type="0" value="19" />
        <element name="Mod_MinPerHour" type="0" value="3" />
        <element name="Mod_StartMonth" type="0" value="6" />
        <element name="Mod_StartDay" type="0" value="1" />
        <element name="Mod_StartHour" type="0" value="13" />
        <element name="Mod_StartYear" type="4" value="1354" />
        <element name="Mod_XPScale" type="0" value="10" />
        <element name="Mod_OnHeartbeat" type="11" value="" />
        <element name="Mod_OnModLoad" type="11" value="_mod_load" />
        <element name="Mod_OnModStart" type="11" value="" />
        <element name="Mod_OnClientEntr" type="11" value="_on_client_enter" />
        <element name="Mod_OnClientLeav" type="11" value="_on_client_exit" />
        <element name="Mod_OnActvtItem" type="11" value="_on_activate_itm" />
        <element name="Mod_OnAcquirItem" type="11" value="_on_acquire_item" />
        <element name="Mod_OnUsrDefined" type="11" value="" />
        <element name="Mod_OnUnAqreItem" type="11" value="_on_unacquire" />
        <element name="Mod_OnPlrDeath" type="11" value="_player_death" />
        <element name="Mod_OnPlrDying" type="11" value="_on_player_dying" />
        <element name="Mod_OnPlrEqItm" type="11" value="_on_player_equip" />
        <element name="Mod_OnPlrLvlUp" type="11" value="" />
        <element name="Mod_OnSpawnBtnDn" type="11" value="_on_player_respa" />
        <element name="Mod_OnPlrRest" type="11" value="_on_player_rest" />
        <element name="Mod_OnPlrUnEqItm" type="11" value="_on_player_unequ" />
        <element name="Mod_OnCutsnAbort" type="11" value="" />
        <element name="Mod_OnPlrChat" type="11" value="" />
        <element name="Mod_StartMovie" type="11" value="" />
        <element name="Mod_CutSceneList" type="15" />
        <element name="Mod_GVar_List" type="15" />
        <element name="Mod_Area_list" type="15" >
            <struct id="6" >
                <element name="Area_Name" type="11" value="cep_starter_001" />
            </struct>
            <struct id="6" >
                <element name="Area_Name" type="11" value="darkawakening" />
            </struct>
            <struct id="6" >
                <element name="Area_Name" type="11" value="area001" />
            </struct>
            <struct id="6" >
                <element name="Area_Name" type="11" value="area" />
            </struct>
        </element>
        <element name="Mod_HakList" type="15" >
            <struct id="8" >
                <element name="Mod_Hak" type="10" value="cep2_add_doors" />
            </struct>
            <struct id="8" >
                <element name="Mod_Hak" type="10" value="cep2_add_loads" />
            </struct>
            <struct id="8" >
                <element name="Mod_Hak" type="10" value="cep2_add_skies" />
            </struct>
            <struct id="8" >
                <element name="Mod_Hak" type="10" value="cep2_add_tiles1" />
            </struct>
            <struct id="8" >
                <element name="Mod_Hak" type="10" value="cep2_add_tiles2" />
            </struct>
            <struct id="8" >
                <element name="Mod_Hak" type="10" value="cep2_build" />
            </struct>
            <struct id="8" >
                <element name="Mod_Hak" type="10" value="cep2_top_2_60" />
            </struct>
            <struct id="8" >
                <element name="Mod_Hak" type="10" value="cep2_add_phenos1" />
            </struct>
            <struct id="8" >
                <element name="Mod_Hak" type="10" value="cep2_add_phenos2" />
            </struct>
            <struct id="8" >
                <element name="Mod_Hak" type="10" value="cep2_add_phenos3" />
            </struct>
            <struct id="8" >
                <element name="Mod_Hak" type="10" value="cep2_add_phenos4" />
            </struct>
            <struct id="8" >
                <element name="Mod_Hak" type="10" value="cep2_add_phenos5" />
            </struct>
            <struct id="8" >
                <element name="Mod_Hak" type="10" value="cep2_core0" />
            </struct>
            <struct id="8" >
                <element name="Mod_Hak" type="10" value="cep2_core1" />
            </struct>
            <struct id="8" >
                <element name="Mod_Hak" type="10" value="cep2_core2" />
            </struct>
            <struct id="8" >
                <element name="Mod_Hak" type="10" value="cep2_core3" />
            </struct>
            <struct id="8" >
                <element name="Mod_Hak" type="10" value="cep2_core4" />
            </struct>
            <struct id="8" >
                <element name="Mod_Hak" type="10" value="cep2_core5" />
            </struct>
            <struct id="8" >
                <element name="Mod_Hak" type="10" value="cep2_core6" />
            </struct>
            <struct id="8" >
                <element name="Mod_Hak" type="10" value="cep2_core7" />
            </struct>
        </element>
        <element name="Mod_CacheNSSList" type="15" />
    </struct>
</gff>


#24
Valgav

Valgav
  • Members
  • 64 messages
Is there any specific reason to use module.ifo instead of having files in folders and load them dynamically using resman/dynres?

Also I hate java but I must admit that xml seems to be a lot easier approach than yaml

EDIT: nwn-lib also contains conversion to xml

#25
Baaleos

Baaleos
  • Members
  • 1 329 messages

Well module.ifo is required in order to set the areas that are instantiated at startup.

It also sets the scripts, xp scale, day night times etc.

 

But yes - nwnx can set most of that anyway.

A module.ifo is required for it to be considered a valid module in any case.

It was just an example.

An IFO file is a gff structure, it was just being used to show how gff data can be represented as an XML, allowing you to construct your gff structures (items, creatures etc) outside of toolset , and then compile and import later.