"""ServerRepository module: contains the ServerRepository class""" from PandaModules import * from ClusterMsgs import * from MsgTypes import * import DirectNotifyGlobal import DirectObject import Task # Cam offset handling is a little sloppy. The problem is that there is a # single arc used for both movement of the camera, and the offset of the # group. # Also, I'm not sure multiple camera-group configurations are working for the # cluster system. class ClusterServer(DirectObject.DirectObject): notify = DirectNotifyGlobal.directNotify.newCategory("ClusterServer") MSG_NUM = 2000000 def __init__(self,cameraGroup,camera): # Store information about the cluster's camera self.cameraGroup = cameraGroup self.camera = camera self.lens = camera.node().getLens() # Initialize camera offsets self.posOffset = Vec3(0,0,0) self.hprOffset = Vec3(0,0,0) # Create network layer objects self.lastConnection = None self.qcm = QueuedConnectionManager() self.qcl = QueuedConnectionListener(self.qcm, 0) self.qcr = QueuedConnectionReader(self.qcm, 0) self.cw = ConnectionWriter(self.qcm,0) port = base.config.GetInt("cluster-server-port",CLUSTER_PORT) self.tcpRendezvous = self.qcm.openTCPServerRendezvous(port, 1) self.qcl.addConnection(self.tcpRendezvous) self.msgHandler = MsgHandler(ClusterServer.MSG_NUM,self.notify) # Start cluster tasks self.startListenerPollTask() self.startReaderPollTask() def startListenerPollTask(self): taskMgr.add(self.listenerPollTask, "serverListenerPollTask",-40) def listenerPollTask(self, task): """ Task to listen for a new connection from the client """ # Run this task after the dataloop if self.qcl.newConnectionAvailable(): print "New connection is available" rendezvous = PointerToConnection() netAddress = NetAddress() newConnection = PointerToConnection() retVal = self.qcl.getNewConnection(rendezvous, netAddress, newConnection) if retVal: # Crazy dereferencing newConnection=newConnection.p() self.qcr.addConnection(newConnection) print "Got a connection!" self.lastConnection = newConnection else: self.notify.warning( "getNewConnection returned false") return Task.cont def startReaderPollTask(self): """ Task to handle datagrams from client """ # Run this task just after the listener poll task and dataloop taskMgr.add(self.readerPollTask, "serverReaderPollTask", -39) def readerPollTask(self, state): # Process all available datagrams while 1: (datagram, dgi,type) = self.msgHandler.nonBlockingRead(self.qcr) if type is CLUSTER_NONE: break else: handleDatagram(dgi, type) return Task.cont def handleDatagram(self, dgi, type): if type == CLUSTER_NONE: pass elif type == CLUSTER_EXIT: import sys sys.exit() elif type == CLUSTER_CAM_OFFSET: self.handleCamOffset(dgi) elif type == CLUSTER_CAM_FRUSTUM: self.handleCamFrustum(dgi) elif type == CLUSTER_CAM_MOVEMENT: self.handleCamMovement(dgi) elif type == CLUSTER_COMMAND_STRING: self.handleCommandString(dgi) else: self.notify.warning("Recieved unknown packet type:" % type) return type def handleCamOffset(self,dgi): x=dgi.getFloat32() y=dgi.getFloat32() z=dgi.getFloat32() h=dgi.getFloat32() p=dgi.getFloat32() r=dgi.getFloat32() self.notify.debug((' new offset=%f %f %f %f %f %f' % (x,y,z,h,p,r))) self.posOffset = Vec3(x,y,z) self.hprOffset = Vec3(h,p,r) def handleCamFrustum(self,dgi): focalLength=dgi.getFloat32() filmSize=(dgi.getFloat32(), dgi.getFloat32()) filmOffset=(dgi.getFloat32(),dgi.getFloat32()) self.notify.debug(' fl, fs, fo=%f, (%f, %f), (%f, %f)' % (focalLength, filmSize[0], filmSize[1], filmOffset[0], filmOffset[1])) self.lens.setFocalLength(focalLength) self.lens.setFilmSize(filmSize[0], filmSize[1]) self.lens.setFilmOffset(filmOffset[0], filmOffset[1]) def handleCamMovement(self,dgi): x=dgi.getFloat32() y=dgi.getFloat32() z=dgi.getFloat32() h=dgi.getFloat32() p=dgi.getFloat32() r=dgi.getFloat32() self.notify.debug((' new position=%f %f %f %f %f %f' % (x,y,z,h,p,r))) finalX = x + self.posOffset[0] finalY = y + self.posOffset[1] finalZ = z + self.posOffset[2] finalH = h + self.hprOffset[0] finalP = p + self.hprOffset[1] finalR = r + self.hprOffset[2] self.cameraGroup.setPosHpr(render,finalX,finalY,finalZ, finalH,finalP,finalR) def handleCommandString(self, dgi): command = dgi.getString() exec( command, globals()) class ClusterServerSync(ClusterServer): def __init__(self,cameraGroup,camera): self.notify.info('starting ClusterServerSync') self.posRecieved = 0 ClusterServer.__init__(self,cameraGroup,camera) self.startSwapCoordinator() return None def readerPollTask(self, task): if self.lastConnection is None: pass elif self.qcr.isConnectionOk(self.lastConnection): # Process datagrams till you get a postion update type = CLUSTER_NONE while type != CLUSTER_CAM_MOVEMENT: (datagram,dgi,type) = self.msgHandler.blockingRead(self.qcr) if type == CLUSTER_CAM_MOVEMENT: # Move camera self.handleCamMovement(dgi) # Set flag for swap coordinator self.posRecieved = 1 elif type == CLUSTER_CAM_OFFSET: # Update camera offset self.handleCamOffset(dgi) elif type == CLUSTER_COMMAND_STRING: # Got a command, execute it self.handleCommandString(dgi) return Task.cont def sendSwapReady(self): self.notify.debug( ('send swap ready packet %d' % self.msgHandler.packetNumber ) ) datagram = self.msgHandler.makeSwapReadyDatagram() self.cw.send(datagram, self.lastConnection) def startSwapCoordinator(self): taskMgr.add(self.swapCoordinatorTask, "serverSwapCoordinator", 51) return None def swapCoordinatorTask(self, task): if self.posRecieved: self.posRecieved = 0 self.sendSwapReady() while 1: (datagram,dgi,type) = self.msgHandler.blockingRead(self.qcr) if type == CLUSTER_SWAP_NOW: self.notify.debug('swapping') base.win.swap() break else: self.handleDatagram(dgi,type) return Task.cont