Roi de France
Status: Offline
Posts: 5,049
Join Date: Nov 2003
Location: 46°43'60N 0°43'0W 0.187A
|
Re: inserting stuff into a file -
31-03-2004
I would rather advise NOT to do this in a temporary file. I'm doing something similar in my bot code ; no matter how you will do it, there's no "insert" function in the standard C libs. You have to read what's BEFORE and AFTER the part you want to change in your file, and then reassemble it together.
Code:
void BotNavSaveBrain (player_t *pPlayer)
{
// this function saves the navigation nodes in the bot's memory in a file to disk. The
// authentication being made by comparison of the recorded number of walkfaces, this data
// is written in the file at the very end of the function, to ensure an error in the save
// process won't let a badly authenticated file on disk.
MFILE *mfp;
FILE *fp;
bot_brain_t *brain;
char nav_filename[256];
char section_name_length;
navnode_t *node;
int face_index, link_index, array_index;
char *section_before = NULL, *section_after = NULL;
int section_before_size, section_after_start, section_after_size;
brain = &pPlayer->Bot.BotBrain; // quick access to bot brain
// build the file name
sprintf (nav_filename, "racc/knowledge/%s/%s.nav", server.mod_name, NormalizeChars (pPlayer->connection_name));
// get the section name
section_name_length = strlen (server.map_name) + 1;
// open the brain for updating (let's read what's before first)
mfp = mfopen (nav_filename, "rb");
if (mfp == NULL)
TerminateOnError ("BotNavLoadBrain(): Unable to operate on %s's nav brain !\n", pPlayer->connection_name);
// locate at start of the section to update
if (mfseekAtSection (mfp, server.map_name) != 0)
TerminateOnError ("BotNavSaveBrain(): Unable to locate before section to update in %s's nav brain !\n", pPlayer->connection_name);
section_before_size = mftell (mfp); // get the size of what's before the section to update
if (section_before_size == 0)
TerminateOnError ("BotNavSaveBrain(): Unable to read before section to update in %s's nav brain !\n", pPlayer->connection_name);
section_before = (char *) malloc (section_before_size + 1); // allocate memory for what's before
if (section_before == NULL)
TerminateOnError ("BotNavSaveBrain(): malloc() failure for reading before section to update in %s's nav brain !\n", pPlayer->connection_name);
mfseek (mfp, 0, SEEK_SET); // rewind at start of file
mfread (section_before, section_before_size, 1, mfp); // and read what's before section to update
// now locate after the section to update
if (mfseekAfterSection (mfp, server.map_name) != 0)
{
if (section_before != NULL)
free (section_before); // free the memory we mallocated() for what's before section to update
TerminateOnError ("BotNavSaveBrain(): Unable to locate after section to update in %s's nav brain !\n", pPlayer->connection_name);
}
section_after_start = mftell (mfp); // get the start of what's after the section to update
mfseek (mfp, 0, SEEK_END);
section_after_size = mftell (mfp) - section_after_start; // get the size of it
if (section_after_size > 0)
{
section_after = (char *) malloc (section_after_size + 1); // allocate memory for what's after
if (section_after == NULL)
{
if (section_before != NULL)
free (section_before); // free the memory we mallocated() for what's before section to update
TerminateOnError ("BotNavSaveBrain(): malloc() failure for reading after section to update in %s's nav brain !\n", pPlayer->connection_name);
}
mfseek (mfp, section_after_start, SEEK_SET); // rewind at where what's after starts
mfread (section_after, section_after_size, 1, mfp); // and read what's after section to update
}
mfclose (mfp); // everything we wanted to know from the previous brain is read, close the file
// and finally update the brain
fp = fopen (nav_filename, "wb");
if (fp == NULL)
{
if (section_before != NULL)
free (section_before); // free the memory we mallocated() for what's before section to update
if (section_after != NULL)
free (section_after); // free the memory we mallocated() for what's before section to update
TerminateOnError ("BotNavSaveBrain(): Unable to operate on %s's nav brain !\n", pPlayer->connection_name);
}
fwrite (section_before, section_before_size, 1, fp); // write what's before
fwrite ("[section]", sizeof ("[section]"), 1, fp); // section tag
fwrite (server.map_name, section_name_length, 1, fp); // section name
fwrite ("\0\0\0\0", sizeof (long), 1, fp); // fill the field with zeroes (temporarily)
// for each navigation node...
for (face_index = 0; face_index < map.walkfaces_count; face_index++)
{
node = &brain->PathMemory[face_index]; // quick access to node
// write the number of links this node has
fwrite (&node->links_count, sizeof (char), 1, fp);
// for each link of this node...
for (link_index = 0; link_index < node->links_count; link_index++)
{
// translate the pointer address into an array relative index
array_index = ((unsigned long) node->links[link_index].node_from - (unsigned long) brain->PathMemory) / sizeof (navnode_t);
if ((array_index < 0) || (array_index >= map.walkfaces_count))
TerminateOnError ("BotNavSaveBrain(): bad node array index %d (max %d), index %d/%d\n", array_index, map.walkfaces_count - 1, link_index, node->links_count);
fwrite (&array_index, sizeof (long), 1, fp); // write the walkface index of the link
// write the reachability type for this link (normal, ladder, elevator...)
fwrite (&node->links[link_index].reachability, sizeof (short), 1, fp);
// read the vector origin for this link
fwrite (&node->links[link_index].v_origin, sizeof (Vector), 1, fp);
}
}
if (section_after_size > 0)
fwrite (section_after, section_after_size, 1, fp); // and write what's after, if needed
// now that the map specific data sections have been dumped, we can write the likelevels
fseek (fp, 0, SEEK_SET); // rewind at start of file
fseek (fp, sizeof ("RACCNAV"), SEEK_CUR); // skip the "RACCNAV" tag
fseek (fp, sizeof ("[likelevels]"), SEEK_CUR); // skip the "[likelevels]" tag
fwrite (&brain->likelevel_ladder, sizeof (long), 1, fp); // write ladder likelevel
fwrite (&brain->likelevel_falledge, sizeof (long), 1, fp); // write falledge likelevel
fwrite (&brain->likelevel_elevator, sizeof (long), 1, fp); // write elevator likelevel
fwrite (&brain->likelevel_platform, sizeof (long), 1, fp); // write platform likelevel
fwrite (&brain->likelevel_conveyor, sizeof (long), 1, fp); // write conveyor likelevel
fwrite (&brain->likelevel_train, sizeof (long), 1, fp); // write train likelevel
fwrite (&brain->likelevel_longjump, sizeof (long), 1, fp); // write train likelevel
fwrite (&brain->likelevel_swim, sizeof (long), 1, fp); // write the swim likelevel
fwrite (&brain->likelevel_teleporter, sizeof (long), 1, fp); // write the teleporter likelevel
// now we're ready to write the authentication tag
fseek (fp, section_before_size, SEEK_SET); // seek back at start of section
fseek (fp, sizeof ("[section]"), SEEK_CUR); // skip the [section] tag
fseek (fp, section_name_length, SEEK_CUR); // skip the section name
fwrite (&map.walkfaces_count, sizeof (long), 1, fp); // write the # of walkfaces on map
fclose (fp); // everything is saved, close the file
if (section_before != NULL)
free (section_before); // free the memory we mallocated() for what's before section to update
if (section_after != NULL)
free (section_after); // free the memory we mallocated() for what's before section to update
return; // and return
}
I could have formatted all this better somehow, but as usuals I'm lazy.
RACC home - Bots-United: beer, babies & bots (especially the latter)
"Learn to think by yourself, else others will do it for you."
|