498 lines
17 KiB
Plaintext
498 lines
17 KiB
Plaintext
// Name : Avlis Persistence System include
|
|
// Purpose : Various APS/NWNX2 related functions
|
|
// Authors : Ingmar Stieger, Adam Colon, Josh Simon
|
|
// Modified : December 21, 2003
|
|
|
|
// This file is licensed under the terms of the
|
|
// GNU GENERAL PUBLIC LICENSE (GPL) Version 2
|
|
/************************************/
|
|
/* Includes */
|
|
/************************************/
|
|
#include "nwnx_object"
|
|
|
|
/************************************/
|
|
/* Return codes */
|
|
/************************************/
|
|
|
|
//void main (){}
|
|
|
|
int SQL_ERROR = 0;
|
|
int SQL_SUCCESS = 1;
|
|
|
|
/************************************/
|
|
/* Function prototypes */
|
|
/************************************/
|
|
sqlquery last_sql_query;
|
|
|
|
// Setup placeholders for ODBC requests and responses
|
|
void SQLInit();
|
|
|
|
// Execute statement in sSQL
|
|
void SQLExecDirect(string sSQL);
|
|
|
|
// Position cursor on next row of the resultset
|
|
// Call this before using SQLGetData().
|
|
// returns: SQL_SUCCESS if there is a row
|
|
// SQL_ERROR if there are no more rows
|
|
int SQLFetch();
|
|
|
|
// * deprecated. Use SQLFetch instead.
|
|
// Position cursor on first row of the resultset and name it sResultSetName
|
|
// Call this before using SQLNextRow() and SQLGetData().
|
|
// returns: SQL_SUCCESS if result set is not empty
|
|
// SQL_ERROR is result set is empty
|
|
int SQLFirstRow();
|
|
|
|
// * deprecated. Use SQLFetch instead.
|
|
// Position cursor on next row of the result set sResultSetName
|
|
// returns: SQL_SUCCESS if cursor could be advanced to next row
|
|
// SQL_ERROR if there was no next row
|
|
int SQLNextRow();
|
|
|
|
// Return value of column iCol in the current row of result set sResultSetName
|
|
string SQLGetData(int iCol);
|
|
|
|
// Return a string value when given a location
|
|
string APSLocationToString(location lLocation);
|
|
|
|
// Return a location value when given the string form of the location
|
|
location APSStringToLocation(string sLocation);
|
|
|
|
// Return a string value when given a vector
|
|
string APSVectorToString(vector vVector);
|
|
|
|
// Return a vector value when given the string form of the vector
|
|
vector APSStringToVector(string sVector);
|
|
|
|
// Set oObject's persistent string variable sVarName to sValue
|
|
// Optional parameters:
|
|
// iExpiration: Number of days the persistent variable should be kept in database (default: 0=forever)
|
|
// sTable: Name of the table where variable should be stored (default: pwdata)
|
|
void SetPersistentString(object oObject, string sVarName, string sValue, int iExpiration = 0, string sTable = "pwdata");
|
|
|
|
// Set oObject's persistent integer variable sVarName to iValue
|
|
// Optional parameters:
|
|
// iExpiration: Number of days the persistent variable should be kept in database (default: 0=forever)
|
|
// sTable: Name of the table where variable should be stored (default: pwdata)
|
|
void SetPersistentInt(object oObject, string sVarName, int iValue, int iExpiration = 0, string sTable = "pwdata");
|
|
|
|
// Set oObject's persistent float variable sVarName to fValue
|
|
// Optional parameters:
|
|
// iExpiration: Number of days the persistent variable should be kept in database (default: 0=forever)
|
|
// sTable: Name of the table where variable should be stored (default: pwdata)
|
|
void SetPersistentFloat(object oObject, string sVarName, float fValue, int iExpiration = 0, string sTable = "pwdata");
|
|
|
|
// Set oObject's persistent location variable sVarName to lLocation
|
|
// Optional parameters:
|
|
// iExpiration: Number of days the persistent variable should be kept in database (default: 0=forever)
|
|
// sTable: Name of the table where variable should be stored (default: pwdata)
|
|
// This function converts location to a string for storage in the database.
|
|
void SetPersistentLocation(object oObject, string sVarName, location lLocation, int iExpiration = 0, string sTable = "pwdata");
|
|
|
|
// Set oObject's persistent vector variable sVarName to vVector
|
|
// Optional parameters:
|
|
// iExpiration: Number of days the persistent variable should be kept in database (default: 0=forever)
|
|
// sTable: Name of the table where variable should be stored (default: pwdata)
|
|
// This function converts vector to a string for storage in the database.
|
|
void SetPersistentVector(object oObject, string sVarName, vector vVector, int iExpiration = 0, string sTable = "pwdata");
|
|
|
|
// Get oObject's persistent string variable sVarName
|
|
// Optional parameters:
|
|
// sTable: Name of the table where variable is stored (default: pwdata)
|
|
// * Return value on error: ""
|
|
string GetPersistentString(object oObject, string sVarName, string sTable = "pwdata");
|
|
|
|
// Get oObject's persistent integer variable sVarName
|
|
// Optional parameters:
|
|
// sTable: Name of the table where variable is stored (default: pwdata)
|
|
// * Return value on error: 0
|
|
int GetPersistentInt(object oObject, string sVarName, string sTable = "pwdata");
|
|
|
|
// Get oObject's persistent float variable sVarName
|
|
// Optional parameters:
|
|
// sTable: Name of the table where variable is stored (default: pwdata)
|
|
// * Return value on error: 0
|
|
float GetPersistentFloat(object oObject, string sVarName, string sTable = "pwdata");
|
|
|
|
// Get oObject's persistent location variable sVarName
|
|
// Optional parameters:
|
|
// sTable: Name of the table where variable is stored (default: pwdata)
|
|
// * Return value on error: 0
|
|
location GetPersistentLocation(object oObject, string sVarname, string sTable = "pwdata");
|
|
|
|
// Get oObject's persistent vector variable sVarName
|
|
// Optional parameters:
|
|
// sTable: Name of the table where variable is stored (default: pwdata)
|
|
// * Return value on error: 0
|
|
vector GetPersistentVector(object oObject, string sVarName, string sTable = "pwdata");
|
|
|
|
// Delete persistent variable sVarName stored on oObject
|
|
// Optional parameters:
|
|
// sTable: Name of the table where variable is stored (default: pwdata)
|
|
void DeletePersistentVariable(object oObject, string sVarName, string sTable = "pwdata");
|
|
|
|
// (private function) Replace special character ' with ~
|
|
string SQLEncodeSpecialChars(string sString);
|
|
|
|
// (private function)Replace special character ' with ~
|
|
string SQLDecodeSpecialChars(string sString);
|
|
|
|
// Get oObject's persistent vector variable sVarName
|
|
// Optional parameters:
|
|
// sTable: Name of the table where variable is stored (default: pwdata)
|
|
// * Return value on error: 0
|
|
vector GetPersistentVector(object oObject, string sVarName, string sTable = "pwdata");
|
|
|
|
// Get oObject's persistent object variable sVarName
|
|
// Optional parameters:
|
|
// sTable: Name of the table where variable is stored (default: pwdata)
|
|
// * Return value on error: 0
|
|
object GetPersistentObject(object oObject, string sVarName, string sTable = "pwdata");
|
|
|
|
|
|
/************************************/
|
|
/* Implementation */
|
|
/************************************/
|
|
|
|
// Functions for initializing APS and working with result sets
|
|
|
|
void SQLInit()
|
|
{
|
|
SQLExecDirect("CREATE TABLE IF NOT EXISTS pwdata(player varchar(64), tag varchar(64), name varchar(64), val text, expire int(11), last timestamp NOT NULL DEFAULT DEFAULT_TIMESTAMP, PRIMARY KEY (player,tag,name))");
|
|
}
|
|
|
|
void SQLExecDirect(string sSQL)
|
|
{
|
|
sqlquery sql = SqlPrepareQueryCampaign("db",sSQL);
|
|
last_sql_query = sql;
|
|
if(GetStringLowerCase(GetStringLeft(sSQL,6)) != "select")
|
|
{
|
|
SqlStep(sql);
|
|
}
|
|
}
|
|
|
|
int SQLFetch()
|
|
{
|
|
return SqlStep(last_sql_query);
|
|
}
|
|
|
|
// deprecated. use SQLFetch().
|
|
int SQLFirstRow()
|
|
{
|
|
return SQLFetch();
|
|
}
|
|
|
|
// deprecated. use SQLFetch().
|
|
int SQLNextRow()
|
|
{
|
|
return SQLFetch();
|
|
}
|
|
|
|
string SQLGetData(int iCol)
|
|
{
|
|
return SqlGetString(last_sql_query,iCol-1);
|
|
}
|
|
|
|
// These functions deal with various data types. Ultimately, all information
|
|
// must be stored in the database as strings, and converted back to the proper
|
|
// form when retrieved.
|
|
|
|
string APSVectorToString(vector vVector)
|
|
{
|
|
return "#POSITION_X#" + FloatToString(vVector.x) + "#POSITION_Y#" + FloatToString(vVector.y) +
|
|
"#POSITION_Z#" + FloatToString(vVector.z) + "#END#";
|
|
}
|
|
|
|
vector APSStringToVector(string sVector)
|
|
{
|
|
float fX, fY, fZ;
|
|
int iPos, iCount;
|
|
int iLen = GetStringLength(sVector);
|
|
|
|
if (iLen > 0)
|
|
{
|
|
iPos = FindSubString(sVector, "#POSITION_X#") + 12;
|
|
iCount = FindSubString(GetSubString(sVector, iPos, iLen - iPos), "#");
|
|
fX = StringToFloat(GetSubString(sVector, iPos, iCount));
|
|
|
|
iPos = FindSubString(sVector, "#POSITION_Y#") + 12;
|
|
iCount = FindSubString(GetSubString(sVector, iPos, iLen - iPos), "#");
|
|
fY = StringToFloat(GetSubString(sVector, iPos, iCount));
|
|
|
|
iPos = FindSubString(sVector, "#POSITION_Z#") + 12;
|
|
iCount = FindSubString(GetSubString(sVector, iPos, iLen - iPos), "#");
|
|
fZ = StringToFloat(GetSubString(sVector, iPos, iCount));
|
|
}
|
|
|
|
return Vector(fX, fY, fZ);
|
|
}
|
|
|
|
string APSLocationToString(location lLocation)
|
|
{
|
|
object oArea = GetAreaFromLocation(lLocation);
|
|
vector vPosition = GetPositionFromLocation(lLocation);
|
|
float fOrientation = GetFacingFromLocation(lLocation);
|
|
string sReturnValue;
|
|
|
|
if (GetIsObjectValid(oArea))
|
|
sReturnValue =
|
|
"#AREA#" + GetTag(oArea) + "#POSITION_X#" + FloatToString(vPosition.x) +
|
|
"#POSITION_Y#" + FloatToString(vPosition.y) + "#POSITION_Z#" +
|
|
FloatToString(vPosition.z) + "#ORIENTATION#" + FloatToString(fOrientation) + "#END#";
|
|
|
|
return sReturnValue;
|
|
}
|
|
|
|
location APSStringToLocation(string sLocation)
|
|
{
|
|
location lReturnValue;
|
|
object oArea;
|
|
vector vPosition;
|
|
float fOrientation, fX, fY, fZ;
|
|
|
|
int iPos, iCount;
|
|
int iLen = GetStringLength(sLocation);
|
|
|
|
if (iLen > 0)
|
|
{
|
|
iPos = FindSubString(sLocation, "#AREA#") + 6;
|
|
iCount = FindSubString(GetSubString(sLocation, iPos, iLen - iPos), "#");
|
|
oArea = GetObjectByTag(GetSubString(sLocation, iPos, iCount));
|
|
|
|
iPos = FindSubString(sLocation, "#POSITION_X#") + 12;
|
|
iCount = FindSubString(GetSubString(sLocation, iPos, iLen - iPos), "#");
|
|
fX = StringToFloat(GetSubString(sLocation, iPos, iCount));
|
|
|
|
iPos = FindSubString(sLocation, "#POSITION_Y#") + 12;
|
|
iCount = FindSubString(GetSubString(sLocation, iPos, iLen - iPos), "#");
|
|
fY = StringToFloat(GetSubString(sLocation, iPos, iCount));
|
|
|
|
iPos = FindSubString(sLocation, "#POSITION_Z#") + 12;
|
|
iCount = FindSubString(GetSubString(sLocation, iPos, iLen - iPos), "#");
|
|
fZ = StringToFloat(GetSubString(sLocation, iPos, iCount));
|
|
|
|
vPosition = Vector(fX, fY, fZ);
|
|
|
|
iPos = FindSubString(sLocation, "#ORIENTATION#") + 13;
|
|
iCount = FindSubString(GetSubString(sLocation, iPos, iLen - iPos), "#");
|
|
fOrientation = StringToFloat(GetSubString(sLocation, iPos, iCount));
|
|
|
|
lReturnValue = Location(oArea, vPosition, fOrientation);
|
|
}
|
|
|
|
return lReturnValue;
|
|
}
|
|
|
|
// These functions are responsible for transporting the various data types back
|
|
// and forth to the database.
|
|
|
|
void SetPersistentString(object oObject, string sVarName, string sValue, int iExpiration =
|
|
0, string sTable = "pwdata")
|
|
{
|
|
string sPlayer;
|
|
string sTag;
|
|
|
|
if (GetIsPC(oObject))
|
|
{
|
|
sPlayer = SQLEncodeSpecialChars(GetPCPlayerName(oObject));
|
|
sTag = SQLEncodeSpecialChars(GetName(oObject));
|
|
}
|
|
else
|
|
{
|
|
sPlayer = "~";
|
|
sTag = GetTag(oObject);
|
|
}
|
|
|
|
sVarName = SQLEncodeSpecialChars(sVarName);
|
|
sValue = SQLEncodeSpecialChars(sValue);
|
|
|
|
string sSQL = "SELECT player FROM " + sTable + " WHERE player='" + sPlayer +
|
|
"' AND tag='" + sTag + "' AND name='" + sVarName + "'";
|
|
SQLExecDirect(sSQL);
|
|
|
|
if (SQLFirstRow() == SQL_SUCCESS)
|
|
{
|
|
// row exists
|
|
sSQL = "UPDATE " + sTable + " SET val='" + sValue +
|
|
"',expire=" + IntToString(iExpiration) + " WHERE player='" + sPlayer +
|
|
"' AND tag='" + sTag + "' AND name='" + sVarName + "'";
|
|
SQLExecDirect(sSQL);
|
|
}
|
|
else
|
|
{
|
|
// row doesn't exist
|
|
sSQL = "INSERT INTO " + sTable + " (player,tag,name,val,expire) VALUES" +
|
|
"('" + sPlayer + "','" + sTag + "','" + sVarName + "','" +
|
|
sValue + "'," + IntToString(iExpiration) + ")";
|
|
SQLExecDirect(sSQL);
|
|
}
|
|
}
|
|
|
|
string GetPersistentString(object oObject, string sVarName, string sTable = "pwdata")
|
|
{
|
|
string sPlayer;
|
|
string sTag;
|
|
|
|
if (GetIsPC(oObject))
|
|
{
|
|
sPlayer = SQLEncodeSpecialChars(GetPCPlayerName(oObject));
|
|
sTag = SQLEncodeSpecialChars(GetName(oObject));
|
|
}
|
|
else
|
|
{
|
|
sPlayer = "~";
|
|
sTag = GetTag(oObject);
|
|
}
|
|
|
|
sVarName = SQLEncodeSpecialChars(sVarName);
|
|
|
|
string sSQL = "SELECT val FROM " + sTable + " WHERE player='" + sPlayer +
|
|
"' AND tag='" + sTag + "' AND name='" + sVarName + "'";
|
|
SQLExecDirect(sSQL);
|
|
|
|
if (SQLFirstRow() == SQL_SUCCESS)
|
|
return SQLDecodeSpecialChars(SQLGetData(1));
|
|
else
|
|
{
|
|
return "";
|
|
// If you want to convert your existing persistent data to APS, this
|
|
// would be the place to do it. The requested variable was not found
|
|
// in the database, you should
|
|
// 1) query it's value using your existing persistence functions
|
|
// 2) save the value to the database using SetPersistentString()
|
|
// 3) return the string value here.
|
|
}
|
|
}
|
|
|
|
void SetPersistentInt(object oObject, string sVarName, int iValue, int iExpiration =
|
|
0, string sTable = "pwdata")
|
|
{
|
|
SetPersistentString(oObject, sVarName, IntToString(iValue), iExpiration, sTable);
|
|
}
|
|
|
|
int GetPersistentInt(object oObject, string sVarName, string sTable = "pwdata")
|
|
{
|
|
return StringToInt(GetPersistentString(oObject, sVarName, sTable));
|
|
}
|
|
|
|
void SetPersistentFloat(object oObject, string sVarName, float fValue, int iExpiration =
|
|
0, string sTable = "pwdata")
|
|
{
|
|
SetPersistentString(oObject, sVarName, FloatToString(fValue), iExpiration, sTable);
|
|
}
|
|
|
|
float GetPersistentFloat(object oObject, string sVarName, string sTable = "pwdata")
|
|
{
|
|
return StringToFloat(GetPersistentString(oObject, sVarName, sTable));
|
|
}
|
|
|
|
void SetPersistentLocation(object oObject, string sVarName, location lLocation, int iExpiration =
|
|
0, string sTable = "pwdata")
|
|
{
|
|
SetPersistentString(oObject, sVarName, APSLocationToString(lLocation), iExpiration, sTable);
|
|
}
|
|
|
|
location GetPersistentLocation(object oObject, string sVarName, string sTable = "pwdata")
|
|
{
|
|
return APSStringToLocation(GetPersistentString(oObject, sVarName, sTable));
|
|
}
|
|
|
|
void SetPersistentVector(object oObject, string sVarName, vector vVector, int iExpiration =
|
|
0, string sTable = "pwdata")
|
|
{
|
|
SetPersistentString(oObject, sVarName, APSVectorToString(vVector), iExpiration, sTable);
|
|
}
|
|
|
|
vector GetPersistentVector(object oObject, string sVarName, string sTable = "pwdata")
|
|
{
|
|
return APSStringToVector(GetPersistentString(oObject, sVarName, sTable));
|
|
}
|
|
|
|
void DeletePersistentVariable(object oObject, string sVarName, string sTable = "pwdata")
|
|
{
|
|
string sPlayer;
|
|
string sTag;
|
|
|
|
if (GetIsPC(oObject))
|
|
{
|
|
sPlayer = SQLEncodeSpecialChars(GetPCPlayerName(oObject));
|
|
sTag = SQLEncodeSpecialChars(GetName(oObject));
|
|
}
|
|
else
|
|
{
|
|
sPlayer = "~";
|
|
sTag = GetTag(oObject);
|
|
}
|
|
|
|
sVarName = SQLEncodeSpecialChars(sVarName);
|
|
string sSQL = "DELETE FROM " + sTable + " WHERE player='" + sPlayer +
|
|
"' AND tag='" + sTag + "' AND name='" + sVarName + "'";
|
|
SQLExecDirect(sSQL);
|
|
}
|
|
|
|
// Problems can arise with SQL commands if variables or values have single quotes
|
|
// in their names. These functions are a replace these quote with the tilde character
|
|
|
|
string SQLEncodeSpecialChars(string sString)
|
|
{
|
|
if (FindSubString(sString, "'") == -1) // not found
|
|
return sString;
|
|
|
|
int i;
|
|
string sReturn = "";
|
|
string sChar;
|
|
|
|
// Loop over every character and replace special characters
|
|
for (i = 0; i < GetStringLength(sString); i++)
|
|
{
|
|
sChar = GetSubString(sString, i, 1);
|
|
if (sChar == "'")
|
|
sReturn += "~";
|
|
else
|
|
sReturn += sChar;
|
|
}
|
|
return sReturn;
|
|
}
|
|
|
|
string SQLDecodeSpecialChars(string sString)
|
|
{
|
|
if (FindSubString(sString, "~") == -1) // not found
|
|
return sString;
|
|
|
|
int i;
|
|
string sReturn = "";
|
|
string sChar;
|
|
|
|
// Loop over every character and replace special characters
|
|
for (i = 0; i < GetStringLength(sString); i++)
|
|
{
|
|
sChar = GetSubString(sString, i, 1);
|
|
if (sChar == "~")
|
|
sReturn += "'";
|
|
else
|
|
sReturn += sChar;
|
|
}
|
|
return sReturn;
|
|
}
|
|
|
|
string APSObjectToString(object oObject)
|
|
{
|
|
return NWNX_Object_Serialize(oObject);
|
|
}
|
|
|
|
object APSStringToObject(string sObject)
|
|
{
|
|
return NWNX_Object_Deserialize(sObject);
|
|
}
|
|
|
|
void SetPersistentObject(object oObject, string sVarName, object oObjectT, int iExpiration =
|
|
0, string sTable = "pwdata")
|
|
{
|
|
SetPersistentString(oObject, sVarName, APSObjectToString(oObjectT), iExpiration, sTable);
|
|
}
|
|
|
|
object GetPersistentObject(object oObject, string sVarName, string sTable = "pwdata")
|
|
{
|
|
return APSStringToObject(GetPersistentString(oObject, sVarName, sTable));
|
|
}
|