Need suggestions about Real-Time chat between sa-mp server and a web application
#1

Has someone ever did that? I mean.. has someone ever did that in the best way possible?


I know there are plenty of ways to do that.. like using php & ajax, flash or JSP, but they are not so easy to do and you can't use it inside a Symfony (PHP Framework) website for example, so I think the best solution is to do that via nodejs using socket.io library.

What I got so far:
[ame]http://www.youtube.com/watch?v=AK2Ofj6m2Vk[/ame]

Sorry about the poor video quality, it is very hard to record two screens at the same time! just put it in 1080p and maximize the video to see all details.

Problems using nodejs:
- The socket between nodejs and web application has to be TCP.
- The socket between nodejs and sa-mp server has to be UDP (I tried to make it TCP but onSocketReceiveData callback is not called for some reason and the socket loose connection while GMX, I made contact with BlueG about these problems but got no response so far).
- By using UDP socket I have to create both client and server in my gamemode and nodejs server, using two different ports (one for sending data, another to receive data). I don't think it is a good solution for that problem.

Besides these problems the application works great! I just wonder if someone have any suggestion to turn it better, I think it still can be written in a better way.




My solution so far:

Nodejs server:
Код:
var sys =       require("sys");
var http =      require("http");
var fs =        require("fs");
var express =   require('express');
var url =       require("url");
var path =      require("path");
var net =       require('net');
var dgram =     require('dgram');
var localIp =   'changeme';
var sampPort =  7778;
var sampSock =  new net.Socket();
var sampUdpClient = dgram.createSocket('udp4');

var homepath = __dirname + '/node_modules/socket.io/';

/**
 * Websockets para o Brazuca's UCP
 * @type {*}
 */
var webchatSocket = http.createServer(
    function(req, res) {
        var uri = url.parse(req.url).pathname;
        var filepath = path.join(homepath, uri);

        fs.readFile(filepath,
        function(err, data) {
            if(err) {
                res.writeHead(500);
                return res.end('Erro ao carregar');
            }

            res.writeHead(200);
            res.end(data);
	    });
    }
);

var io =  require("socket.io").listen(webchatSocket);

io.sockets.on('connection', function(socket) {
    socket.on('chatMessage', function(data) {
        var message = new Buffer('a=msg&msg='+data.message+'\r\n');
        sampUdpClient.send(message, 0, message.length, sampPort, localIp);

        io.sockets.emit('chatMessage', data);
        console.log('>> '+ data);
    });
});

webchatSocket.listen(4000);
/** ********************************************* **/

/**
 * Conexгo UDP com o servidor sa-mp do Brazuca's
 * @type {Socket}
 */
var message = new Buffer('hw');
sampUdpClient.send(message, 0, message.length, sampPort, localIp);

var server = dgram.createSocket('udp4');
server.on('listening', function () {
    var address = server.address();
    console.log('UDP Server listening on ' + address.address + ":" + address.port);
});

server.on('message', function (message, remote) {
    var sampData = filterSampSocketData(message);

    console.log(sampData);

    if(sampData['msg'] !== undefined) {
        console.log('Comando do tipo Mensagem: '+sampData['msg']);
        io.sockets.emit('chatMessage', {message: sampData['msg'].replace(/\+/g, ' ')});
    }
});

server.bind(7779, localIp);
/** ***************************************** **/

/**
 * Utils
 */
function filterSampSocketData(data) {
    var sampData = data.toString().split("&");
    var data = new Array();

    for(x in sampData) {
        var indVal = sampData[x].split("=");

        data[indVal[0]] = indVal[1];
    }

    return data;
}
/** ******************************************* **/

sys.puts('Servidor nodejs iniciado.');
Webchat client:
Код:
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>

        <script src="/public/jquery-2.1.1.min.js"></script>
        <script src="/socket.io/socket.io.js"></script>
        <script>
            $(document).ready(function() {
                var msg = $("#mensagem");

                var socket = io.connect('198.211.116.169:4000');
                socket.on('chatMessage', function(data) {
                    var chatPanel =     $("#chatPanel");
                    var chatWrapper =   $('#chatWrapper');

                    chatWrapper.append(data.message + "<br />");

                    var scroll = chatPanel.hasClass('atBottom');

                    if(scroll) {
                        var height = chatWrapper.height();
                        chatPanel.scrollTop(height);
                    }
                });

                function sendMessage() {
                    if(msg.val().length > 0) {
                        socket.emit('chatMessage', {message: msg.val()});

                        msg.val('');
                        msg.focus();
                    }
                }

                $("#chatForm").submit(function(e) {
                    sendMessage();
                    e.preventDefault();
                });

                msg.focus();
            });
        </script>
    </head>

    <body>
        <h2>Webchat em tempo real (protуtipo)</h2>
        <form method="POST" action="" id="chatForm">
            <div style="border: 1px solid #eee; width: 400px; height: 200px; overflow: auto;" class="atBottom" id="chatPanel">
                <div id="chatWrapper"></div>
            </div>

            <input type="text" id="mensagem" style="width: 350px;"/>
            <input type="submit" value="Enviar"/>
        </form>
    </body>
</html>
Gamemode .pwn:
pawn Код:
// This is a comment
// uncomment the line below if you want to write a filterscript
//#define FILTERSCRIPT

#include <a_samp>
#include <a_http>
#include <strlib>
#include <sockets>

new
    port,
    Socket:sock,
    Socket:nodejsSock,
    ipLocal[64],
    tInds[20][128],
    tVals[20][128]
;

main() {
    format(ipLocal, sizeof(ipLocal), "changeme");
    //port = GetServerVarAsInt("port");

    // Servidor UDP
    sock = socket_create(UDP);

    socket_bind(sock, ipLocal);
    socket_listen(sock, 7778);

    printf("Servidor UDP lendo no ip %s porta 7778", ipLocal);

    return 1;
}

public OnGameModeInit()
{

    SetGameModeText("Blank Script");

    return 1;
}

public OnGameModeExit()
{
    //socket_destroy(sock);
   
    return 1;
}

public OnPlayerRequestClass(playerid, classid)
{
    SetPlayerPos(playerid, 1958.3783, 1343.1572, 15.3746);
    SetPlayerCameraPos(playerid, 1958.3783, 1343.1572, 15.3746);
    SetPlayerCameraLookAt(playerid, 1958.3783, 1343.1572, 15.3746);
    return 1;
}

public OnPlayerConnect(playerid)
{
    return 1;
}

public OnPlayerDisconnect(playerid, reason)
{
    return 1;
}

public OnPlayerText(playerid, text[]) {
    new sockCmd[64];

    format(sockCmd, sizeof(sockCmd), "msg=%s", text);
    cmd(sockCmd);

    return 1;
}

public OnPlayerCommandText(playerid, cmdtext[])
{
    if (strcmp("/mycommand", cmdtext, true, 10) == 0)
    {
        // Do something here
        return 1;
    }
    return 0;
}
// ------------------------------------------------------------------------------------------------------------------------------------------------------------- //
public onSocketAnswer(Socket:id, data[], data_len) {
    printf("testesadasdas");

    return 1;
}
// ------------------------------------------------------------------------------------------------------------------------------------------------------------- //
public onSocketRemoteConnect(Socket:id, remote_client[], remote_clientid) {
    printf("Nova conexгo estabelecida atravйs do IP %s", remote_client);

    return 1;
}

public onSocketReceiveData(Socket:id, remote_clientid, data[], data_len) {
    printf("Comando recebido do cliente %d: %s", remote_clientid, data);

    return 1;
}

public onUDPReceiveData(Socket:id, data[], data_len, remote_client_ip[], remote_client_port) {
    new buffer[128];

    printf("onUDPReceiveData: %s %d %s %d", data, data_len, remote_client_ip, remote_client_port);
   
    if(strcmp(data, "hw", false) == 0) {
        // Cliente UDP
        nodejsSock = socket_create(UDP);

        socket_connect(nodejsSock, ipLocal, 7779);
        print("Conectado ao servidor UDP porta 7779");
    } else {
        tratar(data);
       
        if(strcmp(GET("a"), "msg", true) == 0) {
            format(buffer, sizeof(buffer), "[WebChat] %s", GET("msg"));
       
            SendClientMessageToAll(0xFFFFFFFF, buffer);
        }
    }
   
    return 1;
}
// ------------------------------------------------------------------------------------------------------------------------------------------------------------- //
public onSocketClose(Socket:id) {
    print("teste");
}
// ------------------------------------------------------------------------------------------------------------------------------------------------------------- //
forward cmd(str[]);
public cmd(str[]) {
    new cd[600];

    if(strlen(str) > 0) {
        format(cd, sizeof(cd), "%s&p=%d&t=server", str_replace(" ", "+", str), port);
        socket_send(nodejsSock, cd, strlen(cd));
        printf(">> %s", cd);
    }
}

forward tratar(parametros[]);
public tratar(parametros[]) {
    new vars[7][128], del[3][128], params[128];

    //A funзгo explode dб crash no server se vocк passar uma string recebida por parвmetro diretamente para a funзгo.
    format(params, sizeof(params), "%s", parametros);

    explode(vars, params, "&");
    for(new i = 0; i < sizeof(vars); ++i) {
        if(strfind(vars[i], "=", true) != -1) {
            explode(del, vars[i], "=");
            format(tInds[i], 128, "%s", del[0]);

            format(del[1], sizeof(del[]), "%s", str_replace("\r\n", "", del[1]));
            format(tVals[i], 128, "%s", del[1]);
        }
    }
}

stock GET(ind[]) {
    new result[128], i;

    i = 0;

    while(i < sizeof(tInds)) {
        if(strcmp(tInds[i], ind, false) == 0) {
            format(result, sizeof(result), "%s", tVals[i]);
            return result;
        }

        ++i;
    }

    return result;
}
// ------------------------------------------------------------------------------------------------------------------------------------------------------------- //
Reply
#2

I think this is not related to scripting help...
Reply
#3

Quote:
Originally Posted by Excel™
Посмотреть сообщение
I think this is not related to scripting help...
It is. You script a chat through the web
But the problem is that you can mainly ask stuff about pawn here, cause the most of us can't help you with any other scripting language.
that Nodejs server is something unknown to me.
same goes to the webchat client
the only thnig I know about is the Gamemode.pwn
Well, wait for someone else
Reply
#4

why u don't use https://sampwiki.blast.hk/wiki/HTTP send content from sa-mp server to web and use socket to send content from web to sa-mp server ?

sorry for my bad english
Reply
#5

if you know a little bit programing, you can try to install an IRC server wich will be related to the main Server (your SA:MP server) and a client that you will make.
but you need knowledges to make an IRC Client that will be related to you server.
Reply
#6

e Como coloca em VB.net 2010 ?
Reply


Forum Jump:


Users browsing this thread: