logo logo

 Back to main page

The NWNX Community Forum

 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
 
multiple instance communications
Goto page 1, 2  Next
 
Post new topic   Reply to topic    nwnx.org Forum Index -> General Discussion
View previous topic :: View next topic  
Author Message
Tempest



Joined: 26 Feb 2008
Posts: 32

PostPosted: Fri Apr 18, 2008 3:06    Post subject: multiple instance communications Reply with quote

Hey there everyone. I am in the process of standing up a 3 instance world with all instances running on the same server hardware. I thought I saw somewhere posted here about scripts to provide inter-instance communications for players and DMs? Is there such a beast and if so can someone point me to it?

Also I was told few months back that I could simply point my 2nd instance to the location of the DB for the 1st instance. Would I simply repeat this step for the 3rd instance as well so that I am sharing the DB across all instances?

Thanks for the help!

"T"
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
FunkySwerve



Joined: 02 Jun 2005
Posts: 377

PostPosted: Fri Apr 18, 2008 18:37    Post subject: Reply with quote

You probably saw it referred to in one of my posts. Our system is highly integrated into our other scripts, but theprinciple is simple: insert messages into mysql, and poll the database frommod heartbeat. Here's the table we use for messages:

Code:


mysql> describe user_messages
    -> ;
+-----------------+-------------+------+-----+-------------------+----------------+
| Field           | Type        | Null | Key | Default           | Extra          |
+-----------------+-------------+------+-----+-------------------+----------------+
| um_id           | int(11)     | NO   | PRI | NULL              | auto_increment |
| um_sender_name  | varchar(64) | NO   |     |                   |                |
| um_sender_cdkey | varchar(16) | NO   |     |                   |                |
| um_recipient    | varchar(64) | NO   | MUL |                   |                |
| um_text         | text        | NO   |     |                   |                |
| um_guild        | tinyint(4)  | NO   |     |                   |                |
| um_tstamp       | timestamp   | NO   |     | CURRENT_TIMESTAMP |                |
+-----------------+-------------+------+-----+-------------------+----------------+


Other tables are involved as well, like our user list, but the end result is a system that allows inter-server tells with a !tell command (which are delivered when the person logs in, if they are offline when delivery is attempted), interserver guild channels with /g, interserver dm messages with the !dm command, run announcement interserver shouts with !runmsg, and dm interserver shouts with dm_globalmsg. It relies on a unique id stamped on the tag of the character, and a large number of other highly integrated systems, like SIMTools (highly customized), making it impossible to share in full without sharing our mod, which is not in the cards. The principles underlying the system are simple enough, however, that you should be able to set up at least a rudimentary system with reletive ease.

LMK if you have questions.

Best,
Funky
Back to top
View user's profile Send private message
Tempest



Joined: 26 Feb 2008
Posts: 32

PostPosted: Sat Apr 19, 2008 6:06    Post subject: Reply with quote

ahh yes thats right...Thanks for the memory jog. Well without your help to implement I dont think I have the expertise to make it work. Would be great to have some notes on how to get that bugger installed.

Thanks.... "T"
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
Disco



Joined: 06 Dec 2006
Posts: 152

PostPosted: Sun Apr 20, 2008 9:58    Post subject: Reply with quote

I made a system something like this, but probably a bit simpler. It works from forum > nwn but can easily be made into nwn <> nwn once 1.69 comes out. Intercepting the messages a PC wants to send is the most tricky bit of it all (I find listeners tricky and don't use SIMtools myself).

I can give you the forum > server thing, though. It helps players a lot when the server is full.
Back to top
View user's profile Send private message
Tempest



Joined: 26 Feb 2008
Posts: 32

PostPosted: Mon Apr 21, 2008 2:31    Post subject: Reply with quote

thanks Disco, Im not so worried about the players because I can see the OOC talk being a ton. But I would like to have an in-game system for the DMs to talk across the instances.

"T"
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
FunkySwerve



Joined: 02 Jun 2005
Posts: 377

PostPosted: Mon Apr 21, 2008 6:54    Post subject: Reply with quote

Are you using SIMTools, or at least nwnx_chat? Without it sending dm channel to the chat window is impossible, though you can still send it to the combat log. It'd also make capturing the text child's play.

Funky
Back to top
View user's profile Send private message
Tempest



Joined: 26 Feb 2008
Posts: 32

PostPosted: Tue Apr 22, 2008 2:12    Post subject: Reply with quote

hmm never heard of SImTools? also I thought I had all the NWNX plug-ins but will need to check about chat. Can I get that here?

Thanks... "T"
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
FunkySwerve



Joined: 02 Jun 2005
Posts: 377

PostPosted: Tue Apr 22, 2008 10:29    Post subject: Reply with quote

It's a scriptset that uses nwnx_chat:
http://nwvault.ign.com/View.php?view=Scripts.Detail&id=2993

LMK when you get it installed and working and I'll help you set up a rudimentary interserver messaging system. All the plugins and instructions that you need are there.

Funky
Back to top
View user's profile Send private message
Tempest



Joined: 26 Feb 2008
Posts: 32

PostPosted: Wed Apr 23, 2008 0:35    Post subject: Reply with quote

Thanks a ton Funky! Will go get it now.....
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
Tempest



Joined: 26 Feb 2008
Posts: 32

PostPosted: Wed May 07, 2008 2:18    Post subject: Reply with quote

okay funky got the SIMTOOLS installed, thank you for that. I would like to work with you about the messaging system when you have time.

Also I was wondering how do you control regional languages and learned languages in it?

Thanks!!!

:T:
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
FunkySwerve



Joined: 02 Jun 2005
Posts: 377

PostPosted: Wed May 07, 2008 6:06    Post subject: Reply with quote

I'll work up some rudimentary messaging for you shortly, using MySQL. We add languages only for subrace, and don't use the regionals - they were added at the request of the Myth Drannor PW. I would suggest a teacher, of the sort contained in the test mod, or some kind of region selecting option in a convo somewhere.

Funky
Back to top
View user's profile Send private message
Tempest



Joined: 26 Feb 2008
Posts: 32

PostPosted: Fri May 09, 2008 5:40    Post subject: Reply with quote

thanks so much!
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
FunkySwerve



Joined: 02 Jun 2005
Posts: 377

PostPosted: Sun May 18, 2008 19:34    Post subject: Reply with quote

First, open your module properties and add a local string to the module called Quote with the value " (one double quote, not two singles).

Next, put this onused of a placeable in a player-inaccessible area, after replacing YOUR_KEY with your public cd key, to ensure that no one else pulls it (eg, other dms with access to it). You can remove it after you've used it once, or simply leave it there.
Code:

void CreateTable(object oPC)
{
    SQLExecDirect("DROP TABLE messages");
    SendMessageToPC(GetLastUsedBy(), "Table 'messages' deleted.");

    SQLExecDirect("CREATE TABLE messages (" +
                    "server VARCHAR(32) default NULL," +
                    "name VARCHAR(64) default NULL," +
                    "sender VARCHAR(64) default NULL," +
                    "message VARCHAR(255) default NULL," +
                    "KEY (server,name,message)" +
                    ")" );

    SendMessageToPC(oPC, "Table 'messages' created.");
}
void main()
{
    object oPlayer = GetLastUsedBy();
    if (GetPCPublicCDKey(oPlayer) == "YOUR_KEY")
    {
        CreateTable(oPlayer);
    }
}


Put this on mod load, to write the server's ip as a local string on the mod. This allows you to distinguish the servers from one another despite them running identical modules. It must be placed before any potential returns. If you are using SQLite I don't believe the ip check will work, and you will have to set the ips on the modules manually, meaning that you can not run identical versions of the module on all servers if you are using SQLite.

Code:

    /* determine what server this is by checking the ip via the database */
    string sServerIP;
    string sSQL = "select substring_index(user(), '@', -1) as ip;";

    SQLExecDirect(sSQL);

    if (SQLFetch() == SQL_SUCCESS)
        sServerIP = SQLGetData(1);
    else
        sServerIP == "";

    if (sServerIP != "")
        SetLocalString(OBJECT_SELF, "ServerIP", sServerIP);
    else
        WriteTimestampedLogEntry("Error finding server ip!");


Make this your mod heartbeat, or merge it with your current mod heartbeat. You may want to change the second increment to 6, depending on when you hearbeat is firing at, but it will have to be a divisor of 60, unless you change the 60 to another number. Basically, it's set up to increment the int by 5 every time the heartbeat fires, and whenever it hits a multiple of 60, it checks for messages. This is in order to keep the hb overhead low. The actual heartbeat on my PW is much heftier than this one, which is feather light, so you shouldn't sweat using it.

Code:

#include "fky_chat_inc"

object FindAddressee(string sPlayername)
{
    string sCheck;
    object oPC = GetFirstPC();
    while (GetIsObjectValid(oPC))
    {
        sCheck = GetPCPlayerName(oPC);
        if (sCheck == sPlayername) return oPC;
        oPC = GetNextPC();
    }
    return OBJECT_INVALID;
}

void main()
{
    int nTime = GetLocalInt(OBJECT_SELF,"uptime");
    nTime = nTime + 5;/* changed from 6 because linux server was firing the hb event every 5.012 seconds - set to 6 or whatever rate your mod heartbeat fires at (use profiling to determine), so long as it is a divisor of 60 */
    SetLocalInt(OBJECT_SELF,"uptime", nTime);
    if (!(nTime%60))
    {
        string sServer = GetLocalString(OBJECT_SELF, "ServerIP");
        string sSQL = "SELECT name, sender, message FROM messages WHERE server = '" + sServer + "'";
        string sMessage, sName, sSender;
        object oAddressee;
        object oMod = GetModule();
        SQLExecDirect(sSQL);
        while(SQLFetch() != SQL_ERROR)
        {
            sMessage = SQLDecodeSpecialChars(SQLGetData(3));
            sName = SQLDecodeSpecialChars(SQLGetData(1));
            sSender = SQLDecodeSpecialChars(SQLGetData(2));
            if (sName == "Shout") AssignCommand(oMod, SpeakString(sMessage, TALKVOLUME_SHOUT));
            else if (sName == "DM") {
                sMessage = COLOR_LT_BLUE + sMessage + COLOR_END;
                SendMessageToPCDMs(sMessage);
                SendMessageToPCAdmins(sMessage);
                SendMessageToDMDMs(sMessage);
                SendMessageToDMAdmins(sMessage);
            }
            else
            {
                sName = GetStringRight(sName, GetStringLength(sName)- 4);//prefix is FKY_
                oAddressee = FindAddressee(sName);
                if (GetIsObjectValid(oAddressee))
                {
                    FloatingTextStringOnCreature("<c þ >Interserver message received from " + sSender + "!</c>", oAddressee, FALSE);
                    if (SEND_CHANNELS_TO_CHAT_LOG)
                        SendChatLogMessage(oAddressee, "<c þ >" + sMessage + "</c>", GetMessenger());
                    else
                        SendMessageToPC(oAddressee, "<c þ >" + sMessage + "</c>");
                }
            }
        }
        sSQL = "DELETE FROM messages WHERE server = '" + sServer + "'";
        SQLExecDirect(sSQL);
    }
}


Insert this in fky_chat_inc, just under the two const strings, you should be pasting it in around line 29 or so, above the comments for the CommandRedirect function. You will need to replace the ips I put here with the ips of your servers (not including ports).

Code:

const string SERVER_1_IP = "216.144.214.111";//these are just sample ips, replace them with the ips of your three servers
const string SERVER_2_IP = "216.144.214.112";
const string SERVER_3_IP = "216.144.214.113";


Insert this into fky_chat_inc, in the HandleCommands function, in the 'd' case, after the 'else if (GetStringLeft(sCText, 2) == "de") CommandRedirect(oCPC, 2);' if bracket. If you haven't modified SIMTools and have added the consts above, it should be around line 1957 of that script (it varies between Lin and Win versions).

Code:

                else if (GetStringLeft(sCText, 5) == "dm ")
                {
                    if (GetLocalInt(oCPC, "FKY_CHT_BANDM"))//check for DM ban
                        FloatingTextStringOnCreature(COLOR_RED+"You are banned from DM channel and may not send interserver DM messages."+COLOR_END, oCPC, FALSE);
                    else
                    {
                        sCText = GetStringRight(sCText, GetStringLength(sCText) - 3);
                        sCText = "[DM Message from " + GetPCPlayerName(oCPC) + "] " + sCText;
                        if (GetStringLength(sCText) > 255)
                            FloatingTextStringOnCreature(COLOR_RED+"Combined header and message over 255 characters! Message could not be sent!" + COLOR_END, oCPC);
                        else
                        {
                            sCText = SQLEncodeSpecialChars(sCText);
                            sSort = GetLocalString(GetModule(), "ServerIP");
                            if (sSort == SERVER_1_IP)
                            {
                                sTarget = "INSERT INTO messages (server,name,message) VALUES ('" + SERVER_2_IP + "','DM','" + sCText + "'),('" + SERVER_3_IP + "','DM','" + sCText + "')";
                                SQLExecDirect(sTarget);
                                FloatingTextStringOnCreature("<c þ >DM Message sent to all servers!</c>", oCPC);
                                SQLDecodeSpecialChars(sCText);
                                SendMessageToPCDMs(sCText);
                                SendMessageToPCAdmins(sCText);
                                SendMessageToDMDMs(sCText);
                                SendMessageToDMAdmins(sCText);
                            }
                            else if (sSort == SERVER_2_IP)
                            {
                                sTarget = "INSERT INTO messages (server,name,message) VALUES ('" + SERVER_1_IP + "','DM','" + sCText + "'),('" + SERVER_3_IP + "','DM','" + sCText + "')";
                                SQLExecDirect(sTarget);
                                FloatingTextStringOnCreature("<c þ >DM Message sent to all servers!</c>", oCPC);
                                SQLDecodeSpecialChars(sCText);
                                SendMessageToPCDMs(sCText);
                                SendMessageToPCAdmins(sCText);
                                SendMessageToDMDMs(sCText);
                                SendMessageToDMAdmins(sCText);
                            }
                            else if (sSort == SERVER_3_IP)
                            {
                                sTarget = "INSERT INTO messages (server,name,message) VALUES ('" + SERVER_1_IP + "','DM','" + sCText + "'),('" + SERVER_2_IP + "','DM','" + sCText + "')";
                                SQLExecDirect(sTarget);
                                FloatingTextStringOnCreature("<c þ >DM Message sent to all servers!</c>", oCPC);
                                SQLDecodeSpecialChars(sCText);
                                SendMessageToPCDMs(sCText);
                                SendMessageToPCAdmins(sCText);
                                SendMessageToDMDMs(sCText);
                                SendMessageToDMAdmins(sCText);
                            }
                            else
                                FloatingTextStringOnCreature(COLOR_RED+"IP error! Message could not be sent!" + COLOR_END, oCPC);
                        }
                    }
                }


Insert this into fky_chat_inc, in the HandleCommands function, in the 's' case, after the 'else if (GetStringLeft(sCText, 2) == "sk") CommandRedirect(oCPC, 3);' if bracket. If you haven't modified SIMTools and have added the above consts and code for dm messages it should be around line 2417 of that script (it varies between Lin and Win versions).

Code:

                else if (GetStringLeft(sCText, 6) == "shout ")
                {
                    if (GetLocalInt(oCPC, "FKY_CHT_BANSHOUT"))//check for shout ban
                        FloatingTextStringOnCreature(COLOR_RED+"You are banned from shout channel and may not send interserver shout messages."+COLOR_END, oCPC, FALSE);
                    else
                    {
                        sCText = GetStringRight(sCText, GetStringLength(sCText) - 6);
                        sCText = "[Shout from " + GetPCPlayerName(oCPC) + "] " + sCText;
                        if (GetStringLength(sCText) > 255)
                            FloatingTextStringOnCreature(COLOR_RED+"Combined header and message over 255 characters! Message could not be sent!" + COLOR_END, oCPC);
                        else
                        {
                            sCText = SQLEncodeSpecialChars(sCText);
                            sSort = GetLocalString(GetModule(), "ServerIP");
                            if (sSort == SERVER_1_IP)
                            {
                                sTarget = "INSERT INTO messages (server,name,message) VALUES ('" + SERVER_2_IP + "','Shout','" + sCText + "'),('" + SERVER_3_IP + "','Shout','" + sCText + "')";
                                SQLExecDirect(sTarget);
                                FloatingTextStringOnCreature("<c þ >Shout Message sent to all servers!</c>", oCPC);
                                AssignCommand(GetModule(), SpeakString(SQLDecodeSpecialChars(sCText), TALKVOLUME_SHOUT));
                            }
                            else if (sSort == SERVER_2_IP)
                            {
                                sTarget = "INSERT INTO messages (server,name,message) VALUES ('" + SERVER_1_IP + "','Shout','" + sCText + "'),('" + SERVER_3_IP + "','Shout','" + sCText + "')";
                                SQLExecDirect(sTarget);
                                FloatingTextStringOnCreature("<c þ >Shout Message sent to all servers!</c>", oCPC);
                                AssignCommand(GetModule(), SpeakString(SQLDecodeSpecialChars(sCText), TALKVOLUME_SHOUT));
                            }
                            else if (sSort == SERVER_3_IP)
                            {
                                sTarget = "INSERT INTO messages (server,name,message) VALUES ('" + SERVER_1_IP + "','Shout','" + sCText + "'),('" + SERVER_2_IP + "','Shout','" + sCText + "')";
                                SQLExecDirect(sTarget);
                                FloatingTextStringOnCreature("<c þ >Shout Message sent to all servers!</c>", oCPC);
                                AssignCommand(GetModule(), SpeakString(SQLDecodeSpecialChars(sCText), TALKVOLUME_SHOUT));
                            }
                            else
                                FloatingTextStringOnCreature(COLOR_RED+"IP error! Message could not be sent!" + COLOR_END, oCPC);
                        }
                    }
                }


Insert this into fky_chat_inc, in the HandleCommands function, in the 't' case, after the 'if (sCText == "target")' if bracket. If you haven't modified SIMTools and have added the above consts and code for dm and shout messages it should be around line 2509 of that script (it varies between Lin and Win versions).

Code:

                else if (GetStringLeft(sCText, 5) == "tell ")
                {
                    sCText = GetStringRight(sCText, GetStringLength(sCText) - 5);
                    sKey = GetLocalString(GetModule(), "Quote");
                    if (GetStringLeft(sCText, 1) == sKey)//they have a quote demarcating playername
                    {
                        sCText = GetStringRight(sCText, GetStringLength(sCText) - 1);
                        nText = FindSubString(sCText, sKey);
                        sPlayer = GetStringLeft(sCText, nText);
                        sPlayer = SQLEncodeSpecialChars(sPlayer);
                        sPlayer = "FKY_" + sPlayer;//this prefix prevents nuisance players naming themselves Shout or DM
                        sCText = GetStringRight(sCText, GetStringLength(sCText) - nText - 1);
                        if (GetStringLeft(sCText, 1) == " ")
                            sCText = GetStringRight(sCText, GetStringLength(sCText) - 1);
                    }
                    else //playename is seperated by spaces
                    {
                        while (GetStringLeft(sCText, 1) == " ")
                        {
                            sCText = GetStringRight(sCText, GetStringLength(sCText) - 1);
                        }
                        nText = FindSubString(sCText, " ");
                        if (nText == -1)
                        {
                            FloatingTextStringOnCreature(COLOR_RED+"Addressee must have a space between their name and the message or be placed between double quotes! Message could not be sent!" + COLOR_END, oCPC);
                        }
                        sPlayer = GetStringLeft(sCText, nText);
                        sPlayer = SQLEncodeSpecialChars(sPlayer);
                        sPlayer = "FKY_" + sPlayer;//this prefix prevents nuisance players naming themselves Shout or DM
                        sCText = GetStringRight(sCText, GetStringLength(sCText) - nText - 1);
                    }
                    if (GetStringLength(sCText) > 255)
                    {
                        FloatingTextStringOnCreature(COLOR_RED+"Message over 255 characters! Message could not be sent!" + COLOR_END, oCPC);
                    }
                    else
                    {
                        sInvite = GetPCPlayerName(oCPC);
                        sInvite = SQLEncodeSpecialChars(sInvite);
                        sSort = GetLocalString(GetModule(), "ServerIP");
                        sCText = SQLEncodeSpecialChars(sCText);
                        if (sSort == SERVER_1_IP)
                        {
                            sTarget = "INSERT INTO messages (server,name,sender,message) VALUES ('" + SERVER_2_IP + "','" + sPlayer + "','" + sInvite + "','" + sCText + "'),('" + SERVER_3_IP + "','" + sPlayer + "','" + sInvite + "','" + sCText + "')";
                            SQLExecDirect(sTarget);
                            FloatingTextStringOnCreature("<c þ >Message sent to " + SQLDecodeSpecialChars(sPlayer) + "!</c>", oPC);
                        }
                        else if (sSort == SERVER_2_IP)
                        {
                            sTarget = "INSERT INTO messages (server,name,sender,message) VALUES ('" + SERVER_1_IP + "','" + sPlayer + "','" + sInvite + "','" + sCText + "'),('" + SERVER_3_IP + "','" + sPlayer + "','" + sInvite + "','" + sCText + "')";
                            SQLExecDirect(sTarget);
                            FloatingTextStringOnCreature("<c þ >Message sent to " + SQLDecodeSpecialChars(sPlayer) + "!</c>", oPC);
                        }
                        else if (sSort == SERVER_3_IP)
                        {
                            sTarget = "INSERT INTO messages (server,name,sender,message) VALUES ('" + SERVER_1_IP + "','" + sPlayer + "','" + sInvite + "','" + sCText + "'),('" + SERVER_2_IP + "','" + sPlayer + "','" + sInvite + "','" + sCText + "')";
                            SQLExecDirect(sTarget);
                            FloatingTextStringOnCreature("<c þ >Message sent to " + SQLDecodeSpecialChars(sPlayer) + "!</c>", oPC);
                        }
                        else
                            FloatingTextStringOnCreature(COLOR_RED+"IP error! Message could not be sent!" + COLOR_END, oCPC);
                    }
                }


This gives you three commands. !dm [message] will send the message to all dms on all servers. !shout [message] will shout the message on all servers. !tell [playername] [message] will send a tell to that person (though they will only receive it if they are currently online). You can send tells to players with spaces in their playernames by surrounding the playername in double quotes -without them it'll misread playernames with spaces in them. LMK if you have any questions. Examples:

!tell FunkySwerve hi
!tell "FunkySwerve" hi
!tell "avatar of shadows" come to server x!
!shout doing a lolth run on server y
!dm please lend a hand, I'm stuck in a wall

Funky
Back to top
View user's profile Send private message
Tempest



Joined: 26 Feb 2008
Posts: 32

PostPosted: Thu May 22, 2008 21:44    Post subject: Reply with quote

Thank you again FS, this will really come in handy!!!

"T"
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
Tempest



Joined: 26 Feb 2008
Posts: 32

PostPosted: Mon Jun 02, 2008 20:22    Post subject: Reply with quote

Okay FS need some help from you again. In your instructions it says to not include port numbers and we should only use IP's of the servers hosting the instances. In my case all 4 of our instances are on the same machine. Is it okay to use the same IP of that one machine with the corosponding port numbers?

Thanks..... "T"
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
Display posts from previous:   
Post new topic   Reply to topic    nwnx.org Forum Index -> General Discussion All times are GMT + 2 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group