Network insanity
by Michael Perry · in Torque Game Engine · 03/26/2007 (6:00 am) · 8 replies
Hey all. So I've been working with the network code for a while, and I've managed to get some results, even if they are insane. I could use some help with a couple of bugs, though. . .
Goal:
We have client A and client B. Client A moves forward a certain amount. His information (ID, velocity, position) is packaged and sent to my new UDP socket for transmission. When client B receives the transmission, he checks to see if client A's entity exists (Sim::findObject(id)). If not, he spawns a new AIPlayer and then updates the movement. The problem is, client A is getting the same transmission, creating an AIPlayer and moving him...at this point the IDs are the same and movement gets all mucked up.
So. . .any suggestions on what to look for? If there are specific questions about the code, let me know. Trying to post the whole system here would take too much space, so asking for something specific will allow me to post only what's needed. . .
Goal:
- Create second UDP socket, which broadcasts and receives[li]Send special data and events through new socket, without interfering with default Torque game network
- UDP socket created, initialized, and given its own methods (openPort, closePort, sendTo)[li]Socket broadcasts[li]Socket receives[li]Default Torque game network still works
- When machine A broadcasts a packet, the packet is received by machine B and C, but A gets it back as well, causing unwanted duplication of events[li]Ghosting architecture is causing duplicate events to be created
We have client A and client B. Client A moves forward a certain amount. His information (ID, velocity, position) is packaged and sent to my new UDP socket for transmission. When client B receives the transmission, he checks to see if client A's entity exists (Sim::findObject(id)). If not, he spawns a new AIPlayer and then updates the movement. The problem is, client A is getting the same transmission, creating an AIPlayer and moving him...at this point the IDs are the same and movement gets all mucked up.
So. . .any suggestions on what to look for? If there are specific questions about the code, let me know. Trying to post the whole system here would take too much space, so asking for something specific will allow me to post only what's needed. . .
About the author
Programmer.
#2
All jokes aside, can PyTGE handle UDP and broadcast capabilities? I have to be very specific with this network protocol.
03/26/2007 (5:08 pm)
Thanks very much Bryce. I'm looking into PyTGe. While I have never mentioned it in the forums, I am a Python fanatic and at one point tried to integrate it into everything I did.....I even have a python sticker on my fridge in hopes of future integration =)All jokes aside, can PyTGE handle UDP and broadcast capabilities? I have to be very specific with this network protocol.
#3
Twisted (twistedmatrix.com) is the key. Utilizing their network framework you get a robust, cross platform networking toolkit. Honestly the hardest part of implementing this for your project should be removing the features you don't need.
EDIT: Every time Python/Torque is mentioned I have to add that TorqueScript should be scrapped in favor of Python. :)
03/27/2007 (3:48 pm)
PyTGE is the wrapper for the Python interpreter. We use Python 2.5 integrated with Torque and it utilizes the Twisted framework for non-game network communications.Twisted (twistedmatrix.com) is the key. Utilizing their network framework you get a robust, cross platform networking toolkit. Honestly the hardest part of implementing this for your project should be removing the features you don't need.
EDIT: Every time Python/Torque is mentioned I have to add that TorqueScript should be scrapped in favor of Python. :)
#4
*EDIT* - And 10 seconds later I found it...I think... TGEPython?
It's a 2002 resource, which makes me wonder if there is a more updated resource out there.
03/28/2007 (6:47 am)
So, I may be having a bad day with my searching capabilities, but how does one obtain PyTGE to try out?*EDIT* - And 10 seconds later I found it...I think... TGEPython?
It's a 2002 resource, which makes me wonder if there is a more updated resource out there.
#5
We'll be putting up some additional Python resources at http://www.mmoworkshop.com when the opportunity presents itself :)
-Prairie Games, Inc
03/28/2007 (6:52 am)
Look here: http://www.garagegames.com/mg/forums/result.thread.php?qt=47546We'll be putting up some additional Python resources at http://www.mmoworkshop.com when the opportunity presents itself :)
-Prairie Games, Inc
#6
In the mean time, I can't just leave bugged code in or walk away from what I have currently (that drives me insane). So if someone wants to weigh in on posted bugs, all are welcome and thanks in advance. . .
03/28/2007 (6:57 am)
Thanks for providing that option guys. I'm looking into it now and getting the proposal together.In the mean time, I can't just leave bugged code in or walk away from what I have currently (that drives me insane). So if someone wants to weigh in on posted bugs, all are welcome and thanks in advance. . .
#7
03/28/2007 (8:01 am)
Could you not just use the same socket and still get your feature going?
#8
In engine\platformWin32\winNet.cc:
Game->postEvent(receiveEvent) still needs to be called to process a lot of normal Torque ops. Operating with only one udpSocket, means I would have to perform the code found in the bold section. This caused some issues, so I came up with this:
This way I can transmit special and weird data on a separate port without interfering with the standard Net::process and the UDP socket it deals with.
03/28/2007 (8:35 am)
I tried at first, but there were some issues with implementation:In engine\platformWin32\winNet.cc:
void Net::process()
{
PacketReceiveEvent receiveEvent;
for(;;)
{
S32 addrLen = sizeof(sa);
S32 bytesRead = SOCKET_ERROR;
if(udpSocket != INVALID_SOCKET)
bytesRead = recvfrom(udpSocket, (char *) receiveEvent.data, MaxPacketDataSize, 0, &sa, &addrLen);
if(bytesRead == SOCKET_ERROR && ipxSocket != INVALID_SOCKET)
{
addrLen = sizeof(sa);
bytesRead = recvfrom(ipxSocket, (char *) receiveEvent.data, MaxPacketDataSize, 0, &sa, &addrLen);
}
if(bytesRead == SOCKET_ERROR)
break;
if(sa.sa_family == AF_INET)
IPSocketToNetAddress((SOCKADDR_IN *) &sa, &receiveEvent.sourceAddress);
else if(sa.sa_family == AF_IPX)
IPXSocketToNetAddress((SOCKADDR_IPX *) &sa, &receiveEvent.sourceAddress);
else
continue;
NetAddress &na = receiveEvent.sourceAddress;
if(na.type == NetAddress::IPAddress &&
na.netNum[0] == 127 &&
na.netNum[1] == 0 &&
na.netNum[2] == 0 &&
na.netNum[3] == 1 &&
na.port == netPort)
continue;
if(bytesRead <= 0)
continue;
receiveEvent.size = PacketReceiveEventHeaderSize + bytesRead;
Game->postEvent(receiveEvent);
[b] Game->postSpecialEvent(receiveEvent); // This just seems to muck a lot of stuff[/b]
}Game->postEvent(receiveEvent) still needs to be called to process a lot of normal Torque ops. Operating with only one udpSocket, means I would have to perform the code found in the bold section. This caused some issues, so I came up with this:
static SOCKET MySocket = INVALID_SOCKET;
void Net::processSpecial()
{
SOCKADDR sa;
PacketReceiveEvent receiveEvent;
for(;;)
{
S32 addrLen = sizeof(sa);
S32 bytesRead = SOCKET_ERROR;
if([b]MySocket[/b] != INVALID_SOCKET)
bytesRead = recvfrom([b]MySocket[/b], (char *) receiveEvent.data, MaxPacketDataSize, 0, &sa, &addrLen);
if(bytesRead == SOCKET_ERROR)
break;
if(sa.sa_family == AF_INET)
IPSocketToNetAddress((SOCKADDR_IN *) &sa, &receiveEvent.sourceAddress);
else if(sa.sa_family == AF_IPX)
IPXSocketToNetAddress((SOCKADDR_IPX *) &sa, &receiveEvent.sourceAddress);
else
continue;
NetAddress &na = receiveEvent.sourceAddress;
if(na.type == NetAddress::IPAddress &&
na.netNum[0] == 127 &&
na.netNum[1] == 0 &&
na.netNum[2] == 0 &&
na.netNum[3] == 1 &&
na.port == netPort)
continue;
if(bytesRead <= 0)
continue;
receiveEvent.size = PacketReceiveEventHeaderSize + bytesRead;
[b]Game->postSpecialEvent(receiveEvent);[/b]
}
}This way I can transmit special and weird data on a separate port without interfering with the standard Net::process and the UDP socket it deals with.
Torque Owner Bryce "Cogburn" Weiner
Not to sound like a broken record, but I'd recommend PyTGE and a nice layer of Python w/ Twisted for your non-server communications. You could setup a port listener to fire Torque function calls based on the datagrams received. This not only keeps it completely insulated from the game network connections, but also exposes the full power of Twisted networking for your processing (did this packet come from me?).