428 lines
7.5 KiB
C++
428 lines
7.5 KiB
C++
// vim: set ts=4 sw=4 tw=99 noet:
|
|
//
|
|
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
|
// Copyright (C) The AMX Mod X Development Team.
|
|
//
|
|
// This software is licensed under the GNU General Public License, version 3 or higher.
|
|
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
|
// https://alliedmods.net/amxmodx-license
|
|
|
|
#include <time.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include "sh_list.h"
|
|
#include "CString.h"
|
|
|
|
#include "amxmodx.h"
|
|
|
|
#include "CFlagManager.h"
|
|
|
|
void CFlagManager::SetFile(const char *Filename)
|
|
{
|
|
|
|
m_strConfigFile.assign(g_mod_name.c_str());
|
|
m_strConfigFile.append("/");
|
|
m_strConfigFile.append(get_localinfo("amxx_configsdir","addons/amxmodx/configs"));
|
|
m_strConfigFile.append("/");
|
|
m_strConfigFile.append(Filename);
|
|
|
|
|
|
CreateIfNotExist();
|
|
}
|
|
|
|
const int CFlagManager::LoadFile(const int force)
|
|
{
|
|
CheckIfDisabled();
|
|
// If we're disabled get the hell out. now.
|
|
if (m_iDisabled)
|
|
{
|
|
return 0;
|
|
}
|
|
// if we're not forcing this, and NeedToLoad says we dont have to
|
|
// then just stop
|
|
if (!force && !NeedToLoad())
|
|
{
|
|
return 0;
|
|
};
|
|
|
|
this->Clear();
|
|
|
|
|
|
// We need to load the file
|
|
|
|
FILE *File;
|
|
|
|
File=fopen(m_strConfigFile.c_str(),"r");
|
|
|
|
if (!File)
|
|
{
|
|
AMXXLOG_Log("[AMXX] FlagManager: Cannot open file \"%s\" (FILE pointer null!)",m_strConfigFile.c_str());
|
|
return -1;
|
|
};
|
|
|
|
// Trying to copy this almost exactly as other configs are read...
|
|
String Line;
|
|
|
|
char Command[256];
|
|
char Flags[256];
|
|
|
|
String TempLine;
|
|
while (!feof(File))
|
|
{
|
|
|
|
Line._fread(File);
|
|
|
|
char *nonconst=const_cast<char *>(Line.c_str());
|
|
|
|
|
|
// Strip out comments
|
|
while (*nonconst)
|
|
{
|
|
if (*nonconst==';') // End the line at comments
|
|
{
|
|
*nonconst='\0';
|
|
}
|
|
else
|
|
{
|
|
nonconst++;
|
|
}
|
|
};
|
|
|
|
Command[0]='\0';
|
|
Flags[0]='\0';
|
|
|
|
// Extract the command
|
|
TempLine.assign(Line.c_str());
|
|
|
|
nonconst=const_cast<char *>(TempLine.c_str());
|
|
|
|
char *start=NULL;
|
|
char *end=NULL;
|
|
|
|
// move up line until the first ", mark this down as the start
|
|
// then find the second " and mark it down as the end
|
|
while (*nonconst!='\0')
|
|
{
|
|
if (*nonconst=='"')
|
|
{
|
|
if (start==NULL)
|
|
{
|
|
start=nonconst+1;
|
|
}
|
|
else
|
|
{
|
|
end=nonconst;
|
|
goto done_with_command;
|
|
}
|
|
}
|
|
nonconst++;
|
|
}
|
|
done_with_command:
|
|
|
|
// invalid line?
|
|
if (start==NULL || end==NULL)
|
|
{
|
|
// TODO: maybe warn for an invalid non-commented line?
|
|
continue;
|
|
}
|
|
|
|
*end='\0';
|
|
|
|
strncpy(Command,start,sizeof(Command)-1);
|
|
|
|
|
|
// Now do the same thing for the flags
|
|
nonconst=++end;
|
|
|
|
start=NULL;
|
|
end=NULL;
|
|
|
|
// move up line until the first ", mark this down as the start
|
|
// then find the second " and mark it down as the end
|
|
while (*nonconst!='\0')
|
|
{
|
|
if (*nonconst=='"')
|
|
{
|
|
if (start==NULL)
|
|
{
|
|
start=nonconst+1;
|
|
}
|
|
else
|
|
{
|
|
end=nonconst;
|
|
goto done_with_flags;
|
|
}
|
|
}
|
|
nonconst++;
|
|
}
|
|
done_with_flags:
|
|
// invalid line?
|
|
if (start==NULL || end==NULL)
|
|
{
|
|
// TODO: maybe warn for an invalid non-commented line?
|
|
continue;
|
|
}
|
|
|
|
*end='\0';
|
|
|
|
strncpy(Flags,start,sizeof(Flags)-1);
|
|
|
|
|
|
|
|
//if (!isalnum(*Command))
|
|
if (*Command == '"' ||
|
|
*Command == '\0')
|
|
{
|
|
continue;
|
|
};
|
|
|
|
// Done sucking the command and flags out of the line
|
|
// now insert this command into the linked list
|
|
|
|
AddFromFile(const_cast<const char*>(&Command[0]),&Flags[0]);
|
|
|
|
nonconst=const_cast<char *>(Line.c_str());
|
|
*nonconst='\0';
|
|
};
|
|
|
|
|
|
fclose(File);
|
|
|
|
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* This gets called from LoadFile
|
|
* Do NOT flag the entries as NeedToWrite
|
|
* No comment is passed from the file because
|
|
* this should never get written
|
|
*/
|
|
void CFlagManager::AddFromFile(const char *Command, const char *Flags)
|
|
{
|
|
|
|
CFlagEntry *Entry=new CFlagEntry;
|
|
|
|
Entry->SetName(Command);
|
|
Entry->SetFlags(Flags);
|
|
|
|
// Link it
|
|
m_FlagList.push_back(Entry);
|
|
|
|
};
|
|
|
|
|
|
void CFlagManager::LookupOrAdd(const char *Command, int &Flags, AMX *Plugin)
|
|
{
|
|
if (m_iDisabled) // if disabled in core.ini stop
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
int TempFlags=Flags;
|
|
if (TempFlags==-1)
|
|
{
|
|
TempFlags=0;
|
|
}
|
|
|
|
List<CFlagEntry *>::iterator iter;
|
|
List<CFlagEntry *>::iterator end;
|
|
|
|
iter=m_FlagList.begin();
|
|
end=m_FlagList.end();
|
|
|
|
while (iter!=end)
|
|
{
|
|
if (strcmp((*iter)->GetName()->c_str(),Command)==0)
|
|
{
|
|
CFlagEntry *Entry=(*iter);
|
|
|
|
if (Entry->IsHidden()) // "!" flag, exclude this function
|
|
{
|
|
return;
|
|
}
|
|
// Found, byref the new flags
|
|
Flags=Entry->Flags();
|
|
|
|
// Move it to the back of the list for faster lookup for the rest
|
|
m_FlagList.erase(iter);
|
|
|
|
m_FlagList.push_back(Entry);
|
|
return;
|
|
}
|
|
iter++;
|
|
}
|
|
|
|
// was not found, add it
|
|
|
|
CFlagEntry *Entry=new CFlagEntry;
|
|
|
|
Entry->SetName(Command);
|
|
Entry->SetFlags(TempFlags);
|
|
|
|
if (Plugin)
|
|
{
|
|
CPluginMngr::CPlugin* a = g_plugins.findPluginFast(Plugin);
|
|
|
|
if (a)
|
|
{
|
|
Entry->SetComment(a->getName());
|
|
}
|
|
}
|
|
|
|
// This entry was added from a register_* native
|
|
// it needs to be written during map change
|
|
Entry->SetNeedWritten(1);
|
|
|
|
// Link it
|
|
m_FlagList.push_back(Entry);
|
|
|
|
}
|
|
void CFlagManager::WriteCommands(void)
|
|
{
|
|
List<CFlagEntry *>::iterator iter;
|
|
List<CFlagEntry *>::iterator end;
|
|
FILE *File;
|
|
int NeedToRead=0;
|
|
|
|
// First off check the modified time of this file
|
|
// if it matches the stored modified time, then update
|
|
// after we write so we do not re-read next map
|
|
struct stat TempStat;
|
|
|
|
stat(m_strConfigFile.c_str(),&TempStat);
|
|
|
|
|
|
|
|
if (TempStat.st_mtime != m_Stat.st_mtime)
|
|
{
|
|
NeedToRead=1;
|
|
};
|
|
|
|
|
|
File=fopen(m_strConfigFile.c_str(),"a");
|
|
|
|
if (!File)
|
|
{
|
|
return;
|
|
}
|
|
|
|
iter=m_FlagList.begin();
|
|
end=m_FlagList.end();
|
|
|
|
|
|
|
|
while (iter!=end)
|
|
{
|
|
if ((*iter)->NeedWritten())
|
|
{
|
|
if ((*iter)->GetComment()->size())
|
|
{
|
|
fprintf(File,"\"%s\" \t\"%s\" ; %s\n",(*iter)->GetName()->c_str(),(*iter)->GetFlags()->c_str(),(*iter)->GetComment()->c_str());
|
|
}
|
|
else
|
|
{
|
|
fprintf(File,"\"%s\" \t\"%s\"\n",(*iter)->GetName()->c_str(),(*iter)->GetFlags()->c_str());
|
|
}
|
|
(*iter)->SetNeedWritten(0);
|
|
}
|
|
++iter;
|
|
};
|
|
|
|
fclose(File);
|
|
|
|
|
|
// If NeedToRead was 0, then update the timestamp
|
|
// that was saved so we do not re-read this file
|
|
// next map
|
|
if (!NeedToRead)
|
|
{
|
|
stat(m_strConfigFile.c_str(),&TempStat);
|
|
|
|
m_Stat.st_mtime=TempStat.st_mtime;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int CFlagManager::ShouldIAddThisCommand(const AMX *amx, const cell *params, const char *cmdname) const
|
|
{
|
|
|
|
// If flagmanager is disabled then ignore this
|
|
if (m_iDisabled)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
// If 5th param exists it was compiled after this change was made
|
|
// if it does not exist, try our logic at the end of this function
|
|
// 5th param being > 0 means explicit yes
|
|
// < 0 means auto detect (default is -1), treat it like there was no 5th param
|
|
// 0 means explicit no
|
|
|
|
if ((params[0] / sizeof(cell)) >= 5)
|
|
{
|
|
if (params[5]>0) // This command was explicitly told to be included
|
|
{
|
|
return 1;
|
|
}
|
|
else if (params[5]==0) // this command was explicitly told to NOT be used
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// auto detect if we should use this command
|
|
|
|
// if command access is -1 (default, not set to ADMIN_ALL or any other access), then no
|
|
if (params[3]==-1)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
// if command is (or starts with) "say", then no
|
|
if (strncmp(cmdname,"say",3)==0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
// else use it
|
|
return 1;
|
|
};
|
|
|
|
|
|
void CFlagManager::Clear(void)
|
|
{
|
|
List<CFlagEntry *>::iterator iter;
|
|
List<CFlagEntry *>::iterator end;
|
|
|
|
iter=m_FlagList.begin();
|
|
end=m_FlagList.end();
|
|
|
|
while (iter!=end)
|
|
{
|
|
delete (*iter);
|
|
|
|
++iter;
|
|
}
|
|
|
|
m_FlagList.clear();
|
|
};
|
|
|
|
void CFlagManager::CheckIfDisabled(void)
|
|
{
|
|
if (atoi(get_localinfo("disableflagman","0"))==0)
|
|
{
|
|
m_iDisabled=0;
|
|
}
|
|
else
|
|
{
|
|
m_iDisabled=1;
|
|
}
|
|
};
|