AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Scripting (https://forums.alliedmods.net/forumdisplay.php?f=107)
-   -   Text File Handling (https://forums.alliedmods.net/showthread.php?t=288778)

stickz 10-07-2016 15:43

Text File Handling
 
I made this code to store and read the previous ten maps in text files. And push them to an adt array.

But now I want to store thirty maps in a text file and this method is horribly crude. Is there a better way to accomplish this task, like to store the content in one text file? The last time I tried writing to a different line, it went horrible with 100's of spacers between lines. :(

PHP Code:

#define ARRAY_STORE_COUNT     9

#define MAP_SIZE 32
#define READ_END -1

Handle g_ExcludeMapList INVALID_HANDLE;

public 
void OnPluginStart()
{
    
/* Create the excluded map array list */
    
g_ExcludeMapList CreateArray(ByteCountToCells(PLATFORM_MAX_PATH)); 
}

char nd_text_file[ARRAY_STORE_COUNT][] =
{
    
"data/lastmap.txt",
    
"data/lastmap2.txt",
    
"data/lastmap3.txt",
    
"data/lastmap4.txt",
    
"data/lastmap5.txt",
    
"data/lastmap6.txt",
    
"data/lastmap7.txt",
    
"data/lastmap8.txt",
    
"data/lastmap9.txt"
};

void CreateTextFile()
{
    
/* For the number of previousily stored maps */
    
for (int idx 0idx ARRAY_STORE_COUNTidx++)
    {
        
/* Build a path to the text file */
        
char path[PLATFORM_MAX_PATH];
        
BuildPath(Path_SMpathPLATFORM_MAX_PATHnd_text_file[idx]);
        
        
/* Check if the file does not already exist */
        
if (!FileExists(path))
        {
            
/* Create the non-existent file */            
            
Handle fileHandle OpenFile(path"w");
            
CloseHandle(fileHandle);    
        }    
    }    
}

void ReadTextFile()
{
    
/* Clear the last map exclude array */
    
ClearArray(g_ExcludeMapList);
        
    
/* For the number of previousily stored maps */
    
for (int idx 0idx ARRAY_STORE_COUNTidx++)
    {
        
/* Build the file path based on the array index */        
        
char path[PLATFORM_MAX_PATH];
        
BuildPath(Path_SMpathPLATFORM_MAX_PATHnd_text_file[idx]);
        
        
/* Open file to with the read letter */
        
Handle fileHandle OpenFile(path"r");
        
        
/* Copy file contents to the map string */
        
char map[MAP_SIZE];
        
ReadFileString(fileHandlemapsizeof(map), READ_END); 
        
        
/* Push the map string to the end of the exclude array */
        
PushArrayString(g_ExcludeMapListmap); 
        
        
/* Close the handle to the file we just opened */
        
CloseHandle(fileHandle);
    }
}

void WriteTextFile()
{    
    
/* For the number of previousily stored maps */
    
for (int idx 0idx ARRAY_STORE_COUNTidx++)
    {
        
/* Build the file path based on the array index */        
        
char path[PLATFORM_MAX_PATH];
        
BuildPath(Path_SMpathPLATFORM_MAX_PATHnd_text_file[idx]);
        
        
/* Delete the file */
        
DeleteFile(path);
        
        
/* Create a new file with the same name for writing */
        
Handle fileHandle OpenFile(path"w");
        
        
/* Copy map at idx from the exclude array to the lastMap string */
        
char lastMap[MAP_SIZE];
        
GetArrayString(g_ExcludeMapListidxlastMapsizeof(lastMap));
        
        
/* Write the last map string to the opened file */        
        
WriteFileString(fileHandlelastMaptrue);
        
        
/* Close the handle to the file we just created */
        
CloseHandle(fileHandle);    
    }



Grey83 10-07-2016 20:09

Re: Text File Handling
 
why don't just
PHP Code:

con_logfile maphistory.txt
sm_maphistory 

in the server console? =)

UPD or try this, but there contains more then 10 last maps
PHP Code:

ConVar hName;
char sName[32], map[32], file[256];

public 
void OnPluginStart()
{
    
hName CreateConVar("sm_mh_name""server.txt""Name of the log-file for server's hystory of map"FCVAR_PRINTABLEONLY);
    
hName.GetString(sNamesizeof(sName));
    
CheckName();
}
public 
void OnConfigsExecuted()
{
    
HookConVarChange(hNameOnNameChanged);
}

public 
void OnNameChanged(ConVar cvar, const char[] oldValue, const char[] newValue)
{
    
GetConVarString(cvarsNamesizeof(sName));
    
CheckName();
}

void CheckName()
{
    
TrimString(sName);
    if(!
sName[0])
    {
        
PrintToServer("[MapHistory] The name of the file must be not empty!\n    Changed to 'server.txt'.")
        
sName "server.txt"
    
}
    
BuildPath(Path_SMfilesizeof(file), "logs/%s"sName);
}

public 
void OnMapStart()
{
    
GetCurrentMap(mapsizeof(map));
    
LogToFileEx(file"%s"map);



stickz 10-08-2016 08:53

Re: Text File Handling
 
Quote:

Originally Posted by Grey83 (Post 2460164)
why don't just
PHP Code:

con_logfile maphistory.txt
sm_maphistory 

in the server console? =)

Server console returned unknown command for con_logfile maphistory.txt.

Quote:

Originally Posted by Grey83 (Post 2460164)
PHP Code:

public void OnMapStart()
{
    
GetCurrentMap(mapsizeof(map));
    
LogToFileEx(file"%s"map);



Will LogToFileEx() just print the name of the map on a new line? And nothing else (like dates, time, plugin etc.)? If not it would create extra unneeded work parsing the file.

Grey83 10-08-2016 09:17

Re: Text File Handling
 
stickz, with LogToFileEx:
Quote:

L 10/08/2016 - 11:44:13: csv_island
With LogToFile:
Quote:

L 10/08/2016 - 11:44:13: [map_history_log.smx] csv_island
Quote:

Originally Posted by stickz (Post 2460268)
Server console returned unknown command for con_logfile maphistory.txt

RLY?
It's CVar, not command.

stickz 10-08-2016 17:55

Re: Text File Handling
 
LogToFileEx isn't a good solution because I need to read each map name, then add it to an ADT Array. It adds tons of date/time junk to the file, that will need to be parsed through. There's got to be a better way to do this, that writes ONLY the map name and nothing else to a text file.

I was looking into JSON strings awhile back, but there are no good wrappers or documentation to work with these; that are easy to understand and implement.

Impact123 10-08-2016 18:27

Re: Text File Handling
 
Make sure that the line(s) you read or write don't have any unnecessary new line characters by using TrimString on them. This will fix your "spacer" problem and you can use a single file. GetMapHistory might be useful too.

stickz 10-09-2016 22:45

Re: Text File Handling
 
Quote:

Originally Posted by Impact123 (Post 2460418)
Make sure that the line(s) you read or write don't have any unnecessary new line characters by using TrimString on them. This will fix your "spacer" problem and you can use a single file.

Thanks! I was forgetting to trim the string before adding it to the text file.

My final working code:
PHP Code:

#define MAP_STORE_COUNT    30
#define MAP_SIZE 32

ArrayList g_PreviousMapList;

#define TEXT_FILE_PATH "data/lastmaps.txt"

public void OnPluginStart()
{
    
/* Create the previous map array list */
    
g_PreviousMapList = new ArrayList(MAP_STORE_COUNT);
}

void CreateTextFile()
{
    
/* Build a path to the text file */
    
char path[PLATFORM_MAX_PATH];
    
BuildPath(Path_SMpathPLATFORM_MAX_PATHTEXT_FILE_PATH);
        
    
/* Check if the file does not already exist */
    
if (!FileExists(path))
    {
        
/* Create the non-existent file */            
        
File file OpenFile(path"w");
        
file.Close()   
    }
}

void ReadTextFile()
{
    
/* Clear the last map exclude array */
    
g_PreviousMapList.Clear();
        
    
/* Build the file path to the previous maps */        
    
char path[PLATFORM_MAX_PATH];
    
BuildPath(Path_SMpathPLATFORM_MAX_PATHTEXT_FILE_PATH);
        
    
/* Open file to with the read letter */
    
File file OpenFile(path"r");
    
    
/* Buffer to store file content */
    
char map[MAP_SIZE];
    
    while (!
file.EndOfFile() && file.ReadLine(mapMAP_SIZE))
    {
        
/* Push the map string into previous map list */
         
g_PreviousMapList.PushString(map);
    }
    
    
/* Close the handle to the file we just opened */
    
file.Close();
}

void WriteTextFile()
{    
    
/* Build the file path based on the array index */        
    
char path[PLATFORM_MAX_PATH];
    
BuildPath(Path_SMpathPLATFORM_MAX_PATHTEXT_FILE_PATH);
        
    
/* Delete the file */
    
DeleteFile(path);
        
    
/* Create a new file with the same name for writing */
    
File file OpenFile(path"w");
    
    
/* Buffer to store the last map in */
    
char lastMap[MAP_SIZE];
    
    for (
int idx 0idx g_PreviousMapList.Lengthidx++)
    {
        
/* Get the previous map string */
        
g_PreviousMapList.GetString(idxlastMapMAP_SIZE);
        
        
/* Trim the previous map string (to remove whitespaces) */
        
TrimString(lastMap);
        
        
/* Write the previous map string to text file */
        
file.WriteLine(lastMap);
    }

    
/* Close the handle to the file we just created */
    
file.Close();    



Impact123 10-10-2016 12:16

Re: Text File Handling
 
I would actually trim it before pushing it into the array and only push it when it's not empty by then.

ThatOneGuy 10-10-2016 21:04

Re: Text File Handling
 
In my opinion, this kind of plugin is best servers via a database, even if sqlite. You could store as many as you want, and change the number saved at any time via a cvar. This solution would also allow you to track the most played maps, etc. There are quite a few plugins that do this already...perhaps if you are running one of those, you could instead have your plugin query that database.


All times are GMT -4. The time now is 23:42.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.