voron00
23rd October 2017, 11:17
You may notice some updates in my git lately, so gonna explain some of them.
You can now choose between my and orignal MySQL variant:
1373
You can compile without MySQL too, you proably don't want my MySQL variant as it 100% not comptabile with the original one.
So, what is VoroN's MySQL variant and how do i use it?
I decided to rewrite MySQL because the original one didn't work properly for me anymore, with some lates mysql server updates, it statred leak the memory.
This variant is only suitable (for now atleast) for local MySQL sessions and not good for remote ones. It's based on native function callbacks and args and doesn't requeire izno's wrapper.
Also it has only 2 connections (synchronous and async). In case your really want to use it, here is how:
First, init your connections in your gametype.gsc:
mysql_initialize("localhost", "root", "yourpass", "yourdb", 3306);
async_mysql_initialize("localhost", "root", "yourpass", "yourdb", 3306);
You can init only sync/async too, ifor example if you plan to use async only.
That's all, you don't have to do anything anymore. now you can use your queries:
I'd recommend to pick a little wrapper i made to simplify the queries.
Here it is:
getRows(result)
{
rowcount = mysql_num_rows(result);
fields = [];
field = mysql_fetch_field(result);
while (isDefined(field))
{
fields[fields.size] = field;
field = mysql_fetch_field(result);
}
rows = [];
for (i = 0; i < rowcount; i++)
{
row = mysql_fetch_row(result);
rows[rows.size] = [];
for(j = 0; j < fields.size; j++)
rows[rows.size - 1][j] = row[j];
}
return rows;
}
getAsyncRows(task)
{
rowcount = async_mysql_num_rows(task);
fields = [];
field = async_mysql_fetch_field(task);
while (isDefined(field))
{
fields[fields.size] = field;
field = async_mysql_fetch_field(task);
}
rows = [];
for (i = 0; i < rowcount; i++)
{
row = async_mysql_fetch_row(task);
rows[rows.size] = [];
for(j = 0; j < fields.size; j++)
rows[rows.size - 1][j] = row[j];
}
return rows;
}
fetchSingleRowArray(result)
{
if (!isDefined(result))
return [];
result = mysql_store_result(result);
row = mysql_fetch_row(result);
mysql_free_result(result);
if (isDefined(row))
return row;
else
return [];
}
fetchAsyncSingleRowArray(task)
{
if (!isDefined(task))
return [];
row = async_mysql_fetch_row(task);
async_mysql_free_task(task);
if (isDefined(row))
return row;
else
return [];
}
fetchRowArray(result)
{
if (!isDefined(result))
return [];
result = mysql_store_result(result);
rows = getRows(result);
mysql_free_result(result);
if (isDefined(rows))
return rows;
else
return [];
}
fetchAsyncRowArray(task)
{
if (!isDefined(task))
return [];
rows = getAsyncRows(task);
async_mysql_free_task(task);
if (isDefined(rows))
return rows;
else
return [];
}
If you know that your query will be a single row e.g row[0] only, or you only need to pick that one, then you can use singlerowarray.
How to use synchronous queries:
result = mysql_query("SELECT NOW()"); // query
row = maps\mp\gametypes\_mysql::fetchSingleRowArray(resu lt); // get rows using wrapper, single row only
printf("Result: %\n", row[0]) // print the result
Don't forget that heavy synchronous queries may lag the server, use async ones for those.
How to use async queries:
async_mysql_create_query("SELECT NOW()", ::callbackFunc, "bla");
callbackFunc(task, arg)
{
row = novoselscripts\_mysql::fetchAsyncSingleRowArray(ta sk); // get rows using wrapper, single row only
printf("Result: %\n", row[0]) // print the result
}
You can pass only one argument to the callback function, you don't have to pass a dummy arg if there are none though, also if there are no callback
e.g you only want to save something to your db:
async_mysql_create_query("SELECT NOW()");
That will work, that result will be automatically freed. You can also use
async_mysql_create_query_nosave but there are really no difference.
Also, passing arguments can only be int, float, vector and string, you can't pass arrays or entities.
For entities, if you want to use 'self' inside the callback function, use:
self async_mysql_create_entity_query("SELECT NOW()", ::callbackFunc, "bla");
That's all of the basics, should be pretty simple. Now some further changes:
lookAtKiller() function:
Still quite experimental, an attempt to create a tf2 like killer camera, but not very successful.
Join DeathRun.. if you are interested to see how it looks/works.
Force client downloads:
Enabled by default, clients with cl_allowDownload 0 will be switched to 1 on connect.
Disable rcon access completely:
Disabled by default, set sv_allowRcon to 0 for that.
Bult in va() fix:
In case you want to use original/unpatched binary.
Removed additional iwd verification:
This is still questionable, but looks like there is some possibility to abuse that and make the server lag, but i'm not 100% sure.
This was also removed in cod4x. It still DOES NOT allow clients with modified/missing iwds' so idk. Quite experimental for now.
Get/set weapon cookcable:
Switch your grenades cookable/uncookable on the fly.
Tell me if you have any bugs/issues with the stuff above.
You can now choose between my and orignal MySQL variant:
1373
You can compile without MySQL too, you proably don't want my MySQL variant as it 100% not comptabile with the original one.
So, what is VoroN's MySQL variant and how do i use it?
I decided to rewrite MySQL because the original one didn't work properly for me anymore, with some lates mysql server updates, it statred leak the memory.
This variant is only suitable (for now atleast) for local MySQL sessions and not good for remote ones. It's based on native function callbacks and args and doesn't requeire izno's wrapper.
Also it has only 2 connections (synchronous and async). In case your really want to use it, here is how:
First, init your connections in your gametype.gsc:
mysql_initialize("localhost", "root", "yourpass", "yourdb", 3306);
async_mysql_initialize("localhost", "root", "yourpass", "yourdb", 3306);
You can init only sync/async too, ifor example if you plan to use async only.
That's all, you don't have to do anything anymore. now you can use your queries:
I'd recommend to pick a little wrapper i made to simplify the queries.
Here it is:
getRows(result)
{
rowcount = mysql_num_rows(result);
fields = [];
field = mysql_fetch_field(result);
while (isDefined(field))
{
fields[fields.size] = field;
field = mysql_fetch_field(result);
}
rows = [];
for (i = 0; i < rowcount; i++)
{
row = mysql_fetch_row(result);
rows[rows.size] = [];
for(j = 0; j < fields.size; j++)
rows[rows.size - 1][j] = row[j];
}
return rows;
}
getAsyncRows(task)
{
rowcount = async_mysql_num_rows(task);
fields = [];
field = async_mysql_fetch_field(task);
while (isDefined(field))
{
fields[fields.size] = field;
field = async_mysql_fetch_field(task);
}
rows = [];
for (i = 0; i < rowcount; i++)
{
row = async_mysql_fetch_row(task);
rows[rows.size] = [];
for(j = 0; j < fields.size; j++)
rows[rows.size - 1][j] = row[j];
}
return rows;
}
fetchSingleRowArray(result)
{
if (!isDefined(result))
return [];
result = mysql_store_result(result);
row = mysql_fetch_row(result);
mysql_free_result(result);
if (isDefined(row))
return row;
else
return [];
}
fetchAsyncSingleRowArray(task)
{
if (!isDefined(task))
return [];
row = async_mysql_fetch_row(task);
async_mysql_free_task(task);
if (isDefined(row))
return row;
else
return [];
}
fetchRowArray(result)
{
if (!isDefined(result))
return [];
result = mysql_store_result(result);
rows = getRows(result);
mysql_free_result(result);
if (isDefined(rows))
return rows;
else
return [];
}
fetchAsyncRowArray(task)
{
if (!isDefined(task))
return [];
rows = getAsyncRows(task);
async_mysql_free_task(task);
if (isDefined(rows))
return rows;
else
return [];
}
If you know that your query will be a single row e.g row[0] only, or you only need to pick that one, then you can use singlerowarray.
How to use synchronous queries:
result = mysql_query("SELECT NOW()"); // query
row = maps\mp\gametypes\_mysql::fetchSingleRowArray(resu lt); // get rows using wrapper, single row only
printf("Result: %\n", row[0]) // print the result
Don't forget that heavy synchronous queries may lag the server, use async ones for those.
How to use async queries:
async_mysql_create_query("SELECT NOW()", ::callbackFunc, "bla");
callbackFunc(task, arg)
{
row = novoselscripts\_mysql::fetchAsyncSingleRowArray(ta sk); // get rows using wrapper, single row only
printf("Result: %\n", row[0]) // print the result
}
You can pass only one argument to the callback function, you don't have to pass a dummy arg if there are none though, also if there are no callback
e.g you only want to save something to your db:
async_mysql_create_query("SELECT NOW()");
That will work, that result will be automatically freed. You can also use
async_mysql_create_query_nosave but there are really no difference.
Also, passing arguments can only be int, float, vector and string, you can't pass arrays or entities.
For entities, if you want to use 'self' inside the callback function, use:
self async_mysql_create_entity_query("SELECT NOW()", ::callbackFunc, "bla");
That's all of the basics, should be pretty simple. Now some further changes:
lookAtKiller() function:
Still quite experimental, an attempt to create a tf2 like killer camera, but not very successful.
Join DeathRun.. if you are interested to see how it looks/works.
Force client downloads:
Enabled by default, clients with cl_allowDownload 0 will be switched to 1 on connect.
Disable rcon access completely:
Disabled by default, set sv_allowRcon to 0 for that.
Bult in va() fix:
In case you want to use original/unpatched binary.
Removed additional iwd verification:
This is still questionable, but looks like there is some possibility to abuse that and make the server lag, but i'm not 100% sure.
This was also removed in cod4x. It still DOES NOT allow clients with modified/missing iwds' so idk. Quite experimental for now.
Get/set weapon cookcable:
Switch your grenades cookable/uncookable on the fly.
Tell me if you have any bugs/issues with the stuff above.