Quick Startup

Added by XATRIX almost 6 years ago

Hi, can you explain how to setup the A2Uplink for writing/reading data from and to MySQL ? Step-by-step configuration. I read you readme.txt, but actually can't understand how to setup Arma to pull the data to the log file, and how to make A2Uplink to read it and make some actions based on MySQL scenarios...

Thanks for support

Replies (3)

RE: Quick Startup - Added by MaHuJa almost 6 years ago

I'm sorry that I can't provide a clear step-by-step answer, but it's not that easy... yet.

The mechanism for bringing data (back) into the game has not been finished. It's half done, though, so once I have the reason to finish it up, it might only take a couple hours to have it working.

As for how to set up a mysql link with it... There are two ways to do this.

One is to generate the SQL in armascript, and forward through uplink. However, any user who can run arbitrary scripts, can run any query against your database that your mission/server is authorized to run. This means that you either trust the users in a closed group not to hack the DB, or you need to use addon signing etc to make it hard to bring in unauthorized armascript. Potentially keeping backups and logging all queries, enabling you to restore it reasonably if it is trashed. On the other hand, I could probably create a generic uplink module for this very quickly.

The other is the model used with bstats, where the armascript is calling up functions in a2u, that construct the SQL and do the database calls. As long as these functions do not allow sql injections, they can't do "DROP TABLE X;" on you, or worse. They could still do bogus function calls. This requires an uplink module tailored to your database use. What kind of data are you thinking to store and retrieve?

Here's approximately how it will work (once set up) using the first approach.

In sqf, you construct a string, which is a lua command calling some function, e.g. a string _a containing something along the lines of
mysql( "SELECT * FROM `players` WHERE playerid = 123456789" )
Then you send if off by
[_a, "callback"] call uplink_exec;
At this point, there needs to be an uplink module that has connected to the database, and defines a function mysql() which runs the query, packages the result, and sends it back to the game using functionality that, as I said, hasn't been written yet. The game will then run the armascript function "callback" - as named above - with the results as parameters.

The details are subject to change as I start implementing it, but the general outline will remain. Because of its async nature, using a callback is nonnegotiable - even though it complicates coding a bit. How long it takes before the callback is run will depend on a few things, such as uplink's poll rate, how quickly the db answers, or if uplink is running at all. The game won't stop dead if it's not available or slow to respond.

As for how it would be set up, it would have a module in the directory uplink/user, and upconfig.lua would have it listed in the "load" list. Probably have a parameter in that file for what database/user/pass to connect to. The mission needs to have its database using code set up. And of course, there must be a database set up.

Getting uplink to read the data from the game, depends a lot on your setup.
Windows: I don't quite know what the server does on windows, but I think it's a .rpt file similar to the one generated by the game (client) itself.
Linux: A linux server outputs this data through "stdout" which must be saved to some file - usually the responsibility of the scripts starting the server. The script that comes with the linux server default logs to a file 2302.log depending on the port it is run at. If it's set up by a game server hosting company this is likely different, and you'll need to ask them.

RE: Quick Startup - Added by XATRIX almost 6 years ago

So, is there a way to read data from the SQL to the game ? Maybe sqf supports some read functions from file or stdin/stdout ?

RE: Quick Startup - Added by MaHuJa almost 6 years ago

See http://community.bistudio.com/wiki/loadFile - it's doable.

Of course, it's not that simple.

I cannot rely on a user entering a filename and pressing some load button.
So I spawn a script that looks for a file, reading it (until it has some content), and then looking for the next.

There may be stale data from a previous session
I generate a random number, and check if that number's already been used, until I have an unused number. I then send that number to uplink so it knows what file the game side is looking for.

The server locks any files it reads
For each session, the random number above is the session id. I then look for session.serial, e.g. 1234.0 1234.1 1234.2 and so on.

One important clue is that because the server keeps the files open, it may run afoul of any limits the os places on open files. This has already sunk servers with ace and loads of other addons and missions. These restrictions then need to be relaxed, which is not something I can do. The one thing I am doing, is caching all the writes and writing them all in one file when it runs out of work to do.

The above has (basically) been done. What remains is the exact format of the files I'll be writing, and writing the code to actually do that.
The requirements I'm working towards are
  • Any number of script calls in that one file
  • An error in one sqf script will not prevent the rest from running.
  • Callbacks are spawned, meaning that a callback that runs "forever" won't block other callbacks. As a side effect, the ordering of callbacks are undefined.
  • Callback data being of script form, meaning your function would use _this = call _this; to get your data. That code can throw exceptions.
  • I need the file write to be atomic - if the game were to read a half-written file, that would be bad. (Write elsewhere then rename the file.)