Page 1 of 2
Vaultster for ALFA, how it will work
Posted: Thu Jun 05, 2008 9:36 am
by Hialmar
First a few words about vaultster as it worked with NWN1:
When a PC wants to portal, vaultster sends the bic file to the destination server using specific client and server (both are included in the NWNX2 plugin). When the bic file is completely on the distant computer the portalling starts.
Advantages:
- bic files are stored on the server computers (no more corruption due to network or caching problems) ;
- you don't need to mount a drive using netrive or webdrive ;
- the server doesn't need to wait for the content of the GSID folder to be downloaded (if it isn't cached) before it can present the character selection screen ;
- the server doesn't need to wait for the bic file to be downloaded each time a player connects.
Disadvantages:
- vaultster only works with NWNX2 and therefore only with NWN1 ;
- we have no central location where the bic files are stored ;
- when a server is down you can't easily log on another server and wait in quarantine for a DM to validate you ;
- when you do that, either you end up with an old version of your PC (if you went through that server) or with no PC at all (if you never went through it).
- if an hoster quits ALFA he can go away with all the local PCs if he wants to bug us.
My solutions to those disadvantages:
1- I'll port vaultster to NWNX4 and therefore NWN2 ;
2- There will be a vaultster server running on the vault computer (I'll call it the backup vaultster server) ;
3- There will also be a vaultster client running on the vault computer (I'll call it the backup vaultster client) ;
4- Each time a PC is saved locally on the server, vaultster will try to upload the bic file to the vault computer using the local client and the backup vaultster server. If the upload fails it will retry in background until it manages to upload it ;
5- When a server is down, the player will be able to connect to a web page, identify himself and request for his backed up bic file to be sent to another server. This will use the backup vaultster client (tied to some php code) and the vaultster server on the destination server. Of course the player will then end-up in quarantine and will need a DM to validate him (I think I have a few solutions to avoid that if we want to).
What I have done so far:
1- I have ported vaultster to NWNX4 so that it works with NWN2. I need to test that now.
2- I have started to work on the standalone version of vaultster which will be used for the backup vaultster server.
As soon as I have steps 3 (backup vaultster client) and 4 (backup process) we can start testing all this while I work on step 5 which will be a bit more complex because I need to modify php to be able to call the client code from it.
I'll crosspost this message to several forums in order to have some information/ideas/remarks.
Posted: Thu Jun 05, 2008 3:08 pm
by ç i p h é r
This is excellent news. Thanks for taking this on, Hialmar.
Posted: Thu Jun 05, 2008 7:16 pm
by Nalo Jade
Super cool!
Posted: Sun Jun 08, 2008 2:12 pm
by Hialmar
Okay I have a first version that works.
It does the normal vaultster transfer + the backing up on the vault computer (with a standalone backup vaultster server).
I still need to fix a few little problems but it's functional.
The backup uses an AT for now (like vaultster standard operation).
I.e. you must click on an AT to backup your character.
I'll modify this to use the PC Tools "save character" button.
Now what I need to figure is how I can automatically backup files when a player logs out.
Anyone as an idea about that ?
I suppose it should go in the module "On Client Leave" event but I have never touched at that I think.
Here is the current script I use on the backup AT:
Code: Select all
#include "vaultster_inc"
void main()
{
// check if we are using an AT
object oMyPC = GetClickingObject();
// or if we are trying again to backup
if(!GetIsPC(oMyPC)) oMyPC = OBJECT_SELF;
if(!GetIsPC(oMyPC)) return;
SendMessageToPC(oMyPC, "Vaultster Test.");
//Your code goes here
int status = PortalPC(oMyPC, "vault.alandfaraway.org");
// returns: VAULTSTER_OK portal was successfully initiated
// VAULTSTER_FAILED internal failure
// VAULTSTER_SERVERBUSY too much players portalling already
// VAULTSTER_NOPLAYER object was no player
if(status == VAULTSTER_FAILED) {
SendMessageToPC(oMyPC, "Internal failure. Please contact the Infra Admin or the HDM.");
} else if(status == VAULTSTER_SERVERBUSY) {
SendMessageToPC(oMyPC, "Too many players are being backed up already, will try again in 30 seconds.");
DelayCommand (30.0f, ExecuteScript("vaultster_backup_pc", oMyPC));
} else if(status == VAULTSTER_NOPLAYER) {
SendMessageToPC(oMyPC, "Object was not a player.");
} else {
SendMessageToPC(oMyPC, "Backup was successfully initiated.");
DelayCommand (1.0f, ExecuteScript ("vaultster_backup_check_status", oMyPC));
}
}
And the script which is called regularly to check backup completion:
Code: Select all
#include "vaultster_inc"
void main ()
{
object oPC = OBJECT_SELF;
int status = PortalStatus(oPC);
if (status == VAULTSTER_STATUS_OK)
// file was transferred successfully, so now portal the player
// ActivatePortal (oPC, "nwn.someserver.com", "", "", TRUE);
SendMessageToPC (oPC, "Backup Complete.");
else if (status == VAULTSTER_STATUS_BUSY) {
// vaultster is still busy with the transmission
SendMessageToPC (oPC, "Hold on..");
DelayCommand (1.0f, ExecuteScript ("vaultster_backup_check_status", oPC));
}
else {
// failure during transmission or not able to connect (see log file)
SendMessageToPC(oPC, "Failed to backup the character file. Trying again in 30 seconds.");
DelayCommand (30.0f, ExecuteScript("vaultster_backup_pc", oPC));
}
}
If someone is interested to look at the code it is here:
http://www.alandfaraway.org/Hialmar/
vaultster.rar: the plugin source for windows (you need the source of NWNX4 to compile it).
vaultster_linux.tgz: the standalone server source for linux.
vaultster_test.rar: a test mod
xp_vaultster.ini: ini file for the plugin
xp_vaultster.dll: the plugin for NWNX4
Posted: Sun Jun 08, 2008 2:45 pm
by Hialmar
Okay I checked the ACR and it should be easy to do the following:
Code: Select all
#include "vaultster_inc"
void main()
{
object oMyPC = GetExitingObject();
if(!GetIsPC(oMyPC)) return;
SendMessageToPC(oMyPC, "Vaultster Test.");
//Your code goes here
int status = PortalPC(oMyPC, "vault.alandfaraway.org");
// returns: VAULTSTER_OK portal was successfully initiated
// VAULTSTER_FAILED internal failure
// VAULTSTER_SERVERBUSY too much players portalling already
// VAULTSTER_NOPLAYER object was no player
if(status == VAULTSTER_FAILED) {
SendMessageToPC(oMyPC, "Internal failure. Please contact the Infra Admin or the HDM.");
} else if(status == VAULTSTER_SERVERBUSY) {
SendMessageToPC(oMyPC, "Too many players are being backed up already, will try again in 30 seconds.");
DelayCommand (30.0f, ExecuteScript("vaultster_backup_pc", oMyPC));
} else if(status == VAULTSTER_NOPLAYER) {
SendMessageToPC(oMyPC, "Object was not a player.");
} else {
SendMessageToPC(oMyPC, "Backup was successfully initiated.");
DelayCommand (1.0f, ExecuteScript ("vaultster_backup_check_status", oMyPC));
}
}
However, all the delay commands won't work I'm afraid because oMyPC won't be around.
So maybe I should attach them to the module

Posted: Sun Jun 08, 2008 5:19 pm
by AcadiusLost
This looks very promising- I'd always thought an adaption of Vaultster would be a good way to go for ending the CEB problems, but never had the time to investigate it (nor the expertise to recompile it for NWNx4). I'm thrilled you've taken it upon yourself to code it up. Hopefully soon I can help test and get it integrated into the ACR.
Now, with regards to the DelayCommand issue: this line:
DelayCommand (30.0f, ExecuteScript("vaultster_backup_pc", oMyPC));
The vaultster_backup_pc.nss will be called regardless of whether the PC still exists as an object or not- but if the PC is logged off, oMyPC = OBJECT_INVALID. What is the vaultster script using the pointer to the PC for? If it's being used to work out the BIC filename, we could pass that directly as a string via DelayCommand, so it would be able to execute regardless of whether the PC was logged in or not, for example. If it's not too long, perhaps you could post the vaultster_backup_pc.nss text here as well? Unless it is the middle code block among those you posted here already, that is.
Posted: Sun Jun 08, 2008 7:17 pm
by Vendrin
Awesome work man. Thanks alot!
Posted: Sun Jun 08, 2008 8:39 pm
by Hialmar
AcadiusLost wrote:This looks very promising- I'd always thought an adaption of Vaultster would be a good way to go for ending the CEB problems, but never had the time to investigate it (nor the expertise to recompile it for NWNx4). I'm thrilled you've taken it upon yourself to code it up. Hopefully soon I can help test and get it integrated into the ACR.
Now, with regards to the DelayCommand issue: this line:
DelayCommand (30.0f, ExecuteScript("vaultster_backup_pc", oMyPC));
The vaultster_backup_pc.nss will be called regardless of whether the PC still exists as an object or not- but if the PC is logged off, oMyPC = OBJECT_INVALID. What is the vaultster script using the pointer to the PC for? If it's being used to work out the BIC filename, we could pass that directly as a string via DelayCommand, so it would be able to execute regardless of whether the PC was logged in or not, for example. If it's not too long, perhaps you could post the vaultster_backup_pc.nss text here as well? Unless it is the middle code block among those you posted here already, that is.
The PC is used to get the GSID and the character name in order to find the bic.
Yes I could pass the string to the function after slightly modifying it.
vaultster_backup_pc.nss is the middle code indeed.
The only thing you miss is the vaultster include.
It is in the mod and is similar to that (this is the original one, I'm on my other computer so I cannot fetch the code which is updated for NWNX4 but it is very similar):
Code: Select all
// Name : VaultSTER portal system include
// Purpose : Various VaultSTER related functions
// Authors : Jeroen Broekhuizen, Ignmar Stieger
// Modified : January 12, 2005
// Updates:
// 7-2-2005 - fixed bug in the PortalStatus script
// This file is licensed under the terms of the
// GNU GENERAL PUBLIC LICENSE (GPL) Version 2
// Error codes returned by VaultSter
const int VAULTSTER_OK = 0;
const int VAULTSTER_FAILED = -1;
const int VAULTSTER_SERVERBUSY = -2;
const int VAULTSTER_NOPLAYER = -3;
const int VAULTSTER_INTERNALERROR = -4;
// Status messages
const int VAULTSTER_STATUS_OK = 0;
const int VAULTSTER_STATUS_BUSY = 2;
const int VAULTSTER_STATUS_ERROR= 3;
// Start portaling a player to the requested server. Use PortalStatus
// to keep track of the status of the portal for this player.
// returns: VAULTSTER_OK portal was successfully initiated
// VAULTSTER_FAILED internal failure
// VAULTSTER_SERVERBUSY too much players portalling already
// VAULTSTER_NOPLAYER object was no player
int PortalPC (object oPC, string Server);
// Checks the current status of portalling for the specified player
// returns: VAULTSTER_STATUS_OK transmission was successfull
// VAULTSTER_STATUS_BUSY transmission is not yet finished
// VAULTSTER_STATUS_ERROR there was an error during the transmission
int PortalStatus (object oPC);
//////////////////////////////
// Implementation
//////////////////////////////
// Convers a player name to it's filename
// returns: filename of the character
string convertToFilename(string sPlayerName)
{
string sRes;
string sChar;
int i, j;
int iLen = GetStringLength(sPlayerName);
if (iLen > 16)
iLen = 16;
for (i = 0; i < iLen; i++) {
sChar = GetSubString(sPlayerName, i + j, 1);
if ((sChar != " ") && (sChar != "."))
sRes += sChar;
else {
i--;
j++;
}
}
return sRes;// + ".bic";
}
int PortalPC (object oPC, string Server)
{
// make sure it is a PC object
if (!GetIsPC (oPC)) return VAULTSTER_NOPLAYER;
object oModule = GetModule();
// make sure that the latest changes are saved too
ExportSingleCharacter (oPC);
// fetch the required information
string player = GetPCPlayerName (oPC);
string character = convertToFilename (GetName (oPC));
// build up the command string
string command = Server + "|" + player + "|" + character;
SetLocalString (oModule, "NWNX!VAULTSTER!SEND", command);
int id = StringToInt (GetLocalString (oModule, "NWNX!VAULTSTER!SEND"));
// check the result
if (id < 0)
// return the error message
return id;
else {
// save the id on the player (+1 as id is zero based what is
// problematic with retreiving the id in PortalStatus, as on
// error GetLocalString results also 0).
SetLocalInt (oPC, "VAULTSTER_ID", id+1);
return VAULTSTER_OK;
}
}
int PortalStatus (object oPC)
{
// get the portal id from the player
int id = GetLocalInt (oPC, "VAULTSTER_ID");
if (id == 0) return VAULTSTER_STATUS_ERROR;
// get the status from Vaultster
object oModule = GetModule ();
SetLocalString(oModule, "NWNX!VAULTSTER!STATUS", IntToString(id-1));
int status = StringToInt (GetLocalString (oModule, "NWNX!VAULTSTER!STATUS"));
// delete if neccessary the vaultster id from the player
if (status == VAULTSTER_STATUS_OK || status == VAULTSTER_STATUS_ERROR) {
DeleteLocalInt (oPC, "VAULTSTER_ID");
}
return status;
}
Posted: Sun Jun 08, 2008 8:44 pm
by Hialmar
The only things that change in this script are the following parts (and similar code):
Code: Select all
SetLocalString (oModule, "NWNX!VAULTSTER!SEND", command);
int id = StringToInt (GetLocalString (oModule, "NWNX!VAULTSTER!SEND"));
Which is now replaced with only one call:
Code: Select all
int id = NWNXGetLocalInt("VAULSTER", "SEND", command, 0);
Not sure of the name of the function but that's about it.
I would just need to write another PortalPC function taking the command in parameter I suppose.
Then the tricky part will be to manage the asynchronous calls to PortalStatus.
Posted: Sun Jun 08, 2008 9:56 pm
by AcadiusLost
The upcoming 1.13 NWN2 patch is supposed to add a function to determine the bic file name as well, I expect that would help as well, though it would be easy enough to work in once we have the patch.
Also important to keep in mind is that at the time of the OnClientLeave event, the PC Object still exists, but attempts to collect information on the Player (GSID, CDKey, etc) automatically fail, as the player has already departed. So, that information can be cached as Local Variables on the PC object, but that needs to be done before the OnClientLeave event.
Additionally, we'll be implementing some LetoScript edits to the .bic file which will occur just after the player logs off (so they will act on bics after they are updated on logout). To avoid collision between this and the portaling/backup, we'll have to make sure that part is delayed long enough to ensure the book-keeping gets finished first.
Posted: Mon Jun 09, 2008 8:12 am
by Hialmar
Ah nice about the function to compute the bic file name. It should be easy to replace the current function that does that.
I can maybe cache the GSID on the PC object in the OnClientEnter event.
For the LetoScript edits I can maybe put a sleep of 1 or 2 seconds in the C++ thread which manages the upload.
The best thing however would be if we can have a direct information of the end of modifications of the LetoScript plugin similar to what Vaultster proposes.
What plugin will you use ? I can maybe look at it and modify it to add this feature if it is absent.
Posted: Mon Jun 09, 2008 4:00 pm
by AcadiusLost
The plugin I've used is here, with source:
http://data.virusman.ru/nwn/nwnx4/xp_leto-0.0.1-src.rar
http://data.virusman.ru/nwn/nwnx4/xp_leto-0.0.1.rar
That's adapted by Virusman of NWNx4 - IIRC it's compiled for NWNx4 0.0.7, so you may need the compatibility hook in order to load it. Alternatively, if you want to merge in the functions of the Leto plugin with the improved vaultster one you're working on, that would be a nice way to make sure all bic edits get applied before any syncronization with the backup copy, and forwarding of the BIC to the next Live server.
Re: Vaultster for ALFA, how it will work
Posted: Mon Jun 09, 2008 4:40 pm
by paazin
A quick question about the more 'usage' side of it that a player would see, namely the actual transfer from one server to another. Trying to find an available DM to validate a PC gets kinda difficult - would it be possible to access leto script outisde of nwscript and within it? It might be a useful way to set a hard-coded value on the PC for which server he or she should transfer to/from without having to do too much extra work
Posted: Mon Jun 09, 2008 7:51 pm
by Hialmar
Thanks for the links AL I'll look into that.
Merging both plugins sounds the best thing to do indeed.
Paazin, it will work like before. You'll have visas and things like that.
I'm not sure if they will be stored on the PC or in the database but anyway they will be there.
The only validation you'll need is when your server is down and you want to connect to another server.
Before that you'll have to log on the vault webserver, identify yourself and request that your PC be sent to the server you want to log on.
We could maybe avoid the validation if we can test that the server is down from the webserver. It could work but it won't be a priority.
Posted: Sat Jun 14, 2008 4:47 pm
by Hialmar
I have worked on the auto backup on leave thingy and I'm stuck again.
It gets way too complex if I try to store all the backup data on the module (ie GSIDs, Bic names and thread ids for each and every PC which are logged out but not yet saved).
How can I use DelayCommand with a string AL ?
If I can do that as you suggested before, I could format everything I need in this string (GSID, BicName, thread ID) and it would be way easier.
Alternately maybe we could have an area somewhere and put some dummy objects there with all the details of PCs that we are trying to backup.
It's messy but I'm a bit stuck there.