Chat in Panda3D

I want to create a chat in panda3D. How do I do this?

Thank you.

Well, you should be a little more specific before you expect someone to answer your problem like you intended.
But to answer your question as best I can, I’d reccommend using a library besides Panda to implement a chatting backend. Perhaps Twisted or asynchat would help.

why would someone suggesting to use 3rd party libs when panda comes with a complete networking stack?

anyway, the manual provides valuable information on how to send data over the network.
panda3d.org/manual/index.php/Networking
for a complete chat you also need the DirectScrolledList and a DirectEntry for typing.

I suggested asynchat as it’s in the Python Standard Library, as well as being substantially simpler than Panda’s networking API. I suggested Twisted as it’s also a popular choice, and probably offers better performance than anything Panda has to offer.

Nothing against Panda’s networking stack, just an opinion…

Thanks for your responses.

I found the next code, but there’s an error.

I have windows 7 home premium 64 bits

Client Side. The error is in this part.

from direct.showbase.DirectObject import DirectObject    

from pandac.PandaModules import ConfigVariableString 
ConfigVariableString("window-type", "none").setValue("none") 
import direct.directbase.DirectStart 
from direct.task import Task 
from pandac.PandaModules import QueuedConnectionManager, QueuedConnectionReader, ConnectionWriter, QueuedConnectionListener 
from direct.distributed.PyDatagram import PyDatagram 
from direct.distributed.PyDatagramIterator import PyDatagramIterator 

class Client(DirectObject): 
    def __init__( self ): 
        print "Initializing client test" 
        
        self.port = 9099 
        self.ip_address = "localhost" 
        self.timeout = 3000             # 3 seconds to timeout 
        
        self.cManager = QueuedConnectionManager() 
        self.cListener = QueuedConnectionListener(self.cManager, 0) 
        self.cReader = QueuedConnectionReader(self.cManager, 0) 
        self.cWriter = ConnectionWriter(self.cManager,0) 
        
        self.Connection = self.cManager.openTCPClientConnection(self.ip_address, self.port, self.timeout) 
        if self.Connection: 
            taskMgr.add(self.tskReaderPolling,"read the connection listener",-40) 
            # this tells the client to listen for datagrams sent by the server 
            
            print "Connected to Server" 
            self.cReader.addConnection(self.Connection) 
            PRINT_MESSAGE = 1 
            myPyDatagram = PyDatagram() 
            myPyDatagram.addUint8(100) 
            # adds an unsigned integer to your datagram 
            myPyDatagram.addString("first string of text") 
            # adds a string to your datagram 
            myPyDatagram.addString("second string of text") 
            # adds a second string to your datagram 
            self.cWriter.send(myPyDatagram, self.Connection) 
            # fires it off to the server 
            
            #self.cManager.closeConnection(self.Connection) 
            #print "Disconnected from Server" 
            # uncomment the above 2 lines if you want the client to 
            # automatically disconnect.  Or you can just 
            # hit CTRL-C twice when it's running to kill it 
            # in windows, I don't know how to kill it in linux 
        else: 
            print "Not connected to Server" 
        
    def tskReaderPolling(self, task): 
        if self.cReader.dataAvailable(): 
            datagram=PyDatagram()  
            if self.cReader.getData(datagram): 
                self.processServerMessage(datagram) 
        return Task.cont        
    
    def processServerMessage(self, netDatagram): 
        myIterator = PyDatagramIterator(netDatagram) 
        print myIterator.getString() 
        
Client = Client() 
run() 

SERVER SIDE

from direct.showbase.DirectObject import DirectObject  
from direct.task import Task 
from pandac.PandaModules import ConfigVariableString 
ConfigVariableString("window-type", "none").setValue("none") 
import direct.directbase.DirectStart 
# These are the  Panda libraries needed for everything else 
# to function properly.  The configvariable bit disables the 
# standard window that opens, as the server doesn't need to continually 
# re-draw a window - it just needs to to output to the command prompt 

from panda3d.core import * 

from pandac.PandaModules import QueuedConnectionManager, QueuedConnectionReader, ConnectionWriter, QueuedConnectionListener, NetAddress 
from direct.distributed.PyDatagram import PyDatagram 
from direct.distributed.PyDatagramIterator import PyDatagramIterator 
# panda's built-in networking code for TCP networking 

class Server(DirectObject): 
    def __init__( self ): 
        self.port = 9099 
        self.portStatus = "Closed" 
        self.host = "localhost" 
        self.backlog = 1000 
        self.Connections = {} 
        # basic configuration variables that are used by most of the 
        # other functions in this class 

        self.StartConnectionManager() 
        # manages the connection manager 
        
        self.DisplayServerStatus() 
        # output a status box to the console which tells you the port 
        # and any connections currently connected to your server 
        
    def DisplayServerStatusTASK(self, task): 
        # all this does is periodically load the status function below 
        # add a task to display it every 30 seconds while you are doing 
        # any new coding 
        self.DisplayServerStatus() 
        return Task.again 
    
    def DisplayServerStatus(self): 
        print "\n----------------------------------------------------------------------------\n" 
        print "SERVER STATUS:\n\n" 
        print "Connection Manager Port: " + str(self.port)  + " [" + str(self.portStatus) + "]" 
        for k, v in self.Connections.iteritems(): 
            print "Connection " + k 

    ################################################################## 
    #              TCP Networking Functions and Tasks 
    ################################################################## 
        
    def StartConnectionManager(self): 
        # this function creates a connection manager, and then 
        # creates a bunch of tasks to handle connections 
        # that connect to the server 
        self.cManager = QueuedConnectionManager() 
        self.cListener = QueuedConnectionListener(self.cManager, 0) 
        self.cReader = QueuedConnectionReader(self.cManager, 0) 
        self.cWriter = ConnectionWriter(self.cManager,0) 
        self.tcpSocket = self.cManager.openTCPServerRendezvous(self.port,self.backlog)
        self.cListener.addConnection(self.tcpSocket) 
        self.portStatus = "Open" 
        taskMgr.add(self.ConnectionManagerTASK_Listen_For_Connections,"Listening for Connections",-39) 
        # This task listens for new connections 
        taskMgr.add(self.ConnectionManagerTASK_Listen_For_Datagrams,"Listening for Datagrams",-40) 
        # This task listens for new datagrams 
        taskMgr.add(self.ConnectionManagerTASK_Check_For_Dropped_Connections,"Listening for Disconnections",-41) 
        # This task listens for disconnections 
        
    def ConnectionManagerTASK_Listen_For_Connections(self, task): 
        if(self.portStatus == "Open"): 
        # This exists in case you want to add a feature to disable your 
        # login server for some reason.  You can just put code in somewhere 
        # to set portStatus = 'closed' and your server will not 
        # accept any new connections 
            if self.cListener.newConnectionAvailable(): 
                print "CONNECTION" 
                rendezvous = PointerToConnection() 
                netAddress = NetAddress() 
                newConnection = PointerToConnection() 
                if self.cListener.getNewConnection(rendezvous,netAddress,newConnection): 
                    newConnection = newConnection.p() 
                    self.Connections[str(newConnection.this)] = rendezvous 
                    # all connections are stored in the self.Connections 
                    # dictionary, which you can use as a way to assign 
                    # unique identifiers to each connection, making 
                    # it easy to send messages out 
                    self.cReader.addConnection(newConnection)    
                    print "\nSOMEBODY CONNECTED" 
                    print "IP Address: " + str(newConnection.getAddress()) 
                    print "Connection ID: " + str(newConnection.this) 
                    print "\n" 
                    # you can delete this, I've left it in for debugging 
                    # purposes 
                    self.DisplayServerStatus()                
                    # this fucntion just outputs the port and 
                    # current connections, useful for debugging purposes 
        return Task.cont  

    def ConnectionManagerTASK_Listen_For_Datagrams(self, task): 
        if self.cReader.dataAvailable(): 
            datagram=NetDatagram()  
            if self.cReader.getData(datagram): 
                print "\nDatagram received, sending response" 
                myResponse = PyDatagram() 
                myResponse.addString("GOT YER MESSAGE") 
                self.cWriter.send(myResponse, datagram.getConnection()) 
                # this was just testing some code, but the server will 
                # automatically return a 'GOT YER MESSAGE' datagram 
                # to any connection that sends a datagram to it 
                # this is where you add a processing function here 
                #myProcessDataFunction(datagram) 
        return Task.cont 

    def ConnectionManagerTASK_Check_For_Dropped_Connections(self, task): 
        # if a connection has disappeared, this just does some house 
        # keeping to officially close the connection on the server, 
        # if you don't have this task the server will lose track 
        # of how many people are actually connected to you 
        if(self.cManager.resetConnectionAvailable()): 
            connectionPointer = PointerToConnection() 
            self.cManager.getResetConnection(connectionPointer) 
            lostConnection = connectionPointer.p() 
            # the above pulls information on the connection that was lost 
            print "\nSOMEBODY DISCONNECTED" 
            print "IP Address: " + str(lostConnection.getAddress()) 
            print "ConnectionID: " + str(lostConnection.this) 
            print "\n" 
            del self.Connections[str(lostConnection.this)] 
            # remove the connection from the dictionary 
            self.cManager.closeConnection(lostConnection) 
            # kills the connection on the server 
            self.DisplayServerStatus() 
        return Task.cont 
  

Server = Server() 
run() 

The error is the next

DirectStart: Starting the game. 
Initializing client test 
Connected to Server 
Assertion failed: _current_index < _datagram->get_length() at line 199 of c:\bui 
ldslave\dev_sdk_win32\build\panda3d\panda\src\express\datagramIterator.I 
Traceback (most recent call last): 
  File "c:/proyectos/ej2.py", line 65, in tskReaderPolling 
    self.processServerMessage(datagram) 
  File "c:/proyectos/ej2.py", line 72, in processServerMessage 
    print myIterator.getString() 
AssertionError: _current_index < _datagram->get_length() at line 199 of c:\build 
slave\dev_sdk_win32\build\panda3d\panda\src\express\datagramIterator.I 
:task(error): Exception occurred in PythonTask read the connection listener 
Traceback (most recent call last): 
  File "c:/proyectos/ej2.py", line 78, in <module> 
    run() 
  File "C:\Program Files (x86)\Panda3D-1.8.0\direct\showbase\ShowBase.py", line 
2630, in run 
    self.taskMgr.run() 
  File "C:\Program Files (x86)\Panda3D-1.8.0\direct\task\Task.py", line 502, in 
run 
    self.step() 
  File "C:\Program Files (x86)\Panda3D-1.8.0\direct\task\Task.py", line 460, in 
step 
    self.mgr.poll() 
  File "c:/proyectos/ej2.py", line 65, in tskReaderPolling 
    self.processServerMessage(datagram) 
  File "c:/proyectos/ej2.py", line 72, in processServerMessage 
    print myIterator.getString() 
AssertionError: _current_index < _datagram->get_length() at line 199 of c:\build 
slave\dev_sdk_win32\build\panda3d\panda\src\express\datagramIterator.I 

tho code works well for me. ubuntu 10.04_64. any chance windwos ‘advanced security’ features are interfering?

I checked the firewall, this code if it works in windows xp, but not it works in windows 7. Do you have some idea? :open_mouth:

thanks