Raised This Month: $32 Target: $400
 8% 

[INC] Copycfg


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Bittersweet
Veteran Member
Join Date: May 2012
Old 01-09-2014 , 19:28   [INC] Copycfg
Reply With Quote #1

This include is meant to be used by plugin developers, both as a companion to the updater plugin, and as a replacement for AutoExecConfig.
The name doesn't really tell all it can do. It can back up existing .cfg files, and create cvars that load into memory and get dumped to a .cfg in the same operation. There's also an operation built in to allow server restarts at map end, should your plugin have changed radically between versions.

Revisions
2014.01.12.001 - Changed incorrect boolean bounds compliance FROM: "if (!cvar && cvar!= 1) cvar = 1" TO: "if (cvar > 1) cvar = 1"
2014.01.12.002 - Added support to opcode 0 to ignore existing .cfg files with the current version.

Bad news:
  • Slow and expensive file operations
  • User comments not supported (though they can be saved in a backup and manually edited in by the user - see Good News below)

Good news:
  • No limitation on number of, or location(s) of your .cfg file(s)
  • Ability to create backup .cfg files for each version
  • Unused cvars removed from the .cfg file
  • New cvars added to the .cfg file
  • Existing cvars keep their current values*
  • *If an existing cvar's value falls outside of any defined bounds, it is adjusted up or down to comply with the bounds
  • Friendly to the developer and the user - server restarts can be requested by developer but disabled by the user
  • Easily tailored to the developer's needs

copycfg.inc:
PHP Code:
#if defined _copycfg_included
        #endinput
#endif
#define _copycfg_included

//Revisions
//2014.01.12.001 - Changed incorrect boolean bounds compliance FROM: "if (!cvar && cvar!= 1) cvar = 1" TO: "if (cvar > 1) cvar = 1"
//2014.01.12.002 - Added support to opcode 0 to ignore existing .cfg files with the current version.

/**
 * Carries out copycfg operations according to the opcode. 
 * opcode 0 backs up and creates the .cfg file
 * opcode 1 creates a convar and writes it to the .cfg file
 * opcode 2 creates a repeating warning message, and sets the cvar copycfg_restartmap to true.  Your plugin can read this cvar to decide if restart is required
 *
 * @param    opcode                Defines the operation to carry out.  0=backup & create .cfg file 1=CreateConVar 2=set up server restart at end of map
 * @param    pathtocfgfile        path to the plugin's .cfg file relative to the game folder.  Example:  "/cfg/sourcemod/example.cfg"
 *                                If opcode is 2, send the value to use as a repeating warning timer as a string.  Example "120.0" = 120 seconds.  The default is 10.0
 * @param    convartype            The type of the ConVar 0|1|2|3.  0=boolean, 1=integer, 2=float, 3=string.
 * @param    name                name of the ConVar.
 * @param    defaultValue        Default value of the ConVar.  This does not need to match whatever is in memory.  This is how your redefine the default value
 * @param    description            Description for the ConVar.  This does not need to match whatever is in memory.  This is how your redefine the description
 * @param    flags                Optional bitstring of flags determining how the convar should be handled. See FCVAR_* constants for more details.
 * @param    hasMin                Boolean that defines if the ConVar has a lower bounds.  This does not need to match whatever is in memory.  This is how the redefine the minimum value
 * @param    min                    Float that defines the lower bounds of the ConVar.  This does not need to match whatever is in memory.  This is how the redefine the minimum value
 * @param    hasMax                Boolean that defines if the ConVar has an upper bounds.  This does not need to match whatever is in memory.  This is how the redefine the maximum value
 * @param    max                    Float that defines the upper bounds of the ConVar.  This does not need to match whatever is in memory.  This is how the redefine the maximum value
 * @return                        opcode 0: INVALID_HANDLE on failure.  The calling plugin's handle on success
 * @return                        opcode 1: INVALID_HANDLE on failure.  The cvar's handle on success
 * @return                        opcode 2: The calling plugin's handle if server restart not allowed by user.  INVALID_HANDLE if a server restart is scheduled at the end of the map
 */
stock Handle:Copycfg(const opcode=0, const String:pathtocfgfile[]="", const convartype=0, const String:name[]="", const String:defaultValue[]="", const String:description[]=""flags=0bool:hasMin=falseFloat:min=0.0bool:hasMax=falseFloat:max=0.0)
{
    new 
String:execpath[PLATFORM_MAX_PATH] = ""
    
new String:backupfilename[PLATFORM_MAX_PATH] = ""
    
new String:line[256] = ""
    
new String:search[256] = ""
    
new String:previousversion[64] = ""
    
new String:pluginname[128] = ""
    
new String:pluginversion[64] = ""
    
GetPluginInfo(INVALID_HANDLEPlInfo_Namepluginnamesizeof(pluginname))
    
GetPluginInfo(INVALID_HANDLEPlInfo_Versionpluginversionsizeof(pluginversion))
    new 
Handle:f_file INVALID_HANDLE
    
new Handle:c_cvar INVALID_HANDLE
    CreateConVar
("copycfg_allow_restart""1" "user end cvar to allow/block server restarts at the end of the map")    
    
CreateConVar("copycfg_restart_scheduled""0" "cvar used to communicate a server restart"FCVAR_DONTRECORD|FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY)    
    
//Create copycfg.cfg if it does not exist. We can't use AutoExecConfig or we'll get other cvars in the file
    
if (!FileExists("/cfg/sourcemod/copycfg.cfg"))
    {
        
//Create a copycfg.cfg file
        
f_file OpenFile("/cfg/sourcemod/copycfg.cfg""w")
        if (
f_file != INVALID_HANDLE)
        {
            
Format(linesizeof(line), "// This file was auto-generated by Copycfg")
            
WriteFileLine(f_fileline)
            
Format(linesizeof(line), "// ConVars used by copycfg.inc")
            
WriteFileLine(f_fileline)
            
//Write 2 blank lines to keep compatible with existing format
            
line "\r\n"
            
WriteFileLine(f_fileline)
            
WriteFileLine(f_fileline)
            
Format(linesizeof(line), "// user end cvar to allow/block server restarts at the end of the map")
            
WriteFileLine(f_fileline)
            
Format(linesizeof(line), "// -")
            
WriteFileLine(f_fileline)
            
Format(linesizeof(line), "// Default: %s%s%s"'"'"1"'"')
            
WriteFileLine(f_fileline)
            
Format(linesizeof(line), "copycfg_allow_restart %s%s%s"'"'"1"'"')
            
WriteFileLine(f_fileline)
            
//Write 1 blank line to keep compatible with existing format
            
line "\r\n"
            
WriteFileLine(f_fileline)
            
CloseHandle(f_file)
        }
        else
        {
            
PrintToServer("[%s %s] - Error creating /cfg/sourcemod/copycfg.cfg"pluginnamepluginversion)
        }
    }
    
//Execute copycfg.cfg
    
ServerCommand("exec /sourcemod/copycfg.cfg"
    new 
pos StrContains(pathtocfgfile"/cfg/"false)
    if (
pos == 0)
    {
        
Format(execpathsizeof(execpath), pathtocfgfile[5])
    }
    else
    {
        
Format(execpathsizeof(execpath), pathtocfgfile)
    }
    switch (
opcode)
    {
        case 
0:
        
//Back up & create .cfg file
        
{
            
//Check it the file exists.  If so execute it, if not create it
            
if (FileExists(pathtocfgfile))
            {
                
PrintToServer("[%s %s] - Executing existing cfg file %s"pluginnamepluginversionpathtocfgfile)
                
ServerCommand("exec %s"execpath)
                
//Open the file and get the version
                
f_file OpenFile(pathtocfgfile"r")
                if (
f_file == INVALID_HANDLE)
                {
                    
PrintToServer("[%s %s] - ERROR!  Could open file %s for reading"pluginnamepluginversionpathtocfgfile)
                    return 
INVALID_HANDLE
                
}
                
Format(searchsizeof(search), "// ConVars for plugin %s version "pluginname)
                while (!
IsEndOfFile(f_file))
                {
                    
ReadFileLine(f_filelinesizeof(line))
                    
TrimString(line)
                    if (
StrContains(linesearch) > -1)
                    
//This is the line containing the version
                    
{
                        
Format(previousversionsizeof(previousversion), line[strlen(search)])
                        break
                    }
                }
                
CloseHandle(f_file)
                
//If this .cfg version matches the current version, we don't need to do anything else
                
if (StrEqual(previousversionpluginversion))
                {
                    
PrintToServer("[%s %s] - %s is the current version"pluginnamepluginversionpathtocfgfile)
                    return 
GetMyHandle()
                }
                
//Send a message that the .cfg will be backed up
                
Format(backupfilenamesizeof(backupfilename), "%s.%s.bak"pathtocfgfilepreviousversion)
                
PrintToServer("[%s %s] - Copycfg is backing up %s"pluginnamepluginversionpathtocfgfile)
                
PrintToServer("to %s"backupfilename)
                
//If a backup already exists, delete it
                
if (FileExists(backupfilename)) DeleteFile(backupfilename)
                
// Now we want to rename the .cfg file to .cfg.version to back it up
                
if (RenameFile(backupfilenamepathtocfgfile))
                {
                    
PrintToServer("[%s %s] - Your previous configuration file %s was backed up"pluginnamepluginversionpathtocfgfile)
                    
PrintToServer("as %s"backupfilename)
                }
                else
                {
                    
PrintToServer("[%s %s] - ERROR!  Could not rename file %s to %s"pluginnamepluginversionpathtocfgfilebackupfilename)
                    return 
INVALID_HANDLE
                
}
            }
            
//Open the specified .cfg file
            
f_file OpenFile(pathtocfgfile"w")
            
//Make sure handle to file was created
            
if (f_file == INVALID_HANDLE)
            {
                
PrintToServer("[%s %s] - ERROR!  Could not create handle to the file %s"pluginnamepluginversionpathtocfgfile)
                return 
INVALID_HANDLE
            
}
            
//If the file has a size of -1, it does not exist, so an error has occurred creating it
            
if (FileSize(pathtocfgfile) == -1)
            {
                
PrintToServer("[%s %s] - ERROR!  Could not open the file %s for writing"pluginnamepluginversionpathtocfgfile)
                
CloseHandle(f_file)
                return 
INVALID_HANDLE
            
}
            else
            
//File was just created, write headers
            
{
                
Format(linesizeof(line), "// This file was auto-generated by Copycfg")
                
WriteFileLine(f_fileline)
                
Format(linesizeof(line), "// ConVars for plugin %s version %s"pluginnamepluginversion)
                
WriteFileLine(f_fileline)
                
//Write 2 blank lines to keep compatible with existing format
                
line "\r\n"
                
WriteFileLine(f_fileline)
                
WriteFileLine(f_fileline)
            }
            
CloseHandle(f_file)
            return 
GetMyHandle()
        }
        case 
1:
        
//Create ConVars
        
{
            
c_cvar CreateConVar(namedefaultValuedescriptionflagshasMinminhasMaxmax)
            if (
c_cvar == INVALID_HANDLE)
            {
                
PrintToServer("[%s %s] - ERROR!  Could not create or open handle to the cvar %s"pluginnamepluginversionname)
                return 
INVALID_HANDLE
            
}
            
//Open the specified .cfg file
            
f_file OpenFile(pathtocfgfile"a")
            if (
f_file == INVALID_HANDLE)
            {
                
PrintToServer("[%s %s] - ERROR!  Could not open the file %s"pluginnamepluginversionpathtocfgfile)
                return 
INVALID_HANDLE
            
}
            
//If the file has a size of -1, it does not exist, so an error has occurred creating it
            
if (FileSize(pathtocfgfile) == -1)
            {
                
PrintToServer("[%s %s] - ERROR!  Could not open the file %s"pluginnamepluginversionpathtocfgfile)
                return 
INVALID_HANDLE
            
}
            if    (
FileSize(pathtocfgfile) == 0)
            
//If the file has a size of 0, it was just created, don't use
            
{
                
PrintToServer("[%s %s] - ERROR!  The file %s does not have valid headers.  Use opcode 0 before calling opcode 1."pluginnamepluginversionpathtocfgfile)
                return 
INVALID_HANDLE
            
}
            
//Now write the ConVar
            
Format(linesizeof(line), "// %s"description)
            
WriteFileLine(f_fileline)
            
Format(linesizeof(line), "// -")
            
WriteFileLine(f_fileline)
            
Format(linesizeof(line), "// Default: %s%s%s"'"'defaultValue'"')
            
WriteFileLine(f_fileline)
            if (
hasMin)
            {
                
Format(linesizeof(line), "// Minimum: %s%f%s"'"'min'"')
                
WriteFileLine(f_fileline)
            }
            if (
hasMax)
            {
                
Format(linesizeof(line), "// Maximum: %s%f%s"'"'max'"')
                
WriteFileLine(f_fileline)
            }
            switch (
convartype)
            {
                case 
0:
                {
                    new 
cvar GetConVarInt(c_cvar)
                    if (
cvar 0cvar 0
                    
if (cvar 1cvar 1
                    Format
(linesizeof(line), "%s %s%i%s"name'"'cvar'"')
                }
                case 
1:
                {
                    new 
cvar GetConVarInt(c_cvar)
                    new 
Float:cvarfloat float(cvar)
                    if (
hasMin && cvarfloat min)cvar RoundFloat(min)
                    if (
hasMax && cvarfloat max)cvar RoundFloat(max)
                    
Format(linesizeof(line), "%s %s%i%s"name'"'cvar'"')
                }
                case 
2:
                {
                    new 
Float:cvar GetConVarFloat(c_cvar)
                    if (
hasMin && cvar min)cvar min
                    
if (hasMax && cvar max)cvar max
                    Format
(linesizeof(line), "%s %s%f%s"name'"'cvar'"')
                }
                case 
3:
                {
                    new 
String:cvar[256]
                    
GetConVarString(c_cvarcvarsizeof(cvar))
                    new 
Float:cvarfloat StringToFloat(cvar)
                    if (
hasMin && cvarfloat min)FloatToString(mincvarsizeof(cvar))
                    if (
hasMax && cvarfloat max)FloatToString(maxcvarsizeof(cvar))
                    
Format(linesizeof(line), "%s %s%s%s"name'"'cvar'"')
                }
            }
            
WriteFileLine(f_fileline)
            
//Write 1 blank line to keep compatible with existing format
            
line "\r\n"
            
WriteFileLine(f_fileline)
            
CloseHandle(f_file)
            return 
c_cvar
        
}
        case 
2:
        
//Set up server restart
        
{
            if (
GetConVarBool(FindConVar("copycfg_allow_restart")))
            {
                if (!
GetConVarBool(FindConVar("copycfg_restart_scheduled")))
                {
                    
SetConVarBool(FindConVar("copycfg_restart_scheduled"), true)
                    
PrintToServer("[%s %s] - Server will restart at the end of the map for updates."pluginnamepluginversion)
                    
PrintCenterTextAll("Server will restart at the end of the map for updates.")
                    new 
Float:freq StringToFloat(pathtocfgfile)
                    if (
freq <= 0.0freq 10.0 
                    CreateTimer
(freqCopycfgSendWarningMsg_TIMER_REPEAT)
                    return 
INVALID_HANDLE
                
}
                else
                {
                    
PrintToServer("[%s %s] - Server restart already scheduled"pluginnamepluginversion)
                    return 
INVALID_HANDLE
                
}
            }
            else
            {
                
PrintToServer("[%s %s] - Developer requested server restart disabled in copycfg.cfg"pluginnamepluginversion)
                return 
GetMyHandle()
            }
        }
    }
    
PrintToServer("[%s %s] - ERROR!  Copycfg opcode %i failed!  The opcode is not defined..."pluginnamepluginversionopcode)
    return 
INVALID_HANDLE
}
public 
Action:CopycfgSendWarningMsg(Handle:timer)
{
    new 
String:pluginname[128] = ""
    
new String:pluginversion[64] = ""
    
GetPluginInfo(INVALID_HANDLEPlInfo_Namepluginnamesizeof(pluginname))
    
GetPluginInfo(INVALID_HANDLEPlInfo_Versionpluginversionsizeof(pluginversion))
    
PrintToServer("[%s %s] - Server will restart at the end of the map for updates."pluginnamepluginversion)
    
PrintCenterTextAll("Server will restart at the end of the map for updates.")

Example plugins:
example1.sp:
PHP Code:
#include <sourcemod>
#include <updater>
#include <autoexecconfig>
#include <copycfg>

#define UPDATE_URL "http://your_url/updater/example.txt"

new const String:PLUGIN_NAME[]= "example"
new const String:PLUGIN_AUTHOR[]= "Bittersweet"
new const String:PLUGIN_DESCRIPTION[]= "An example/test plugin using copycfg concept.  To use Copycfg, you must include copycfg.inc and use Copycfg with the correct opcode to handle creating/loading .cfg files and cvars."
new const String:PLUGIN_VERSION[]= "1.0.0"

public Plugin:myinfo =
{
    
name PLUGIN_NAME,
    
author PLUGIN_AUTHOR,
    
description PLUGIN_DESCRIPTION,
    
version PLUGIN_VERSION,
    
url "http://www.sourcemod.net/"
}
public 
OnPluginStart()
{
    
PrintToServer("[%s %s] Loaded"PLUGIN_NAMEPLUGIN_VERSION)
    
CreateConVar("example_version"PLUGIN_VERSION"example plugin used for testing copycfg plugin"FCVAR_DONTRECORD|FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY)
    
//Always call copycfg with opcode 0 before calling any other opcodes, or you get no backup file for the previous version
    
Copycfg(0"/cfg/sourcemod/example.cfg")
    
Copycfg(1"/cfg/sourcemod/example.cfg"0"example_cvar1""0""Boolean test cvar.")
    
Copycfg(1"/cfg/sourcemod/example.cfg"1"example_cvar2""25""Integer test cvar."FCVAR_PLUGINtrue0.0true100.0)
    
Copycfg(1"/cfg/sourcemod/example.cfg"2"example_cvar3""2.0""Float test cvar."FCVAR_PLUGINtrue0.0true10.0)
    
//Copycfg(1, "/cfg/sourcemod/example.cfg", 3, "example_cvar4", "test", "String test cvar.", FCVAR_PLUGIN)
    
if (LibraryExists("updater"))
    {
        
Updater_AddPlugin(UPDATE_URL)
    }
}
public 
OnLibraryAdded(const String:name[])
{
    if (
StrEqual(name"updater"))
    {
        
Updater_AddPlugin(UPDATE_URL)
    }
}
public 
OnConfigsExecuted()
{
    
//Forcing an update would be optional
    
new UpdateTriggered Updater_ForceUpdate()
    if (
UpdateTriggered)
    {
        
PrintToServer("[%s %s] - Checking for update(s)..."PLUGIN_NAMEPLUGIN_VERSION)
    }
    else
    {
        
PrintToServer("[%s %s] - Updater DID NOT trigger an update..."PLUGIN_NAMEPLUGIN_VERSION)
    }
}
public 
Action:Updater_OnPluginChecking()
{
    
PrintToServer("[%s %s] - Contacting update server..."PLUGIN_NAMEPLUGIN_VERSION)
    return 
Plugin_Continue
}
public 
Action:Updater_OnPluginDownloading()
{
    
PrintToServer("[%s %s] - Downloading update(s)..."PLUGIN_NAMEPLUGIN_VERSION)
    return 
Plugin_Continue
}
public 
Updater_OnPluginUpdated()
{
    
//Only reload the plugin if: the user has blocked restarting the server, or a restart was already scheduled
    
if (Copycfg(2) == GetMyHandle()) ReloadPlugin(INVALID_HANDLE)
}
public 
OnMapStart()
{
    
PrintToServer("[%s %s] - Map start"PLUGIN_NAMEPLUGIN_VERSION)
    if (
GetConVarBool(FindConVar("copycfg_restart_scheduled")))
    {
        
PrintToServer("[%s %s] - Server should restart"PLUGIN_NAMEPLUGIN_VERSION)
        
ServerCommand("_restart")
    }
    else
    {
        
PrintToServer("[%s %s] - No restart scheduled"PLUGIN_NAMEPLUGIN_VERSION)
    }
}
//End of code 
example2.sp:
PHP Code:
#include <sourcemod>
#include <updater>
#include <autoexecconfig>
#include <copycfg>

#define UPDATE_URL "http://your_url/updater/example.txt"

new const String:PLUGIN_NAME[]= "example"
new const String:PLUGIN_AUTHOR[]= "Bittersweet"
new const String:PLUGIN_DESCRIPTION[]= "An example/test plugin using copycfg concept.  To use Copycfg, you must include copycfg.inc and use copycfg with the correct opcode to handle creating/loading .cfg files and cvars."
new const String:PLUGIN_VERSION[]= "2.0.0"

public Plugin:myinfo =
{
    
name PLUGIN_NAME,
    
author PLUGIN_AUTHOR,
    
description PLUGIN_DESCRIPTION,
    
version PLUGIN_VERSION,
    
url "http://www.sourcemod.net/"
}
public 
OnPluginStart()
{
    
PrintToServer("[%s %s] Loaded"PLUGIN_NAMEPLUGIN_VERSION)
    
CreateConVar("example_version"PLUGIN_VERSION"example plugin used for testing copycfg plugin"FCVAR_DONTRECORD|FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY)
    
//Always call copycfg with opcode 0 before calling any other opcodes, or you get no backup file for the previous version
    
Copycfg(0"/cfg/sourcemod/example.cfg")
    
//Copycfg(1, "/cfg/sourcemod/example.cfg", 0, "example_cvar1", "0", "Boolean test cvar.")
    
Copycfg(1"/cfg/sourcemod/example.cfg"1"example_cvar2""75""Integer test cvar."FCVAR_PLUGINtrue50.0true100.0)
    
Copycfg(1"/cfg/sourcemod/example.cfg"2"example_cvar3""7.0""Float test cvar."FCVAR_PLUGINtrue5.0true10.0)
    
Copycfg(1"/cfg/sourcemod/example.cfg"3"example_cvar4""test""String test cvar."FCVAR_PLUGIN)
    if (
LibraryExists("updater"))
    {
        
Updater_AddPlugin(UPDATE_URL)
    }
}
public 
OnLibraryAdded(const String:name[])
{
    if (
StrEqual(name"updater"))
    {
        
Updater_AddPlugin(UPDATE_URL)
    }
}
public 
OnConfigsExecuted()
{
    
//Forcing an update would be optional
    
new UpdateTriggered Updater_ForceUpdate()
    if (
UpdateTriggered)
    {
        
PrintToServer("[%s %s] - Checking for update(s)..."PLUGIN_NAMEPLUGIN_VERSION)
    }
    else
    {
        
PrintToServer("[%s %s] - Updater DID NOT trigger an update..."PLUGIN_NAMEPLUGIN_VERSION)
    }
}
public 
Action:Updater_OnPluginChecking()
{
    
PrintToServer("[%s %s] - Contacting update server..."PLUGIN_NAMEPLUGIN_VERSION)
    return 
Plugin_Continue
}
public 
Action:Updater_OnPluginDownloading()
{
    
PrintToServer("[%s %s] - Downloading update(s)..."PLUGIN_NAMEPLUGIN_VERSION)
    return 
Plugin_Continue
}
public 
Updater_OnPluginUpdated()
{
    
//Only reload the plugin if: the user has blocked restarting the server, or a restart was already scheduled
    
if (Copycfg(2) == GetMyHandle()) ReloadPlugin(INVALID_HANDLE)
}
public 
OnMapStart()
{
    
PrintToServer("[%s %s] - Map start"PLUGIN_NAMEPLUGIN_VERSION)
    if (
GetConVarBool(FindConVar("copycfg_restart_scheduled")))
    {
        
PrintToServer("[%s %s] - Server should restart"PLUGIN_NAMEPLUGIN_VERSION)
        
ServerCommand("_restart")
    }
    else
    {
        
PrintToServer("[%s %s] - No restart scheduled"PLUGIN_NAMEPLUGIN_VERSION)
    }
}
//End of code 
How to use examples:
1. Place the copycfg.inc file in your /sourcemod/scripting/include folder
2. Copy example1.sp and insert your UPDATE_URL in the define directive.
To prevent your server from restarting, remove Copycfg(2) from Updater_OnPluginUpdated().
You can change other things later after you see how it works.
Save it in your /addons/sourcemod/scripting folder.
3. Copy example2.sp and insert your UPDATE_URL in the define directive.
To prevent your server from restarting, remove Copycfg(2) from Updater_OnPluginUpdated().
You can change other things later after you see how it works.
Save it in your /addons/sourcemod/scripting folder.
4. Compile example1.sp, and rename it to example.smx (or whatever filename.smx)
5. Place the newly created .smx into your updater's plugin folder
6. Create the necessary example.txt file for updater with version 2 being the latest
7. Compile example2.sp, and rename it to example.smx (or whatever filename.smx)
8. Copy the newly created .smx to your plugin folder and load it
9. Load the plugin and watch your server console

If you don't change the filenames being passed to Copycfg, you should see the plugin updating,
and when all is said and done you should have example version 2.0.0 in your plugins folder and
loaded into memory. You should have a backup .cfg file named example.cfg.1.0.0.bak and a new
example.cfg with only the cvars defined in example2. Cvars that were defined in example1, but
not in example2, will still exist in memory until the server is restarted, but existing cvars will keep
user defined values unless they fall outside of defined bounds, in which case they are adjusted to
fall just within the lower or higher end of the bounds.

Details:
Copycfg works with opcodes. The opcode is always the 1st parameter.
The 2nd parameter is a full file path (except for opcode 2, see below), so you aren't constrained to any certain directory or just one .cfg file. See copycfg.inc for details on all of the parameters,
but briefly:

opcode 0 creates a back up .cfg with the current version.
The version is also noted inside the file. It also creates a new empty .cfg file as specified
in the 2nd parameter. As of revision 2014.01.12.002, no file writing operations are carried out if
the current .cfg file contains the current version header.

opcode 1 creates convars, both in memory and in the file passed in the 2nd parameter.
It also ensures any pre-existing cvars are set to user-defined values, unless they fall out of
bounds. This opcode will also create the file specified in the 2nd parameter if it doesn't exist,
but it will not back up the previous version as opcode 0 does, therefore using opcode 0 first
is recommended for each .cfg file
. With opcode 1, the 3rd parameter specifies the cvar type,
which allows for cvars to be set correctly without any guesswork. See copycfg.inc for details.

opcode 2 is used to schedule a server restart, if the user hasn't disabled them in
copycfg.cfg. The developer actually has to use code as shown in the examples in OnMapStart()
(it wouldn't work in OnMapEnd() on my CS:S server) to restart the server.
The opcode simply sets a cvar as a flag that a server restart has been requested.
In most cases, you probably won't even need to do this. With opcode 2, the second
parameter defines the frequency of warning messages sent to the server console, and to players
in-game that the server will restart at the end of the map.

Other notes:
AutoExecConfig is never used anywhere in Copycfg, and you shouldn't use it if using Copycfg.
If the file /cfg/sourcemod/copycfg.cfg doesn't exist, it is created by the include.
The default I have defined allows server restarts, but you can easily change that if you wish.
Running the example plugins I've provided without altering anything other than UPDATE_URL,
will result in a server restart at the end of the map!
Attached Files
File Type: sp Get Plugin or Get Source (example1.sp - 103 views - 3.0 KB)
File Type: sp Get Plugin or Get Source (example2.sp - 164 views - 3.0 KB)
File Type: inc copycfg.inc (13.0 KB, 99 views)
__________________
Thank you in advance for your help

My plugins:
[CS:S] BOT Swat | [ANY] CVAR Randomizer | [CS:S] SM CS:S Tag Beta | [CS:S] Bot2Player
Awesome & Crucial plugins by other people:
[CS:S/CS:GO] GunGame | [UMC3] Ultimate Mapchooser | [ANY] Server Crontab | [ANY] SM ForceCamera

Last edited by Bittersweet; 01-12-2014 at 10:12.
Bittersweet is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 17:01.


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