PDA

View Full Version : Some latest updates



voron00
23rd October 2017, 12: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.

Whiskas
23rd October 2017, 15:29
Could you show us an example of weapon cookable? Should it be executed on weapon obj?

Thanks for your work

voron00
23rd October 2017, 15:38
Could you show us an example of weapon cookable? Should it be executed on weapon obj?

Thanks for your work

It's just another weaponfunction offset from: https://killtube.org/showthread.php?2159-Weapon-functions-(-setMoveSpeedScale)

But here's my code:


loadWeaponFunctions()
{
loadedweapons = getLoadedWeapons();

for (i = 0; i < loadedweapons.size; i++)
{
assert(i < 48); // bugs out after approximately 48 (izno)

if (isDefined(level.weapons[loadedweapons[i]]))
level.weapons[loadedweapons[i]].id = i; // i = weapon index
}
}

getWeaponId(weapon)
{
if (isDefined(level.weapons[weapon]) && isDefined(level.weapons[weapon].id))
return level.weapons[weapon].id;
else
return -1;
}

weaponMaxAmmo(weapon)
{
id = getWeaponId(weapon);

if (id == -1)
return 0;

return getweaponmaxammo(id);
}

weaponClipSize(weapon)
{
id = getWeaponId(weapon);

if (id == -1)
return 0;

return getweaponclipsize(id);
}

weaponDamage(weapon)
{
id = getWeaponId(weapon);

if (id == -1)
return 0;

return getweapondamage(id);
}

weaponMeleeDamage(weapon)
{
id = getWeaponId(weapon);

if (id == -1)
return 0;

return getweaponmeleedamage(id);
}

weaponFireTime(weapon)
{
id = getWeaponId(weapon);

if (id == -1)
return 0;

return getweaponfiretime(id);
}

weaponMeleeTime(weapon)
{
id = getWeaponId(weapon);

if (id == -1)
return 0;

return getweaponmeleetime(id);
}

weaponReloadTime(weapon)
{
id = getWeaponId(weapon);

if (id == -1)
return 0;

return getweaponreloadtime(id);
}

weaponReloadEmptyTime(weapon)
{
id = getWeaponId(weapon);

if (id == -1)
return 0;

return getweaponreloademptytime(id);
}

weaponHitLocMultiplier(weapon, hitloc)
{
id = getWeaponId(weapon);

if (id == -1)
return 0;

return getweaponhitlocmultiplier(id, hitloc);
}

setWepDamage(weapon, dmg)
{
id = getWeaponId(weapon);

if (id == -1)
return 0;

return setweapondamage(id, dmg);
}

setWepMeleeDamage(weapon, dmg)
{
id = getWeaponId(weapon);

if (id == -1)
return 0;

return setweaponmeleedamage(id, dmg);
}

setWepFireTime(weapon, time)
{
id = getWeaponId(weapon);

if (id == -1)
return 0;

return setweaponfiretime(id, time);
}

setWepMeleeTime(weapon, time)
{
id = getWeaponId(weapon);

if (id == -1)
return 0;

return setweaponmeleetime(id, time);
}

setWepReloadTime(weapon, time)
{
id = getWeaponId(weapon);

if (id == -1)
return 0;

return setweaponreloadtime(id, time);
}

setWepReloadEmptyTime(weapon, time)
{
id = getWeaponId(weapon);

if (id == -1)
return 0;

return setweaponreloademptytime(id, time);
}

setWepHitLocMultiplier(weapon, hitloc, multiplier)
{
id = getWeaponId(weapon);

if (id == -1)
return 0;

return setweaponhitlocmultiplier(id, hitloc, float(multiplier));
}

There are no cookable since im not using it, but should be quite easy to copy-paste.


weaponCookable(weapon)
{
id = getWeaponId(weapon);

if (id == -1)
return 0;

return getweaponcookable(id);
}

setWepCookable(weapon, cookable)
{
id = getWeaponId(weapon);

if (id == -1)
return 0;

return setweaponcookable(id, cookable);
}

Whiskas
23rd October 2017, 16:11
Wow, thanks.

Ni3ls
23rd October 2017, 17:57
But this will apply to everybody with that specific weapon right? (all mp44's). It's not possible to apply this only to the weapon I'm holding (just my mp44)?

voron00
23rd October 2017, 18:46
But this will apply to everybody with that specific weapon right? (all mp44's). It's not possible to apply this only to the weapon I'm holding (just my mp44)?

Ye, not possible.

voron00
16th November 2017, 16:19
Pushed some experimental stuff to dev branch, might wanna test. Basicly rewrote everything for structures, added custom bot usermove stuff, bots are not lagging anymore, etc, some fixes are still coming up though.

voron00
19th November 2017, 18:54
Pushed weapondef_t, only a few things are unknown there.

voron00
6th December 2017, 18:03
The changes seems stable to me, pushed to master.