class NetworkClient(): def __init__(self): self.timeout = 3000 self.c_manager = QueuedConnectionManager() self.c_reader = QueuedConnectionReader(self.c_manager, 0) self.c_writer = ConnectionWriter(self.c_manager, 0) def connect(self, ip, port): self.connection = self.c_manager.openTCPClientConnection( ip, port, self.timeout) if self.connection: self.c_reader.addConnection(self.connection) return (True) return (False) def disconnect(self): if self.connection: self.c_manager.closeConnection(self.connection) else: print("Trying to disconnect while not connected!") def send_data(self): data = PyDatagram() data.addString("Hello, world!") self.c_writer.send(data, self.connection)
class Client(object): def __init__(self, host="localhost", port=5001, name="client"): self.name = name self.cManager = QueuedConnectionManager() self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) self.readerCallbacks = [] taskMgr = Task.TaskManager() # how long until we give up trying to reach the server? timeout_in_miliseconds = 3000 # 3 seconds self.myConnection = self.cManager.openTCPClientConnection( host, port, timeout_in_miliseconds) if not self.myConnection: print("{}: Failed to connect to server!".format(self.name)) return self.cReader.addConnection( self.myConnection) # receive messages from server taskMgr.add(self.tskReaderPolling, "Poll the connection reader", -40) print("{}: Successfully connected to server {} at {}!".format( self.name, port, host)) def tskReaderPolling(self, taskdata): # reader callback if not self.cReader.dataAvailable(): return Task.cont # catch the incoming data in this instance # Check the return value; if we were threaded, someone else could have # snagged this data before we did datagram = NetDatagram() if not self.cReader.getData(datagram): return Task.cont for callback in self.readerCallbacks: callback(datagram) return Task.cont def addReaderCallback(self, callbackFunction): self.readerCallbacks.append(callbackFunction) def ProcessReaderData(self, data): # TODO(vicdie): overwrite in derived classes pass def Close(self): # close connection if it exists if self.myConnection: self.cManager.closeConnection(self.myConnection)
class Network(): def __init__(self): self.c_manager = QueuedConnectionManager() self.c_listener = QueuedConnectionListener(self.c_manager, 0) self.c_reader = QueuedConnectionReader(self.c_manager, 0) self.c_writer = ConnectionWriter(self.c_manager,0) self.active_conns=[] self.port_address=9099 #No-other TCP/IP services are using this port self.backlog=1000 #If we ignore 1,000 connection attempts, something is wrong! #tcp_socket = c_manager.openTCPServerRendezvous(port_address,backlog) #self.tcp_socket = self.c_manager.openTCPServerRendezvous("0.0.0.0", 9099, 1000) #self.c_listener.addConnection(self.tcp_socket) def tsk_listener_pol(self, taskdata): if self.c_listener.newConnectionAvailable(): rendezvous = PointerToConnection() netAddress = NetAddress() newConnection = PointerToConnection() if self.c_listener.getNewConnection(rendezvous,netAddress,newConnection): print("Connected: "+str(netAddress)) newConnection = newConnection.p() self.active_conns.append(newConnection) # Remember connection self.c_reader.addConnection(newConnection) # Begin reading connection return Task.cont def tsk_reader_pol(self, taskdata): if self.c_reader.dataAvailable(): datagram=NetDatagram() # catch the incoming data in this instance # Check the return value; if we were threaded, someone else could have # snagged this data before we did if self.c_reader.getData(datagram): self.data_process(datagram) return Task.cont def data_process(self, datagram): it = PyDatagramIterator(datagram) message = it.getString() print("Processed: "+message+" from: "+str(datagram.getAddress())) def listen(self): print("Now listening on all addresses on port 9099") self.tcp_socket = self.c_manager.openTCPServerRendezvous("0.0.0.0", 9099, 1000) self.c_listener.addConnection(self.tcp_socket) taskMgr.add(self.tsk_listener_pol, "Poll connection listener", -39) taskMgr.add(self.tsk_reader_pol, "Pol the connection reader", -40) def unlisten(self): print("Stopping listen") self.c_manager.closeConnection(self.tcp_socket)
class Client(ShowBase): def __init__(self): ShowBase.__init__(self, windowType='none') self.port = 5555 self.addr = "127.0.0.1" self.timeout = 3000 self.connect_to_server() def connect_to_server(self) -> None: self.manager = QueuedConnectionManager() self.reader = QueuedConnectionReader(self.manager, 0) self.writer = ConnectionWriter(self.manager, 0) try: self.connection = self.manager.openTCPClientConnection( self.addr, self.port, self.timeout) # Listen for data sent from server taskMgr.add(self.handle_server_connection, "Poll the connection listener", -40) print("Connected to server...") self.reader.addConnection(self.connection) taskMgr.add(self.send_server_message, "Send msg", -41) except: print("Server not connected...") def handle_server_connection(self, task_data: Task) -> Task: if self.reader.dataAvailable(): datagram = PyDatagram() if self.reader.getData(datagram): self.handle_server_message(datagram) return Task.cont def send_server_message(self, task_data: Task) -> None: new_datagram = PyDatagram() name = input("What's your name? ") new_datagram.addString(name) self.writer.send(new_datagram, self.connection) def handle_server_message(self, message: str) -> None: iterator = PyDatagramIterator(message) print(iterator.getString())
class Server: def __init__(self): self.port = 5555 self.addr = "127.0.0.1" self.backlog = 7 self.active_connections = dict() self.start = False self.connect() def connect(self) -> None: # Handle connections and terminations self.manager = QueuedConnectionManager() # Wait for clients connection requests self.listener = QueuedConnectionListener(self.manager, 0) # Buffers incoming data from active connection self.reader = QueuedConnectionReader(self.manager, 0) # Transmit PyDatagrams to active connection self.writer = ConnectionWriter(self.manager, 0) # Open TCP Rendezvous to accept client connections with a limit self.socket = self.manager.openTCPServerRendezvous( self.port, self.backlog) self.listener.addConnection(self.socket) print("Server listening on port %s...." % str(self.port)) # Listen for mew incoming connections taskMgr.add(self.handle_incoming_connections, "Poll the connection listener", -39) # Listen for new datagrams taskMgr.add(self.handle_connection_data, "Poll the connection reader", -40) # Listen for dropped connections taskMgr.add(self.handle_dropped_connections, "Poll the dropped connection listener", -41) # See if game can be started taskMgr.add(self.start_game, "Start Game", -42) def start_game(self, task_data: Task) -> Task: if len(self.active_connections) == self.backlog: self.start = True return Task.cont def handle_incoming_connections(self, task_data: Task) -> Task: if self.listener.newConnectionAvailable(): rendezvous = PointerToConnection() net_addr = NetAddress() new_connection = PointerToConnection() if self.listener.getNewConnection(rendezvous, net_addr, new_connection): new_connection = new_connection.p() # Keep track of our active connections self.active_connections[str( new_connection.this)] = new_connection # Start reading the new connection self.reader.addConnection(new_connection) print("%s just connected" % str(new_connection)) return Task.cont def handle_connection_data(self, task_data: Task) -> Task: if self.reader.dataAvailable(): # Catch the incoming data datagram = NetDatagram() if self.reader.getData(datagram): name = self.handle_client_message(datagram) broadcast = f"Everyone, welcome {name} to the game!" self.broadcast_message(broadcast) return Task.cont def handle_dropped_connections(self, task_data: Task) -> Task: if self.manager.resetConnectionAvailable(): connection_pointer = PointerToConnection() self.manager.getResetConnection(connection_pointer) lost_connection = connection_pointer.p() print("% s disconnected from server" % str(lost_connection)) del self.active_connections[str(lost_connection.this)] self.manager.closeConnection(lost_connection) return Task.cont def handle_client_message(self, message: str) -> str: iterator = PyDatagramIterator(message) return iterator.getString() def get_connections_count(self) -> int: return len(self.active_connections) def send_personal_message(self, message: str, client: PointerToConnection) -> None: datagram = self.create_new_datagram(message) self.writer.send(datagram, client) def broadcast_message(self, message: str) -> None: datagram = self.create_new_datagram(message) for client in self.active_connections: self.writer.send(datagram, self.active_connections[client]) def create_new_datagram(self, message: str) -> PyDatagram: new_datagram = PyDatagram() new_datagram.addString(message) return new_datagram def terminate_all_clients(self) -> None: for client in self.active_connections: self.reader.removeConnection(client) self.active_connections = list() def terminate_specific_client(self, client: PointerToConnection) -> None: self.reader.removeConnection(client) del self.active_connections[str(client)]
class Login_Page(DirectObject): def __init__(self): base.setBackgroundColor( 254, 254, 254 ) # sets the background color to black because the # default grey color bugs me for some reason self.loginScreen() # draws the login screen self.usernameBox['focus'] = 1 # sets the cursor to the username field by default self.accept('tab', self.cycleLoginBox) # enables the user to cycle through the text fields with the tab key # this is a standard feature on most login forms self.accept('enter', self.attemptLogin) # submits the login form, or you can just click the Login button def loginScreen(self): # creates a basic login screen that asks for a username/password boxloc = Vec3(0.0, 0.0, 0.0) # all items in the login form will have a position relative to this # this makes it easier to shift the entire form around once we have # some graphics to display with it without having to change the # positioning of every form element # p is the position of the form element relative to the boxloc # coordinates set above it is changed for every form element p = boxloc + Vec3(-0.5, 0, 0.0) self.textObject = OnscreenText(text = "Username:"******"Username: "******"" , pos = p, scale=.05, initialText="", numLines = 1) # Username textbox where you type in your username p = boxloc + Vec3(-0.5, -0.1, 0.0) self.textObject = OnscreenText(text = "Password:"******"Password: "******"" , pos = p, scale=.05, initialText="", numLines = 1, obscured = 1) # Password textbox where you type in your password # Note - obscured = 1 denotes that all text entered will be replaced # with a * like a standard password box p = boxloc + Vec3(0, 0, -0.2) self.loginButton = DirectButton(text = ("Login", "Login", "Login", "Login"), pos = p, scale = 0.075, command=self.attemptLogin) # The 'Login' button that will trigger the attemptLogin function # when clicked p = boxloc + Vec3(-0.5, -0.4, 0) self.statusText = OnscreenText(text = "", pos = p, scale = 0.05, fg = (1, 0, 0, 1), align=TextNode.ALeft) # A simple text object that you can display an error/status messages # to the user def updateStatus(self, statustext): self.statusText.setText(statustext) # all this does is change the status text. def composeStringMessage(self, msg): myPyDatagram = PyDatagram() myPyDatagram.addString(msg) return myPyDatagram def retrieveStringMessage(self,datagram): myIterator = PyDatagramIterator(datagram) msg = myIterator.getString() print msg, " received" def sendRequest(self): if(self.received): print "->Client request:" # Send a request to the server msg = self.usernameBox.get()+" "+self.passwordBox.get() request = self.composeStringMessage(msg) ack = self.cWriter.send(request,self.connection) print msg, " sent" self.received = 0 def receiveResponse(self): print "<-Server response:" while self.cReader.dataAvailable(): datagram = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram): self.retrieveStringMessage(datagram) self.received = 1 def communicate(self): #print "communicate" self.sendRequest() self.receiveResponse() def updateRoutine(self,task): self.communicate() return task.again; def attemptLogin(self): # checks to make sure the user inputed a username and password: # if they didn't it will spit out an error message # if they did, it will try to connect to the login server # (under construction) if(self.usernameBox.get() == ""): if(self.passwordBox.get() == ""): self.updateStatus("ERROR: You must enter a username and password before logging in.") else: self.updateStatus("ERROR: You must specify a username") self.passwordBox['focus'] = 0 self.usernameBox['focus'] = 1 elif(self.passwordBox.get() == ""): self.updateStatus("ERROR: You must enter a password") self.usernameBox['focus'] = 0 self.passwordBox['focus'] = 1 else: self.updateStatus("Attempting to login...") print "Attempting to connect to Server with credentials: (" + self.usernameBox.get() + ", " + self.passwordBox.get() + ")" # this is where the networking code will get put in self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) HOST = "localhost"; PORT = 1234; self.connection = self.cManager.openTCPClientConnection(HOST, PORT, 10000) self.received = 1 if self.connection: self.cReader.addConnection(self.connection) #taskMgr.add(self.updateRoutine, 'updateRoutine') taskMgr.doMethodLater(3, self.updateRoutine, 'updateRoutine') def cycleLoginBox(self): # function is triggered by the tab key so you can cycle between # the two input fields like on most login screens # IMPORTANT: When you change the focus to one of the text boxes, # you have to unset the focus on the other textbox. If you do not # do this Panda seems to get confused. if(self.passwordBox['focus'] == 1): self.passwordBox['focus'] = 0 self.usernameBox['focus'] = 1 elif(self.usernameBox['focus'] == 1): self.usernameBox['focus'] = 0 self.passwordBox['focus'] = 1
class TCP(): def __init__(self, _core): print ("TCP Protocol Startup...") self.core = _core self.config = self.core.client.config # Connection on TCP self.tcpConnection = None def start(self): self.setupTCP() self.startTCPTasks() def setupTCP(self): self.tcpManager = QueuedConnectionManager() self.tcpReader = QueuedConnectionReader(self.tcpManager, 0) self.tcpWriter = ConnectionWriter(self.tcpManager, 0) def startTCPTasks(self): taskMgr.add(self.tcpReaderTask, "tcpReaderTask", -10) print ("TCP Reader Started") def tcpReaderTask(self, task): """ Handle any data from clients by sending it to the Handlers. """ while 1: (datagram, data, opcode) = self.tcpNonBlockingRead(self.tcpReader) if opcode is MSG_NONE: # Do nothing or use it as some 'keep_alive' thing. break else: # Handle it self.core.packetManager.handlePacket(opcode, data) return Task.cont # TCP NonBlockingRead?? def tcpNonBlockingRead(self, qcr): """ Return a datagram collection and type if data is available on the queued connection udpReader """ if self.tcpReader.dataAvailable(): datagram = NetDatagram() if self.tcpReader.getData(datagram): data = DatagramIterator(datagram) opcode = data.getUint8() else: data = None opcode = MSG_NONE else: datagram = None data = None opcode = MSG_NONE # Return the datagram to keep a handle on the data return (datagram, data, opcode) def connectToServer(self, _ip, _port): self.tcpConnection = self.tcpManager.openTCPClientConnection(_ip, _port, 1000) if self.tcpConnection != None: self.tcpReader.addConnection(self.tcpConnection) # Close the main menu and move the client into the game # for now we will make a shortcut #self.clientManager.guiManager.menu.hide()
class Client(DirectObject): def __init__(self, host, port, timeout=3000, compress=False, connectionStateChangedHandler=None): DirectObject.__init__(self) self.connectionStateChangedHandler = connectionStateChangedHandler self.myConnection = None self.host = host self.port = port self.timeout = timeout self.compress = compress self.cManager = QueuedConnectionManager() self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) # By default, we are not connected self.connected = False self.passedData = [] self.connect(self.host, self.port, self.timeout) def cleanup(self): self.removeAllTasks() def startPolling(self): self.doMethodLater(0.1, self.tskDisconnectPolling, "clientDisconnectTask") def connect(self, host, port, timeout=3000): # Connect to our host's socket self.myConnection = self.cManager.openTCPClientConnection( host, port, timeout) if self.myConnection: self.myConnection.setNoDelay(True) self.myConnection.setKeepAlive(True) print "Connected" self.cReader.addConnection( self.myConnection) # receive messages from server self.connected = True # Let us know that we're connected self.startPolling() if self.connectionStateChangedHandler: self.connectionStateChangedHandler.handleConnection() else: print "Unable to connect" if self.connectionStateChangedHandler: self.connectionStateChangedHandler.handleFailure() def tskDisconnectPolling(self, task): if not self.connected: return Task.done # TODO: Hacky sending nothing to force disconnect triggers #self.sendData() # Also checking for dataAvailable on reader will trigger the connection disconnected self.cReader.dataAvailable() # TODO: Confirm this works for client side (to both game server and master server) while self.cManager.resetConnectionAvailable(): connPointer = PointerToConnection() self.cManager.getResetConnection(connPointer) connection = connPointer.p() # Remove the connection we just found to be "reset" or "disconnected" self.cReader.removeConnection(connection) # Let us know that we are not connected self.connected = False print "disconnected" if self.connectionStateChangedHandler: self.connectionStateChangedHandler.handleDisconnection() return Task.again def processData(self, netDatagram): myIterator = PyDatagramIterator(netDatagram) return self.decode(myIterator.getString()) def encode(self, data, compress=False): # encode(and possibly compress) the data with rencode return rencode.dumps(data, compress) def decode(self, data): # decode(and possibly decompress) the data with rencode return rencode.loads(data) def sendData(self, data=None): myPyDatagram = PyDatagram() myPyDatagram.addString(self.encode(data, self.compress)) self.cWriter.send(myPyDatagram, self.myConnection) def passData(self, data): self.passedData.append(data) def getData(self): data = self.passedData self.passedData = [] while self.cReader.dataAvailable(): datagram = NetDatagram() if self.cReader.getData(datagram): data.append(self.processData(datagram)) return data
class World(DirectObject): def __init__(self): self.keyMap = {"left":0, "right":0, "forward":0, "cam-left":0, "cam-right":0} self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) self.opponents = dict() self.logStat = -1 self.id = 0 self.username = "" host = "localhost" port = 9252 self.connection = self.cManager.openTCPClientConnection(host, port, 10000) self.received = 1 self.playersText = [] if self.connection: self.cReader.addConnection(self.connection) taskMgr.add(self.updateRoutine, 'updateRoutine') taskMgr.add(self.login, 'login') taskMgr.doMethodLater(.1, self.heartbeat, 'heartbeat') # Replace with actual, dynamic list of players from the server self.players = dict() # Placeholder, replace with actual # of players later self.numberOfPlayers = 2 # Stores the OnScreenText for each player in the players list # Populated and depopulated using listPlayers and delistPlayers self.playersText = [] # Stores all the player objects currently logged in self.playerObjects = [] base.win.setClearColor(Vec4(0,0,0,1)) # Post the instructions #self.title = addTitle("Panda3D Tutorial: Roaming Ralph (Walking on Uneven Terrain)") #self.inst1 = addInstructions(0.95, "[ESC]: Quit") #self.inst2 = addInstructions(0.90, "[Left Arrow]: Rotate Ralph Left") #self.inst3 = addInstructions(0.85, "[Right Arrow]: Rotate Ralph Right") #self.inst4 = addInstructions(0.80, "[Up Arrow]: Run Ralph Forward") #self.inst6 = addInstructions(0.70, "[A]: Rotate Camera Left") #self.inst7 = addInstructions(0.65, "[S]: Rotate Camera Right") #self.inst8 = addInstructions(0.60, "[Q]: Display List Of Connected Players") # Set up the environment # # This environment model contains collision meshes. If you look # in the egg file, you will see the following: # # <Collide> { Polyset keep descend } # # This tag causes the following mesh to be converted to a collision # mesh -- a mesh which is optimized for collision, not rendering. # It also keeps the original mesh, so there are now two copies --- # one optimized for rendering, one for collisions. self.environ = loader.loadModel("models/world") self.environ.reparentTo(render) self.environ.setPos(0,0,0) # Create the main character, Ralph ralphStartPos = self.environ.find("**/start_point").getPos() self.ralph = Actor("models/ralph", {"run":"models/ralph-run", "walk":"models/ralph-walk"}) self.ralph.reparentTo(render) self.ralph.setScale(.2) self.ralph.setPos(ralphStartPos) ralphStartPos.setY(ralphStartPos.getY()-10) self.ralph.setPos(ralphStartPos.getX(),ralphStartPos.getY(),ralphStartPos.getZ()) self.initx = ralphStartPos.getX() # Add our Ralph to list to Ralphs self.playerObjects.append(self.ralph) # Load and transform the panda actor. self.pandaActor = Actor("models/panda-model", {"walk": "models/panda-walk4"}) self.pandaActor.setScale(0.003, 0.003, 0.003) self.pandaActor.reparentTo(render) # Loop its animation. #self.pandaActor.loop("walk") self.pandaActor.setPos(ralphStartPos.getX(),ralphStartPos.getY()-20,ralphStartPos.getZ()) # Create a floater object. We use the "floater" as a temporary # variable in a variety of calculations. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) # Accept the control keys for movement and rotation self.accept("escape", self.disconnect) self.accept("arrow_left", self.setKey, ["left",1]) self.accept("arrow_right", self.setKey, ["right",1]) self.accept("arrow_up", self.setKey, ["forward",1]) self.accept("a", self.setKey, ["cam-left",1]) self.accept("s", self.setKey, ["cam-right",1]) self.accept("arrow_left-up", self.setKey, ["left",0]) self.accept("arrow_right-up", self.setKey, ["right",0]) self.accept("arrow_up-up", self.setKey, ["forward",0]) self.accept("a-up", self.setKey, ["cam-left",0]) self.accept("s-up", self.setKey, ["cam-right",0]) self.accept("q", self.listPlayers) self.accept("q-up", self.delistPlayers) taskMgr.add(self.move,"moveTask") # Call whenever a ralph has logged in, use arg "out" for logouts self.displayLoginText() # Game state variables self.isMoving = False # Set up the camera base.disableMouse() base.camera.setPos(self.ralph.getX(),self.ralph.getY()+10,2) # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. self.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0,0,1000) self.ralphGroundRay.setDirection(0,0,-1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) self.pandaActorGroundRay = CollisionRay() self.pandaActorGroundRay.setOrigin(0,0,1000) self.pandaActorGroundRay.setDirection(0,0,-1) self.pandaActorGroundCol = CollisionNode('pandaActorRay') self.pandaActorGroundCol.addSolid(self.pandaActorGroundRay) self.pandaActorGroundCol.setFromCollideMask(BitMask32.bit(0)) self.pandaActorGroundCol.setIntoCollideMask(BitMask32.allOff()) self.pandaActorGroundColNp = self.pandaActor.attachNewNode(self.pandaActorGroundCol) self.pandaActorGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.pandaActorGroundColNp, self.pandaActorGroundHandler) self.camGroundRay = CollisionRay() self.camGroundRay.setOrigin(0,0,1000) self.camGroundRay.setDirection(0,0,-1) self.camGroundCol = CollisionNode('camRay') self.camGroundCol.addSolid(self.camGroundRay) self.camGroundCol.setFromCollideMask(BitMask32.bit(0)) self.camGroundCol.setIntoCollideMask(BitMask32.allOff()) self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Uncomment this line to see the collision rays #self.ralphGroundColNp.show() #self.camGroundColNp.show() self.miniMap = miniMap(self.ralph) self.miniMap.setNpc('tower_1', 'models/hexahedron.png', 0.05, 0.2, 0.3) self.miniMap.setNpc('tower_2', 'models/hexahedron.png', 0.05, -0.4, -0.5) # Uncomment this line to show a visual representation of the # collisions occuring #self.cTrav.showCollisions(render) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(-5, -5, -5)) directionalLight.setColor(Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) self.setAI() #Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): self.miniMap.updateHeroPos(self.ralph.getX(), self.ralph.getY()) self.miniMap.updateHeroHpr(self.ralph.getH()) # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. base.camera.lookAt(self.ralph) if (self.keyMap["cam-left"]!=0): base.camera.setX(base.camera, -20 * globalClock.getDt()) if (self.keyMap["cam-right"]!=0): base.camera.setX(base.camera, +20 * globalClock.getDt()) # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.ralph.getPos() # If a move-key is pressed, move ralph in the specified direction. if (self.keyMap["left"]!=0): self.ralph.setH(self.ralph.getH() + 300 * globalClock.getDt()) if (self.keyMap["right"]!=0): self.ralph.setH(self.ralph.getH() - 300 * globalClock.getDt()) if (self.keyMap["forward"]!=0): self.ralph.setY(self.ralph, -25 * globalClock.getDt()) # Makes the panda look at ralph when not using AI #self.pandaActor.lookAt(self.ralph) #self.pandaActor.setH(self.pandaActor.getH() + 180) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. if (self.keyMap["forward"]!=0) or (self.keyMap["left"]!=0) or (self.keyMap["right"]!=0): if self.isMoving is False: self.ralph.loop("run") self.isMoving = True else: if self.isMoving: self.ralph.stop() self.ralph.pose("walk",5) self.isMoving = False print "stop" self.requestStop() # If the camera is too far from ralph, move it closer. # If the camera is too close to ralph, move it farther. camvec = self.ralph.getPos() - base.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if (camdist > 10.0): base.camera.setPos(base.camera.getPos() + camvec*(camdist-10)) camdist = 10.0 if (camdist < 5.0): base.camera.setPos(base.camera.getPos() - camvec*(5-camdist)) camdist = 5.0 # Now check for collisions. self.cTrav.traverse(render) # Adjust ralph's Z coordinate. If ralph's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = [] for i in range(self.ralphGroundHandler.getNumEntries()): entry = self.ralphGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): self.ralph.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.ralph.setPos(startpos) entries2 = [] for i in range(self.pandaActorGroundHandler.getNumEntries()): entry = self.pandaActorGroundHandler.getEntry(i) entries2.append(entry) entries2.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries2)>0) and (entries2[0].getIntoNode().getName() == "terrain"): self.pandaActor.setZ(entries2[0].getSurfacePoint(render).getZ()) else: self.pandaActor.setPos(startpos) # Keep the camera at one foot above the terrain, # or two feet above ralph, whichever is greater. entries = [] for i in range(self.camGroundHandler.getNumEntries()): entry = self.camGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): base.camera.setZ(entries[0].getSurfacePoint(render).getZ()+1.0) if (base.camera.getZ() < self.ralph.getZ() + 2.0): base.camera.setZ(self.ralph.getZ() + 2.0) # The camera should look in ralph's direction, # but it should also try to stay horizontal, so look at # a floater which hovers above ralph's head. self.floater.setPos(self.ralph.getPos()) self.floater.setZ(self.ralph.getZ() + 2.0) base.camera.lookAt(self.floater) if self.isMoving: self.moveRalph() return task.cont def displayLoginText(self, s="in"): self.loginText = addInstructions(-0.95, "A Ralph has logged " + s) myTask = taskMgr.doMethodLater(3, self.removeLoginText, 'removeLoginTextTask') def moveRalph(self): pkg = PyDatagram() pkg.addUint16(114) pkg.addFloat32(self.ralph.getX()) pkg.addFloat32(self.ralph.getY()) pkg.addFloat32(self.ralph.getZ()) pkg.addFloat32(self.ralph.getH()) self.cWriter.send(pkg,self.connection) def disconnect(self): pkg = PyDatagram() pkg.addUint16(119) self.cWriter.send(pkg,self.connection) sys.exit() def requestStop(self): pkg = PyDatagram() pkg.addUint16(115) self.cWriter.send(pkg,self.connection) def stopPlayer(self, data): id = data.getInt32() if id != self.id: self.opponents[id].character.stop() self.opponents[id].character.pose("walk",5) def movePlayer(self, data): id = data.getInt32() x = data.getFloat32() y = data.getFloat32() z = data.getFloat32() rotation = data.getFloat32() if id == self.id: self.ralph.setPos(x, y, z) self.ralph.setH(rotation) else: self.opponents[id].character.setPos(x,y,z) self.opponents[id].character.setH(rotation) self.opponents[id].character.loop("run", restart = 0) self.miniMap.updateTeamMatePos(id, x, y) def check(self): while self.cReader.dataAvailable(): print "data here" datagram = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram): data = PyDatagramIterator(datagram) responseCode = data.getUint16() print responseCode if responseCode == 201: self.getPlayer(data) elif responseCode == 202: self.register(data) elif responseCode == 203: self.getOpponent(data) elif responseCode == 214: self.movePlayer(data) elif responseCode == 215: self.stopPlayer(data) elif responseCode == 219: self.dropPlayer(data) else: print "nothing found" def heartbeat(self, task): pkg = PyDatagram() pkg.addUint16(113) self.cWriter.send(pkg,self.connection) return task.again def updateRoutine(self,task): self.check() return task.again; def login(self, task): self.option = 0 self.option = str(raw_input("1-Login\n2-Register\n")) if self.option == "1": un = str(raw_input("Username: "******"Password: "******"2": un = str(raw_input("Username: "******"Password: "******"Account Made" taskMgr.add(self.login, 'login') else: print "Username Taken" taskMgr.add(self.login, 'login') def registerRequest(self, username, password): pkg = PyDatagram() pkg.addUint16(102) pkg.addString(username) pkg.addString(password) return pkg def getPlayer(self, data): self.logStat = data.getUint16() if self.logStat == 0: self.id = data.getInt32() self.username = data.getString() x = data.getFloat32() y = data.getFloat32() z = data.getFloat32() rotation = data.getFloat32() if x == 0 and y == 0 and z == 0: ralphStartPos = self.environ.find("**/start_point").getPos() self.ralph.setPos(ralphStartPos.getX(),ralphStartPos.getY(),ralphStartPos.getZ()) else: self.ralph.setPos( x, y, z ) self.ralph.setH( rotation ) else: print "login failed" taskMgr.add(self.login, 'login') def getOpponent(self, data): opponent = Player() opponent.id = data.getInt32() opponent.username = data.getString() x = data.getFloat32() y = data.getFloat32() z = data.getFloat32() rotation = data.getFloat32() opponent.character.reparentTo(render) opponent.character.setScale(.2) opponent.character.setPos(x, y, z) opponent.character.setH(rotation) self.opponents[opponent.id] = opponent self.displayLoginText() self.miniMap.setTeamMate(opponent.id, 0.025, x, y) def dropPlayer(self, data): id = data.getInt32() self.opponents[id].character.removeNode() del self.opponents[id] self.displayLoginText(s="out") self.miniMap.delTeamMate(id) def removeLoginText(self, task): self.loginText.destroy() return task.done def listPlayers(self): i = 0.55 for p in self.opponents: self.playersText.append( addInstructions(i, self.opponents[p].username) ) i -= 0.05 def delistPlayers(self): for x in self.playersText: x.destroy() def findClosestRalph(self): px = self.pandaActor.getX() py = self.pandaActor.getY() pz = self.pandaActor.getZ() closestPlayer = self.ralph rx = self.ralph.getX() ry = self.ralph.getY() rz = self.ralph.getZ() minDist = math.sqrt( (rx-px)*(rx-px) + (ry-py)*(ry-py) + (rz-pz)*(rz-pz) ) for x in self.opponents: rx = self.opponents[x].character.getX() ry = self.opponents[x].character.getY() rz = self.opponents[x].character.getZ() dist = math.sqrt( (rx-px)*(rx-px) + (ry-py)*(ry-py) + (rz-pz)*(rz-pz) ) if (dist < minDist): minDist = dist closestPlayer = self.opponents[x].character return closestPlayer, minDist # Panda chasing Ralph def setAI(self): #Creating AI World self.AIworld = AIWorld(render) self.AIchar = AICharacter("panda",self.pandaActor, 100, 0.05, 5) self.AIworld.addAiChar(self.AIchar) self.AIbehaviors = self.AIchar.getAiBehaviors() closestRalph = self.findClosestRalph() self.AIbehaviors.pursue(closestRalph[0]) self.pandaActor.loop("walk") #AI World update taskMgr.add(self.AIUpdate,"AIUpdate") #to update the AIWorld def AIUpdate(self,task): self.AIworld.update() closestRalph = self.findClosestRalph() if ( self.numberOfPlayers <= 1 or not restrain(closestRalph[1], -CHASE_DISTANCE, CHASE_DISTANCE) or closestRalph[1] < 3): self.AIbehaviors.pauseAi("pursue") else: self.AIbehaviors.pursue(closestRalph[0]) return task.cont
class ConnectionManager: notify = DirectNotifyGlobal.directNotify.newCategory("ConnectionManager") def __init__(self): self.socket = None self.hostName = None self.port = None self.ourChannel = 100001 self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) def start(self): self.hostName = base.configManager.getString('host-name', '127.0.0.1') self.port = base.configManager.getInt('port-number', 6667) self.socket = self.cManager.openTCPServerRendezvous( self.hostName, self.port, 1000) if self.socket: self.cListener.addConnection(self.socket) self._serverStarted(self.hostName, self.port) taskMgr.add(self._socketListener, 'Connection Listener') taskMgr.add(self._socketReader, 'Connection Reader') else: self.notify.warning( "Unable to start server on %s:%d - is the port in use?" % (self.hostName, self.port)) base.logManager.writeServerEvent( 'ServerBase', 'Unable to start server on %s:%d - is the port in use?' % (self.hostName, self.port)) sys.exit() def _serverStarted(self, host, port): self.notify.warning("Server started on %s:%d" % (host, port)) base.logManager.writeServerEvent( 'ServerBase', 'Server started on %s:%d' % (host, port)) def _socketListener(self, task): if self.cListener.newConnectionAvailable(): rendezvous = PointerToConnection() netAddress = NetAddress() newConnection = PointerToConnection() if self.cListener.getNewConnection(rendezvous, netAddress, newConnection): newConnection = newConnection.p() base.activeConnections[newConnection] = NetworkedClient() self.cReader.addConnection(newConnection) self.notify.warning("New Unauthed Client Connected: %s" % (netAddress)) return Task.cont def _socketReader(self, task): if self.cReader.dataAvailable(): datagram = NetDatagram() if self.cReader.getData(datagram): base.messageManager.handleMessage(datagram) return Task.cont
class NetworkClient(): """ All remote clients will have one of these in their GameManager. This class communicates with a server (NetworkHost) to update game state. """ def __init__(self, gameManager): self._connManager = QueuedConnectionManager() self._timeout = CLIENT_TIMEOUT self._loadConfig() self._gameManager = gameManager self._playerInfo = dict() # Party Member Info self._creatures = dict() # Creates by cID. self._connection = None def _loadConfig(self): """ Loads network configuration defaults. """ self._portAddress = ConfigVariableInt("default-port", DEFAULT_PORT).getValue() def startClient(self, ipAddress): """ Finishes client init and attempts a connection. """ # Initialize Reader and Writer: self._connReader = QueuedConnectionReader(self._connManager, 0) self._connWriter = ConnectionWriter(self._connManager, 0) # Initialize connection: self._connection = self._connManager.openTCPClientConnection( ipAddress, self._portAddress, self._timeout) if self._connection: print("[Client Connected]") self._connReader.addConnection(self._connection) # Begin handling messages (start listening): taskMgr.add(self._onReaderPoll, "Poll the connection reader", -40) self._gameManager.onLocalClientJoinedParty(self._connection\ .this) # GameManager callback def _onReaderPoll(self, taskdata): """ Called on an interval to interpret messages from the reader. """ if self._connReader.dataAvailable(): newDatagram = NetDatagram() # Double check to make sure (Multithreading safety): if self._connReader.getData(newDatagram): self._interpretDatagram(newDatagram) return Task.cont # Repeat this call on an interval def sendMessage(self, msg, msgType): """ Sends a given message to the server. """ print("[Client Sending %s message type %s]" % (str(self._connection), str(msgType))) self._connWriter.send(msg, self._connection) def _interpretDatagram(self, datagram): """ Interprets a received datagram and performs actions based on its values. """ msg = PyDatagramIterator(datagram) msgType = msg.getUint8() if msgType == DEBUG_MESSAGE: print(msg.getString()) elif msgType == MAP_MESSAGE: print("[Client Received Map Data]") if self._gameManager.getTileMap() == None: data = msg.getString32() self._gameManager.onClientFirstReceivedMap(data) elif msgType == UPDATE_PLAYER_INFO: data = msg.getString() self._updatePlayerInfoHandler(data) elif msgType == SPAWN_CHARACTER: data = msg.getString() dataDict = json.loads(data) self._onSpawnHandler(dataDict) elif msgType == SYNC_ACTION: data = msg.getString() dataDict = json.loads(data) self._onActionSyncHandler(dataDict) elif msgType == SYNC_HEALTH: data = msg.getString() dataDict = json.loads(data) self._onHealthSyncHandler(dataDict) elif msgType == SYNC_DEATH: data = msg.getString() dataDict = json.loads(data) self._onDeathSyncHandler(dataDict) elif msgType == SYNC_RESPAWN: data = msg.getString() dataDict = json.loads(data) self._onRespawnPermissionGranted(dataDict) elif msgType == SPAWN_ITEM: data = msg.getString() dataDict = json.loads(data) self._onItemSpawned(dataDict) elif msgType == WIN_STATE: data = msg.getString() self._onGameWon(data) def _onGameWon(self, data): """ Show the win state achieved screen with the specified playerinfo as the winner details. """ newPlayerData = PlayerInfo(fromJson=data) self._gameManager.onWinStateAchieved(newPlayerData) def _onItemSpawned(self, dataDict): """ The server spawned an item, handle spawning on this client """ itemType = ITEM_ID_DICT[dataDict['itemType']] itemID = dataDict['objID'] newPos = Point2D(dataDict['pos'][0], dataDict['pos'][1]) # Create item locally: newItem = itemType(self._gameManager, itemID, coords=newPos) self._gameManager.getTileMap().spawnItem(newItem, newPos) # Track new item: self._creatures[itemID] = newItem def _onDeathSyncHandler(self, dataDict): """ Handles syncing of death for the given creature """ deadCreature = self._creatures[dataDict['objID']] # Play death sequence on this character: deadCreature.deathSequence(amClient=True) def _onHealthSyncHandler(self, dataDict): """ Handles syncing of health values for creatures """ print("_onHealthSyncHandler") newHealth = dataDict['newHealth'] affectedCreature = self._creatures[dataDict['objID']] affectedCreature.onHPModified(newHealth) def _onSpawnHandler(self, dataDict): """ Handles networking spawning characters """ # Spawn object locally if the object at cID doesn't already exist. if not dataDict['objID'] in self._creatures.keys(): # Spawn object of charType at pos objectType = getCharacterTypeAsClass(dataDict['charType']) newPos = Point2D(dataDict['pos'][0], dataDict['pos'][1]) newChar = objectType(parentCtrlr=None, cID=dataDict['objID'], gameManager=self._gameManager, coords=newPos) self._creatures[dataDict['objID']] = newChar self._gameManager.getTileMap().spawnObject(newChar, newPos) print("[Client Spawned %s]" % dataDict['objID']) # If we have a player info for this player, use their name for the # displayName: print(dataDict['objID'], self._playerInfo) if dataDict['objID'] in self._playerInfo: newName = self._playerInfo[dataDict['objID']].cName newChar.setNameDisplay(newName) else: # Ignore Overwrite pass def _updatePlayerInfoHandler(self, data): """ Update our player list with a player info given by data. """ newPlayerData = PlayerInfo(fromJson=data) self._playerInfo[newPlayerData.cID] = newPlayerData self._gameManager.updatePartyInfo(self._playerInfo, self._connection.this) # Update the creature's floating display name (unless it is ours): ignoreThisUpdate = False if self._gameManager._localPlayer: if newPlayerData.cID == self._gameManager._localPlayer\ .getCharacter().getCID(): ignoreThisUpdate = True if not ignoreThisUpdate and newPlayerData.cID in self._creatures: self._creatures[newPlayerData.cID]\ .setNameDisplay(newPlayerData.cName) def _onRespawnPermissionGranted(self, dataDict): """ Respawn the given character at the given location. """ targetObj = self._creatures[dataDict['objID']] newPos = Point2D(dataDict['pos'][0], dataDict['pos'][1]) targetObj.respawn(newPos) def _onActionSyncHandler(self, dataDict): """ Attempts to queue an action for execution on a target denoted by dataDict['objID'] """ syncedAction = ACTION_NETWORKING_DICT[dataDict['actionID']] # Add a few local variables to dataDict: targetObj = self._creatures[ dataDict['objID']] # TODO Maybe make this part of dataDict! dataDict['tileMap'] = self._gameManager.getTileMap() if 'targetCID' in dataDict: # If there is another target: # Assign the target: dataDict['target'] = self._creatures[dataDict['targetCID']] dataDict['isServer'] = False # Let sync function know we are remote # Create the newAction newAction = syncedAction(targetObj, **dataDict) targetObj.startAction(newAction) # queue or start the new action def updateLocalPlayerInfo(self, info=None): """ Updates info for this local player and sends it to the server. """ if not info: initData = PlayerInfo(cID=self._connection.this) self._playerInfo[self._connection.this] = initData infoMsg = createPlayerInfoMessage(initData) self.sendMessage(infoMsg, UPDATE_PLAYER_INFO) else: infoMsg = createPlayerInfoMessage(info) self.sendMessage(infoMsg, UPDATE_PLAYER_INFO) def syncAction(self, actionID, **kwargs): """ The local player has performed an action that must be synced across the network. Send a message to all clients telling them to perform a related action on that character. """ msg = createSyncActionMessage(self._connection.this, actionID, **kwargs) self.sendMessage(msg, SYNC_ACTION) def sendPlayerRespawnRequest(self): msg = createRespawnRequest(self._connection.this) self.sendMessage(msg, SYNC_RESPAWN) def localPlayerWins(self): """ Tell host we won. Then wait for a response. """ msg = createWinMessage(self._playerInfo[self._connection.this]) self.sendMessage(msg, WIN_STATE) def spawnGameObject(self, gameObject): """ Tracks the given gameObject and sends it to the server """ # First, track it locally: self._creatures[self.getCID()] = gameObject # Tell server to spawn it for them and everyone else: msg = createSpawnCharacterMessage(gameObject, self.getCID()) self.sendMessage(msg, SPAWN_CHARACTER) def getCID(self): return self._connection.this
class Connection(GlobalClockMixin, TaskMixin): def __init__(self, base, host, port): self.base = base self.host = host self.port = port self._conn = None self._retry_elapsed = 0 self._retry_next = 0 self._data_last_received = 0 self.manager = QueuedConnectionManager() self.reader = QueuedConnectionReader( self.manager, 0, # number of threads ) # we're using our own protocol so we don't want panda reading our headers and getting # all foobared by it (not setting raw mode causes `dataAvailable` to block # once there is actually data to process) self.reader.setRawMode(True) self.writer = ConnectionWriter( self.manager, 0, # number of threads ) def connect(self, connected_callback, task): """ Attempts to connect to the server and if unable to will retry adding a second to the wait time to each consecutive failure. """ self._retry_elapsed += self.get_dt() if self._retry_elapsed < self._retry_next: return task.cont logging.debug('attempting to connect to server at %s:%d', self.host, self.port) self._conn = self.manager.openTCPClientConnection( self.host, self.port, 10000, # timeout ms ) if self._conn: logging.debug('connection established') self.reader.addConnection(self._conn) # reset the counters in case the connection drops and we have to restart the # connection process self._retry_elapsed = 0 self._retry_next = 0 # add a task to poll the connection for data self.add_task( self.task_read_polling, name='connection_reader_poll', sort=-39, ) connected_callback() return # no connection so retry in a bit self._retry_elapsed = 0 if self._retry_next == 0: self._retry_next = 1 elif self._retry_next > 9: self._retry_next = 10 else: self._retry_next += 1 logging.error( 'Unable to connect to server %s:%s, will retry in %d seconds', self.host, self.port, self._retry_next, ) return task.cont def task_read_polling(self, task): if self.reader.dataAvailable(): logging.debug('data available from server') datagram = Datagram() if self.reader.getData(datagram): logging.debug('received data from server: %s', datagram) logging.debug('received data from server: %s', datagram.getMessage()) # TODO: provide a way to supply a data callback self._data_last_received = 0 else: # no data received logging.debug('no data') self._data_last_received += self.get_dt() if self._data_last_received >= 10: logging.error('connection to server lost') return return task.cont def shutdown(self): logging.info('connection reader shutting down') self.reader.shutdown()
class SocketTCP(ShowBase): def __init__(self, _parent=None): ShowBase.__init__(self, windowType = 'none') print ("TCP Protocol Startup...") #self.parent = _parent #self.config = self.parent.server.config # tmp config self.tcpport = 6000 self.backlog = 10 self.hostname = '127.0.0.1' self.sendPacketQueue = None def startAll(self): self.setupTCP() self.startTCPTasks() def setupTCP(self): self.tcpManager = QueuedConnectionManager() self.tcpReader = QueuedConnectionReader(self.tcpManager, 0) self.tcpWriter = ConnectionWriter(self.tcpManager, 0) self.tcpListener = QueuedConnectionListener(self.tcpManager, 0) self.tcpSocket = self.tcpManager.openTCPServerRendezvous(self.tcpport, self.backlog) self.tcpListener.addConnection(self.tcpSocket) print ("Started Server on: ", self.hostname, self.tcpport) def startTCPTasks(self): taskMgr.add(self.tcpListenerTask, "tcpListenerTask", 0) print ("TCP Listener Started") taskMgr.add(self.tcpReaderTask, "tcpReaderTask", -10) print ("TCP Reader Started") taskMgr.add(self.tcpDisconnectionHandler, "tcpDisconnectionHandler", 20) print ("TCP Disconnection Handler Started") taskMgr.add(self.tcpQueuedSendHandlerTask, "tcpQueuedSendhandlerTask", -11) print ("TCP Queued Send Handler Started") # TCP Listener Task def tcpListenerTask(self, task): """ Accept new incoming connection from clients, related to TCP """ # Handle new connection if self.tcpListener.newConnectionAvailable(): rendezvous = PointerToConnection() netAddress = NetAddress() newConnection = PointerToConnection() if self.tcpListener.getNewConnection(rendezvous, netAddress, newConnection): newConnection = newConnection.p() # Tell the reader about the new TCP connection self.tcpReader.addConnection(newConnection) #self.core.createPlayerObject(generateUUID(),newConnection, netAddress) print ("Server: " + str(generateUUID), str(netAddress.getIpString())) else: print ("Server: Connection Failed from -", str(netAddress.getIpString())) return Task.cont def tcpReaderTask(self, task): """ Handle any data from clients by sending it to the Handlers. """ while 1: (datagram, data, opcode) = self.tcpNonBlockingRead(self.tcpReader) if opcode is MSG_NONE: # Do nothing or use it as some 'keep_alive' thing. break else: # Handle it #self.core.packetManager.handlePacket(opcode, data, datagram.getAddress()) print("Set Packet Handler to handle packets!") return Task.cont # TCP NonBlockingRead?? def tcpNonBlockingRead(self, qcr): """ Return a datagram collection and type if data is available on the queued connection udpReader """ if self.tcpReader.dataAvailable(): datagram = NetDatagram() if self.tcpReader.getData(datagram): data = DatagramIterator(datagram) opcode = data.getUint8() else: data = None opcode = MSG_NONE else: datagram = None data = None opcode = MSG_NONE # Return the datagram to keep a handle on the data return (datagram, data, opcode) # TCP Disconnection Handler def tcpDisconnectionHandler(self, task): # Check for resets if self.tcpManager.resetConnectionAvailable(): resetConnection = PointerToConnection() self.tcpManager.getResetConnection(resetConnection) print(str(resetConnection.p())) #for client in self.core.server.clients: # if self.core.server.clients[client].connection == resetConnection.p(): # del self.core.server.clients[client] # self.tcpReader.removeConnection(resetConnection.p()) # print ("Removed Connection:", resetConnection.p()) # print ('Current Clients:', self.core.server.clients) # break return Task.cont def sendPacket(self, _pkt, _connection): self.tcpWriter.send(_pkt, _connection) def sendBroadcast(self, _pkt, _skipif=None): for client in self.serverManager.clients: if _skipif == client: pass else: conn = self.serverManager.clients[client].connection self.tcpWriter.send(_pkt, conn) def addPacketToSendQueue(self, _data): # _data should contain packet and connection pass def addPacketToBroadcastQueue(self, _pkt, _connectionList): # _data should contain the pkt data and _connectionList should be the valid connections for that broadcast # Could have a grouping system that put clients together and broadcasts go per group pass def tcpQueuedSendHandlerTask(self, task): if not self.sendPacketQueue.isEmpty(): self.addPacketToSendQueue(self.sendPacketQueue.removeFromQue()) return Task.cont
class MyApp(ShowBase): def __init__(self): ShowBase.__init__(self) self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) host = "localhost" port = 9252 self.connection = self.cManager.openTCPClientConnection(host, port, 10000) self.received = 1 if self.connection: self.cReader.addConnection(self.connection) taskMgr.add(self.updateRoutine, 'updateRoutine') taskMgr.add(self.message, 'message') def message(self, task): self.option = 0 self.option = str(raw_input("1-Send integer\n2-Send string\n3-Send short\n4-Send float\n")) if self.option == "1": msg = int(100 * random.random()) - 50 request = self.intRequest(msg) self.cWriter.send(request,self.connection) print "sent ", msg taskMgr.remove('message') elif self.option == "2": msg = ''.join(random.choice('abcdefghijklmnopqrstuvwxyz') for x in range(7)) request = self.stringRequest(msg) self.cWriter.send(request,self.connection) print "sent ", msg taskMgr.remove('message') elif self.option == "3": msg = int(100 * random.random()) request = self.shortRequest(msg) self.cWriter.send(request,self.connection) print "sent ", msg taskMgr.remove('message') elif self.option == "4": msg = 100 * random.random() request = self.floatRequest(msg) self.cWriter.send(request,self.connection) print "sent ", msg taskMgr.remove('message') def intRequest(self, msg): pkg = PyDatagram() pkg.addUint16(1) pkg.addInt32(msg) return pkg def stringRequest(self, msg): pkg = PyDatagram() pkg.addUint16(2) pkg.addString(msg) return pkg def shortRequest(self, msg): pkg = PyDatagram() pkg.addUint16(3) pkg.addUint16(msg) return pkg def floatRequest(self, msg): pkg = PyDatagram() pkg.addUint16(4) pkg.addFloat32(msg) return pkg def registerRequest(self, username, password): pkg = PyDatagram() pkg.addUint16(102) pkg.addString(username) pkg.addString(password) return pkg def check(self): while self.cReader.dataAvailable(): print "data here" datagram = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram): data = PyDatagramIterator(datagram) responseCode = data.getUint16() print responseCode if responseCode == 1: self.getInt(data) elif responseCode == 2: self.getString(data) elif responseCode == 3: self.getShort(data) elif responseCode == 4: self.getFloat(data) else: print "nothing found" def getInt(self, data): msg = data.getInt32() print "recieved ", msg taskMgr.add(self.message, 'message') def getString(self, data): msg = data.getString() print "recieved ", msg taskMgr.add(self.message, 'message') def getShort(self, data): msg = data.getUint16() print "recieved ", msg taskMgr.add(self.message, 'message') def getFloat(self, data): msg = data.getFloat32() print "recieved ", msg taskMgr.add(self.message, 'message') def updateRoutine(self,task): self.check() return task.again;
class Connection(ShowBase): def __init__(self): self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) try: host = "localhost" port = 9252 self.connection = self.cManager.openTCPClientConnection( host, port, 10000) self.received = 1 if self.connection: self.cReader.addConnection(self.connection) taskMgr.add(self.updateRoutine, 'updateRoutine') # taskMgr.add(self.message, 'message') except: pass # def message(self, task): # self.option = 0 # self.option = str(raw_input("1-Send integer\n2-Send string\n3-Send short\n4-Send float\n")) # if self.option == "1": # msg = int(100 * random.random()) - 50 # request = self.intRequest(msg) # self.cWriter.send(request,self.connection) # print "sent ", msg # taskMgr.remove('message') # elif self.option == "2": # msg = ''.join(random.choice('abcdefghijklmnopqrstuvwxyz') for x in range(7)) # request = self.stringRequest(msg) # self.cWriter.send(request,self.connection) # print "sent ", msg # taskMgr.remove('message') # elif self.option == "3": # msg = int(100 * random.random()) # request = self.shortRequest(msg) # self.cWriter.send(request,self.connection) # print "sent ", msg # taskMgr.remove('message') # elif self.option == "4": # msg = 100 * random.random() # request = self.floatRequest(msg) # self.cWriter.send(request,self.connection) # print "sent ", msg # taskMgr.remove('message') def intRequest(self, msg): pkg = PyDatagram() pkg.addUint16(1) pkg.addInt32(msg) return pkg def stringRequest(self, msg): pkg = PyDatagram() pkg.addUint16(2) pkg.addString(msg) return pkg def shortRequest(self, msg): pkg = PyDatagram() pkg.addUint16(3) pkg.addUint16(msg) return pkg def floatRequest(self, msg): pkg = PyDatagram() pkg.addUint16(4) pkg.addFloat32(msg) return pkg def loginRequest(self, username, password): pkg = PyDatagram() pkg.addUint16(101) pkg.addString(username) pkg.addString(password) return pkg def registerRequest(self, username, password): pkg = PyDatagram() pkg.addUint16(103) pkg.addString(username) pkg.addString(password) return pkg def characterCreationRequest(self, username, classType): pkg = PyDatagram() pkg.addUint16(104) pkg.addString(username) pkg.addUint16(0) pkg.addUint16(classType) return pkg def chatRequest(self, message): pkg = PyDatagram() pkg.addUint16(105) pkg.addString(message) return pkg def moveRequest(self, x, y, z, h, isMoving): pkg = PyDatagram() pkg.addUint16(106) pkg.addFloat32(x) pkg.addFloat32(y) pkg.addFloat32(z) pkg.addFloat32(h) pkg.addUint16(isMoving) return pkg def check(self): while self.cReader.dataAvailable(): print "data here" datagram = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram): data = PyDatagramIterator(datagram) responseCode = data.getUint16() print responseCode if responseCode == 1: self.getInt(data) elif responseCode == 2: self.getString(data) elif responseCode == 3: self.getShort(data) elif responseCode == 4: self.getFloat(data) elif responseCode == 201: self.getLogin(data) elif responseCode == 203: self.getRegistion(data) elif responseCode == 204: self.getCharacterCreation(data) elif responseCode == 205: self.getChat(data) elif responseCode == 206: self.getMove(data) else: print "nothing found" def getInt(self, data): msg = data.getInt32() print "recieved ", msg taskMgr.add(self.message, 'message') def getString(self, data): msg = data.getString() print "recieved ", msg taskMgr.add(self.message, 'message') def getShort(self, data): msg = data.getUint16() print "recieved ", msg taskMgr.add(self.message, 'message') def getFloat(self, data): msg = data.getFloat32() print "recieved ", msg taskMgr.add(self.message, 'message') def getLogin(self, data): flag = data.getUint16() if (flag == 0): print "Invalid Login" else: listSize = data.getUint16() for i in xrange(listSize): characterName = data.getString() characterId = data.getUint16() characterType = data.getUint16() characterFaction = data.getUint16() # Need to add these to an active characters class def getRegistion(self, data): flag = data.getUint16() if (flag == 0): print "Invalid Login" else: print "Account Created" def getCharacterCreation(self, data): flag = data.getUint16() if (flag == 0): print "Invalid Character" else: listSize = data.getUint16() for i in xrange(listSize): characterName = data.getString() characterId = data.getUint16() characterType = data.getUint16() characterFaction = data.getUint16() # Need to add these to an active characters class def getChat(self, data): username = data.getString() factionId = data.getUint16() message = data.getString() def getMove(self, data): username = data.getString() x = data.getFloat32() y = data.getFloat32() z = data.getFloat32() h = data.getFloat32() isMoving = data.getUint16() def updateRoutine(self, task): self.check() return task.again
class login(DirectObject): TEXT_COLOR = (1,1,1,1) FONT_TYPE_01 = 0 TEXT_SHADOW_COLOR = (0,0,0,0.5) usernameInput = "" passwordInput = "" frame = DirectFrame() username = OnscreenText() password = OnscreenText() cpassword = OnscreenText() failed = OnscreenText() userTextbox = DirectEntry() passTextbox = DirectEntry() submitBtn = DirectButton() registerBtn = DirectButton() cancelBtn = DirectButton() registerUsername = "" registerPassword = "" registerCPassword = "" regInputUser = DirectEntry() regInputPass = DirectEntry() regInputCPass = DirectEntry() regRegisterBtn = DirectButton() regCancelBtn = DirectButton() #character selection varaiables createCharacter = DirectButton() deleteCharacter = DirectButton() selectCharacter = OnscreenText() selectCharacterTextbox = DirectEntry() selectCharacterInput='' referenceForSelection = OnscreenText() myScrolledList = DirectScrolledList() submitBtn = DirectButton() cancelBtn = DirectButton() #character deletion varaiables selectCharactertodelete = OnscreenText() deleteBtn = DirectButton() delCancelBtn = DirectButton() CharacterToDeleteTextbox = DirectEntry() referenceForDeletion = OnscreenText() CharacterToDeleteInput = ' ' #character creation varaiables v=[0] v1=[0] nameOfChar = OnscreenText() nameOfCharTextbox = DirectEntry() factionSelection = OnscreenText() nameOfCharInput ='' def __init__(self): print 'Loading Login...' # self.cManager = ConnectionManager() # self.startConnection() self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) frame = DirectFrame(frameColor=(0, 0, 0, 1), #(R,G,B,A) frameSize=(-1, 1, -1, 1),#(Left,Right,Bottom,Top) pos=(-0.5, 0, 0.5)) self.connection = self.cManager.openTCPClientConnection(Constants.SERVER_IP, Constants.SERVER_PORT, 1000) if self.connection: self.cReader.addConnection(self.connection) taskMgr.add(self.updateRoutine, 'updateRoutine-Connection', -39) taskMgr.doMethodLater(5, self.checkConnection, 'checkConnection') self.createLoginWindow() def startConnection(self): """Create a connection to the remote host. If a connection cannot be created, it will ask the user to perform additional retries. """ if self.cManager.connection == None: if not self.cManager.startConnection(): return False return True def func1(self): self.clickedSubmit() self.createSelectionWindow() def clearPassText(self): self.passTextbox.enterText('') def clearUserText(self): self.userTextbox.enterText('') def getUserText(self): self.usernameInput = self.userTextbox.get() def getPassText(self): self.passwordInput = self.passTextbox.get() def setUserText(self, textEntered): print "username: "******"password: "******"" and self.passwordInput is not ""): print "You pressed Submit", self.usernameInput, " ; ",self.passwordInput # self.cManager.sendRequest(Constants.CMSG_AUTH, self.usernameInput+" "+self.passwordInput); login_info = self.usernameInput + " " + self.passwordInput request = self.loginRequest(login_info) self.cWriter.send(request,self.connection) self.createSelectionWindow() else: print "Please enter in a username and password" def clickedCancel(self): print "You pressed Cancel" exit() def clickedRegister(self): print "You pressed Register" self.createRegisterWindow() def clickedRegRegister(self): self.registerUsername = self.regInputUser.get() self.registerPassword = self.regInputPass.get() self.registerCPassword = self.regInputCPass.get() if self.registerPassword == self.registerCPassword: print "Success (",self.registerUsername, ", ",self.registerPassword,", ",self.registerCPassword,")" #self.cManager.sendRequest(Constants.CMSG_REGISTER, self.registerUsername+" "+self.registerPassword) register_info = self.registerUsername + " " + self.registerPassword request = self.registerRequest(register_info) self.cWriter.send(request,self.connection) self.createLoginWindow() else: self.failed = OnscreenText(text="Your password does not match Confirm Password.", pos=(-0.5, 0, 1), scale=0.06,fg=(1,0.5,0.5,1), align=TextNode.ACenter,mayChange=0) self.failed.reparentTo(self.frame) print "Failed (",self.registerUsername, ", ",self.registerPassword,", ",self.registerCPassword,")" def clickedRegCancel(self): self.destroyRegisterWindow() self.createLoginWindow() def destroyLoginWindow(self): self.frame.destroy() self.username.destroy() self.password.destroy() self.userTextbox.destroy() self.passTextbox.destroy() self.submitBtn.destroy() self.registerBtn.destroy() self.cancelBtn.destroy() def destroyRegisterWindow(self): self.frame.destroy() self.username.destroy() self.password.destroy() self.cpassword.destroy() self.regInputUser.destroy() self.regInputPass.destroy() self.regInputCPass.destroy() self.cancelBtn.destroy() self.registerBtn.destroy() self.failed.destroy(); def createLoginWindow(self): self.frame = DirectFrame(frameColor=(0, 0, 0, 1), #(R,G,B,A) frameSize=(-1, 1, -1, 1),#(Left,Right,Bottom,Top) pos=(-0.5, 0, 0.5)) self.username = OnscreenText(text = "username:"******"password: "******"" ,scale=.05,pos=(.1,0,0), command=self.setUserText,initialText="username", numLines = 1,focus=1,focusInCommand=self.clearUserText, focusOutCommand=self.getUserText) self.passTextbox = DirectEntry(text = "" ,scale=.05,pos=(.1,0, -.2),command=self.setPassText,initialText="password", numLines = 1,focus=0,focusInCommand=self.clearPassText, focusOutCommand=self.getPassText) self.userTextbox.reparentTo(self.frame) self.passTextbox.reparentTo(self.frame) self.submitBtn = DirectButton(text = ("Submit", "Login", "Submit", "disabled"), scale=.08, command=self.func1, pos=(0.8, 0.0, -0.90)) self.registerBtn = DirectButton(text = ("Register", "Register", "Register", "disabled"), scale=.075, command=self.clickedRegister, pos=(0.5, 0.0, -0.90)) self.cancelBtn = DirectButton(text = ("Cancel", "Cancel", "Cancel", "disabled"), scale=.08, command=self.clickedCancel, pos=(0.2, 0.0, -0.90)) self.submitBtn.reparentTo(self.frame) self.cancelBtn.reparentTo(self.frame) self.registerBtn.reparentTo(self.frame) def createRegisterWindow(self): self.frame = DirectFrame(frameColor=(0, 0, 0, 1), #(R,G,B,A) frameSize=(-1, 1, -1, 1),#(Left,Right,Bottom,Top) pos=(-0.5, 0, 0.5)) self.username = OnscreenText(text = "Username:"******"Password: "******"Confirm Password: "******"" ,scale=.05,pos=(.1,0,0), command=self.setUserText,initialText="username", numLines = 1,focus=1,focusInCommand=self.clearUserText, focusOutCommand=self.getUserText) self.regInputPass = DirectEntry(text = "" ,scale=.05,pos=(.1,0, -.2),command=self.setPassText,initialText="password", numLines = 1,focus=0,focusInCommand=self.clearPassText, focusOutCommand=self.getPassText) self.regInputCPass = DirectEntry(text = "" ,scale=.05,pos=(.1,0, -.4),command=self.setPassText,initialText="confirm password", numLines = 1,focus=0,focusInCommand=self.clearPassText, focusOutCommand=self.getPassText) self.regInputUser.reparentTo(self.frame) self.regInputPass.reparentTo(self.frame) self.regInputCPass.reparentTo(self.frame) self.registerBtn = DirectButton(text = ("Register", "Register", "Register", "disabled"), scale=.075, command=self.clickedRegRegister, pos=(0.8, 0.0, -0.90)) self.cancelBtn = DirectButton(text = ("Cancel", "Cancel", "Cancel", "disabled"), scale=.08, command=self.clickedRegCancel, pos=(0.2, 0.0, -0.90)) self.cancelBtn.reparentTo(self.frame) self.registerBtn.reparentTo(self.frame) def check(self): while self.cReader.dataAvailable(): datagram = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram): data = PyDatagramIterator(datagram) responseCode = data.getUint16() if responseCode == 1: self.getInt(data) elif responseCode == 201: #login code if (self.getString(data)=="Unsuccessful login"): #appears if login unsuccessful print " " print "Unsuccessful login" print " " self.createLoginWindow() else: print "Your are logged in" #appear if login successful self.createLoginWindow()#appears the login options self.showRalph() elif responseCode == 203: #register code if (self.getString(data)=="Registration successful"): #appear if registration was successful print "You are now registered" print "Please login" #user must login print " " self.createLoginWindow() else: print " "#appear if registration wasn't successful print "Registration was unsuccessful. Pick a different username and please try again " print " " self.createLoginWindow()#user must attempt to register again elif responseCode == 4: self.getFloat(data) else: print "nothing found" def updateRoutine(self,task): self.check() return task.again; def checkConnection(self, task): if not self.cReader.isConnectionOk(self.connection): self.closeConnection() self.showDisconnected(0) return task.done return task.again def closeConnection(self): """Close the current connection with the remote host. If an existing connection is found, remove both the Main task, which is responsible for the heartbeat, and the Connection task, which is responsible for reading packets from the socket, then properly close the existing connection. """ if self.connection != None: taskMgr.remove('updateRoutine-Main') taskMgr.remove('updateRoutine-Connection') taskMgr.remove('checkConnection') self.cManager.closeConnection(self.connection) self.connection = None #function that unpackage the message from server def getString(self, data): msg = data.getString() return msg #package login request def loginRequest(self, login_info): pkg = PyDatagram() pkg.addUint16(101) pkg.addString(login_info) return pkg #package register request def registerRequest(self, register_info): pkg = PyDatagram() pkg.addUint16(103) pkg.addString(register_info) return def showRalph(self): self.environ = loader.loadModel("models/square") self.environ.reparentTo(render) self.environ.setPos(0,0,0) self.environ.setScale(100,100,1) self.moon_tex = loader.loadTexture("models/moon_1k_tex.jpg") self.environ.setTexture(self.moon_tex, 1) # Create the main character, Ralph self.ralph = Actor("models/ralph", {"run":"models/ralph-run", "walk":"models/ralph-walk"}) self.ralph.reparentTo(render) self.ralph.setScale(.2) self.ralph.setPos(0,0,0) #character Creation def createCreateCharWindow(self): self.frame = DirectFrame(frameColor=(0, 0, 0, 1), #(R,G,B,A) frameSize=(-3, 3, -3, 3),#(Left,Right,Bottom,Top) pos=(-0.5, 0, 0.9)) self.buttons = [ DirectRadioButton(text = ' Sword ', variable=self.v, value=[0], scale=0.07, pos=(-0.4,0,0.32), command=self.setText), DirectRadioButton(text = ' Axe ', variable=self.v, value=[1], scale=0.07, pos=(0.2,0,0.32), command=self.setText) ] for button in self.buttons: button.setOthers(self.buttons) self.nameOfChar = OnscreenText(text = "Name The Character :", pos = (-0.2, -0.75), scale = 0.08,fg=(1,0.5,0.5,1),align=TextNode.ACenter,mayChange=0) self.nameOfChar.reparentTo(self.frame) self.nameOfCharTextbox = DirectEntry(text = "" ,scale=.07,pos=(0.25,0, -.75),command=self.setnameOfChar,initialText="name of character", numLines = 1,focus=0,focusInCommand=self.clearnameOfChar, focusOutCommand=self.getnameOfChar) self.nameOfCharTextbox.reparentTo(self.frame) self.factionSelection = OnscreenText(text = "Faction Selection :", pos = (-0.15, -0.95), scale = 0.08,fg=(1,0.5,0.5,1),align=TextNode.ACenter,mayChange=0) self.factionSelection.reparentTo(self.frame) self.factionBtns = [ DirectRadioButton(text = ' Blue ', variable=self.v1, value=[0], scale=0.07, pos=(-0.05,0,-0.05), command=self.setfaction), DirectRadioButton(text = ' Red ', variable=self.v1, value=[1], scale=0.07, pos=(0.3,0,-0.05), command=self.setfaction) ] for button1 in self.factionBtns: button1.setOthers(self.factionBtns) self.okForCreateBtn = DirectButton(text = ("Ok", "Ok", "Ok", "disabled"), scale=.08, command=self.clickedOkForCreateBtn, pos=(-0.05, 0.0, -1.25)) self.cancelForCreateBtn = DirectButton(text = ("Cancel", "Cancel", "Cancel", "disabled"), scale=.08, command=self.clickedCancelForCreateBtn, pos=(0.4, 0.0, -1.25)) self.okForCreateBtn.reparentTo(self.frame) self.cancelForCreateBtn.reparentTo(self.frame) def destroyCreateCharWindow(self): self.frame.destroy() self.nameOfChar.destroy() self.nameOfCharTextbox.destroy() self.factionSelection.destroy() self.okForCreateBtn.destroy() self.cancelForCreateBtn.destroy() def clearnameOfChar(self): self.nameOfCharTextbox.enterText('') def getnameOfChar(self): self.nameOfCharInput = self.nameOfCharTextbox.get() def setnameOfChar(self, textEntered): print "name Of Char: ",textEntered self.nameOfChar = textEntered def clickedOkForCreateBtn(self): print "you have pressed the ok button for creating a character" def clickedCancelForCreateBtn(self): print "you have press the cancel button from the create character frame" self.destroyCreateCharWindow() self.createSelectionWindow() def setText(status=None): bk_text = "CurrentValue " def setfaction(status=None): bk_text = "CurrentValue " #character deletion def createDeleteCharWindow(self): self.frame = DirectFrame(frameColor=(0, 0, 0, 1), #(R,G,B,A) frameSize=(-3, 3, -3, 3),#(Left,Right,Bottom,Top) pos=(-0.5, 0, 0.9)) self.selectCharactertodelete = OnscreenText(text = "Select Character :", pos = (-0.02, -0.35), scale = 0.08,fg=(1,0.5,0.5,1),align=TextNode.ACenter,mayChange=0) self.selectCharactertodelete.reparentTo(self.frame) self.selectCharacterToDeleteTextbox = DirectEntry(text = "" ,scale=.07,pos=(0.45,0, -.35),command=self.setselectCharacterToDelete,initialText="name of character", numLines = 1,focus=0,focusInCommand=self.clearselectCharacterToDelete, focusOutCommand=self.getselectCharacterToDelete) self.selectCharacterToDeleteTextbox.reparentTo(self.frame) self.referenceForDeletion = OnscreenText(text = "Reference to Character List:", pos = (-0.15, -0.75), scale = 0.08,fg=(1,0.5,0.5,1),align=TextNode.ACenter,mayChange=0) self.referenceForDeletion.reparentTo(self.frame) self.deleteScrolledList = DirectScrolledList( decButton_pos= (0.35, 0, 0.53), decButton_text = "Dec", decButton_text_scale = 0.04, decButton_borderWidth = (0.005, 0.005), incButton_pos= (0.35, 0, -0.02), incButton_text = "Inc", incButton_text_scale = 0.04, incButton_borderWidth = (0.005, 0.005), pos = (0.7, 0, -0.99), numItemsVisible = 4, forceHeight = .11, itemFrame_frameSize = (-0.6, 0.6, -0.37, 0.11), itemFrame_pos = (0.35, 0, 0.4)) for playerchar in ['xxxbluesword', 'xxxblueaxe', 'xxxredsword', 'xxxredsword01','xxx_red_sword04']: l = DirectLabel(text = playerchar, text_scale=0.1) self.deleteScrolledList.addItem(l) self.deleteScrolledList.reparentTo(self.frame) self.deleteBtn = DirectButton(text = ("Delete", "Delete", "Delete", "disabled"), scale=.08, command=self.clickedDelete, pos=(-0.2, 0.0, -1.25)) self.delCancelBtn = DirectButton(text = ("Cancel", "Cancel", "Cancel", "disabled"), scale=.08, command=self.clickedDelCancel, pos=(0.3, 0.0, -1.25)) self.deleteBtn.reparentTo(self.frame) self.delCancelBtn.reparentTo(self.frame) def destroyDeleteCharWindow(self): self.frame.destroy() self.selectCharactertodelete.destroy() self.deleteBtn.destroy() self.delCancelBtn.destroy() self.selectCharacterToDeleteTextbox.destroy() self.referenceForDeletion.destroy() def clearselectCharacterToDelete(self): self.selectCharacterToDeleteTextbox.enterText('') def getselectCharacterToDelete(self): self.selectCharacterToDeleteInput = self.nameOfCharTextbox.get() def setselectCharacterToDelete(self, textEntered): print "name Of Char: ",textEntered self.selectCharacterToDelete = textEntered def clickedDelete(self): print "You pressed delete a character" def clickedDelCancel(self): print "to go back to slection menu" self.destroyDeleteCharWindow() self.createSelectionWindow() #character Selection def createSelectionWindow(self): self.frame = DirectFrame(frameColor=(0, 0, 0, 1), #(R,G,B,A) frameSize=(-3, 3, -3, 3),#(Left,Right,Bottom,Top) pos=(-0.5, 0, 0.9)) self.createCharacter = DirectButton(text = ("Create Character","Create Character","Create Character","disabled"), scale=.08, command = self.clickedCreateChar, pos=(-0.14,0.0,-0.25)) self.deleteCharacter = DirectButton(text = ("Delete Character","Delete Character","Delete Character","disabled"), scale=.08, command = self.clickedDeleteChar, pos=(-0.14,0.0,-0.40)) self.createCharacter.reparentTo(self.frame) self.deleteCharacter.reparentTo(self.frame) self.selectCharacter = OnscreenText(text = "Select Character :", pos = (-0.12, -0.55), scale = 0.08,fg=(1,0.5,0.5,1),align=TextNode.ACenter,mayChange=0) self.selectCharacter.reparentTo(self.frame) self.myScrolledList = DirectScrolledList( decButton_pos= (0.35, 0, 0.53), decButton_text = "Dec", decButton_text_scale = 0.04, decButton_borderWidth = (0.005, 0.005), incButton_pos= (0.35, 0, -0.02), incButton_text = "Inc", incButton_text_scale = 0.04, incButton_borderWidth = (0.005, 0.005), pos = (0.05, 0, -0.3), numItemsVisible = 4, forceHeight = .11, itemFrame_frameSize = (-0.6, 0.6, -0.37, 0.11), itemFrame_pos = (0.35, 0, 0.4), ) self.selectCharacterTextbox = DirectEntry(text = "" ,scale=.07,pos=(0.28,0, -.55),command=self.setselectCharacterTextbox,initialText="name of character", numLines = 1,focus=0,focusInCommand=self.clearselectCharacterTextbox, focusOutCommand=self.getselectCharacterTextbox) self.selectCharacterTextbox.reparentTo(self.frame) self.referenceForSeletion = OnscreenText(text = "Reference to Character List:\n that already exists", pos = (-0.30, -0.75), scale = 0.08,fg=(1,0.5,0.5,1),align=TextNode.ACenter,mayChange=0) self.referenceForSeletion.reparentTo(self.frame) for playerchar in ['xxxbluesword', 'xxxblueaxe', 'xxxredsword', 'xxxredsword01','xxx_red_sword04']: l = DirectLabel(text = playerchar, text_scale=0.1) self.myScrolledList.addItem(l) self.submitBtn = DirectButton(text = ("Start", "Start", "Start", "disabled"), scale=.08, command=self.clickedSubmit, pos=(-0.2, 0.0, -1.45)) self.cancelBtn = DirectButton(text = ("Cancel", "Cancel", "Cancel", "disabled"), scale=.08, command=self.clickedCancel, pos=(0.3, 0.0, -1.45)) self.submitBtn.reparentTo(self.frame) self.cancelBtn.reparentTo(self.frame) def destroySelectionWindow(self): self.frame.destroy() self.selectCharacter.destroy() self.createCharacter.destroy() self.deleteCharacter.destroy() self.submitBtn.destroy() self.cancelBtn.destroy() def clearselectCharacterTextbox(self): self.selectCharacterTextbox.enterText('') def getselectCharacterTextbox(self): self.selectCharacterTextbox = self.selectCharacterTextbox.get() def setselectCharacterTextbox(self, textEntered): print "name Of Char: ",textEntered self.selectCharacterTextbox = textEntered def clickedCreateChar(self): print "You pressed create a new character" self.destroySelectionWindow() self.createCreateCharWindow() def clickedDeleteChar(self): print "You pressed delete a character" self.destroySelectionWindow() self.createDeleteCharWindow() def clickedSubmit(self): print "you pressed start button" def clickedCancel(self): print "You pressed Cancel"
class MyApp(ShowBase): uname = None def __init__(self): ShowBase.__init__(self) self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) host = "localhost"; port = 6002; self.connection = self.cManager.openTCPClientConnection(host, port, 10000) self.received = 1 if self.connection: self.cReader.addConnection(self.connection) #taskMgr.add(self.updateRoutine, 'updateRoutine') # LOGIN Request Starts self.uname = raw_input('Enter username :'******'Enter password :'******'Login') if(self.received): print "->Client request:" # Send a request to the server myPyDatagram101 = PyDatagram() prot = 101 myPyDatagram101.addUint16(prot) myPyDatagram101.addString(self.uname) myPyDatagram101.addString(self.password) self.cWriter.send(myPyDatagram101,self.connection) self.received = 0 taskMgr.add(self.receiveResponse101,'Login') def sendRequest101(self): if(self.received): print "->Client request:" # Send a request to the server myPyDatagram101 = PyDatagram() prot = 101 myPyDatagram101.addUint16(prot) myPyDatagram101.addString(self.uname) myPyDatagram101.addString(self.password) self.cWriter.send(myPyDatagram101,self.connection) self.received = 0 def receiveResponse101(self,task): while self.cReader.dataAvailable(): datagram = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram): self.myIterator = PyDatagramIterator(datagram) print "<-Server response:" print self.myIterator.getUint16() self.msg = self.myIterator.getUint32() self.l = self.myIterator.getUint32() if self.msg is not None: if self.l is not 0: for x in range(0,self.l): print self.myIterator.getString() print self.myIterator.getUint32() print self.myIterator.getUint32() print self.msg, " received" #raw_input("Press Enter to continue...") self.received = 0 taskMgr.remove('Login') #1-Character creatopm #taskMgr.add(self.sendRequest104, 'CharacterCreation') #2-heartbeat of playgame after login MyApp.sendRequest113(self) return task.again # LOGIN Request End # CHARACTER CREATION Starts def sendRequest104(self,task): if(self.received): print "->Client request:" # Send a request to the server myPyDatagram = PyDatagram() prot = 104 cname = raw_input('Character Name :') faction_id_104 = raw_input('press 0 for Red Or 1 for Blue ? :') classType_104 = raw_input('press 0 for Axe Or 1 for Sword ? :') myPyDatagram.addUint16(prot) myPyDatagram.addString(cname) myPyDatagram.addUint32(faction_id_104) myPyDatagram.addUint32(classType_104) self.cWriter.send(myPyDatagram,self.connection) print "104 sent" self.received = 0 taskMgr.add(self.receiveResponse104,"characterresponse") def receiveResponse104(self,task): while self.cReader.dataAvailable(): datagram = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram): self.myIterator1 = PyDatagramIterator(datagram) print '------' print self.myIterator1.getUint16() self.msg = self.myIterator1.getUint32() if self.msg is not None: print "<-Server response:" print self.msg, " received" raw_input("Press Enter to continue...") self.received = 0 taskMgr.remove('CharacterCreation') taskMgr.add(self.sendRequest106, 'move') return task.again #CHARACTER CREATION Ends # Move Starts def sendRequest106(self,task): if(self.received): print "->Client request:" # Send a request to the server myPyDatagram106 = PyDatagram() prot = 106 xpos = raw_input('X Position :') ypos = raw_input('Y Position :') zpos = raw_input('Z Position :') hpos = raw_input('Heading (0 to 360):') ismoving = raw_input('Moving ? -- 0 for NO , 1 for YES :') myPyDatagram106.addUint16(prot) myPyDatagram106.addUint32(xpos) myPyDatagram106.addUint32(ypos) myPyDatagram106.addUint32(zpos) myPyDatagram106.addUint32(hpos) myPyDatagram106.addUint32(ismoving) self.cWriter.send(myPyDatagram106,self.connection) self.received = 0 taskMgr.add(self.receiveResponse106,"characterresponse") def receiveResponse106(self,task): while self.cReader.dataAvailable(): datagram6 = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram6): myIterator = PyDatagramIterator(datagram6) print myIterator.getUint16() msg = myIterator.getString() if msg is not None: print "<-Server response:" print msg print myIterator.getUint32() print myIterator.getUint32() print myIterator.getUint32() print myIterator.getUint32() print myIterator.getUint32() raw_input("Press Enter to continue...") self.received = 1 # Attack #raw_input("Press Enter to continue...") taskMgr.add(self.sendRequest108, 'health') return task.again #Move Ends #Change Health Starts def sendRequest108(self,task): if(self.received): print "->Client request:" # Send a request to the server myPyDatagram108 = PyDatagram() prot = 108 change_Health = raw_input('Change in health (-100 to 100):') myPyDatagram108.addUint16(prot) myPyDatagram108.addUint32(change_Health) self.cWriter.send(myPyDatagram108,self.connection) self.received = 0 taskMgr.add(self.receiveResponse108,"healthresponse") def receiveResponse108(self,task): while self.cReader.dataAvailable(): datagram8 = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram8): myIterator = PyDatagramIterator(datagram8) print myIterator.getUint16() msg = myIterator.getString() if msg is not None: print "<-Server response:" print msg print myIterator.getUint32() self.received = 1 # CP State raw_input("Press Enter to continue...") taskMgr.add(self.sendRequest107, 'attack') #Change Health Ends return task.again # Attack Starts def sendRequest107(self,task): if(self.received): print "->Client request:" # Send a request to the server myPyDatagram107 = PyDatagram() prot = 107 attackId = raw_input('Attack Id (0 or 1):') myPyDatagram107.addUint16(prot) myPyDatagram107.addUint32(attackId) self.cWriter.send(myPyDatagram107,self.connection) #print " sent" self.received = 0 taskMgr.add(self.receiveResponse108,"attackresponse") def receiveResponse107(self,task): while self.cReader.dataAvailable(): datagram7 = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram7): myIterator = PyDatagramIterator(datagram7) print myIterator.getUint16() msg = myIterator.getString() if msg is not None: print "<-Server response:" print msg print myIterator.getUint32() raw_input("Press Enter to continue...") self.received = 1 # Change Health taskMgr.add(self.sendRequest112, 'CP Capture') return task.again #Attack Ends #CP Capture Starts def sendRequest112(self,task): if(self.received): print "->Client request:" # Send a request to the server myPyDatagram112 = PyDatagram() prot = 112 CP_id = raw_input('Control Point ID (1 to 5): ') faction_id = raw_input('press 0 for Red Or 1 for Blue ? :') myPyDatagram112.addUint16(prot) myPyDatagram112.addUint32(CP_id) myPyDatagram112.addUint32(faction_id) self.cWriter.send(myPyDatagram112,self.connection) #print " sent" self.received = 0 taskMgr.add(self.receiveResponse112,"CPCaptureRes") def receiveResponse112(self,task): while self.cReader.dataAvailable(): datagram12 = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram12): myIterator = PyDatagramIterator(datagram12) print myIterator.getUint16() msg = myIterator.getUint32() if msg is not None: print "<-Server response:" print msg print myIterator.getUint32() raw_input("Press Enter to continue...") self.received = 1 #HeartBeat #raw_input("Press Enter to continue...") #taskMgr.add(self.communicate105, 'chat') #CP Capture Ends # CHAT Starts def communicate105(self,task): #print "communicate" self.sendRequest105() self.receiveResponse105(task) return task.again; def sendRequest105(self): if(self.received): print "->Client request:" # Send a request to the server myPyDatagram105 = PyDatagram() prot = 105 chat = raw_input('Insert Chat Message :') myPyDatagram105.addUint16(prot) myPyDatagram105.addString(chat) self.cWriter.send(myPyDatagram105,self.connection) print " sent" self.received = 0 def receiveResponse105(self,task): print "<-Server response:" while self.cReader.dataAvailable(): datagram5 = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram5): myIterator = PyDatagramIterator(datagram5) print myIterator.getUint16() msg = myIterator.getUint16() print msg, " received" if msg is not None: raw_input("Press Enter to continue...") self.received = 1 # Move raw_input("Press Enter to continue...") taskMgr.add(self.communicate111, 'CP state') #CHAT Ends #CP State Starts def communicate111(self,task): #print "communicate" self.sendRequest111() self.receiveResponse111(task) return task.again; def sendRequest111(self): if(self.received): print "->Client request:" # Send a request to the server myPyDatagram111 = PyDatagram() prot = 111 CP_id = raw_input('Control Point ID (1 to 5): ') CP_state = raw_input('Control Point state (1 red, 2 blue, 3 purple): ') myPyDatagram111.addUint16(prot) myPyDatagram111.addUint16(CP_id) myPyDatagram111.addUint16(CP_state) self.cWriter.send(myPyDatagram111,self.connection) print " sent" self.received = 0 def receiveResponse111(self,task): print "<-Server response:" while self.cReader.dataAvailable(): datagram11 = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram11): myIterator = PyDatagramIterator(datagram11) print myIterator.getUint16() msg = myIterator.getUint16() print msg, " received" if msg is not None: raw_input("Press Enter to continue...") self.received = 1 # CP Capture raw_input("Press Enter to continue...") taskMgr.add(self.communicate102, 'Logout') #CP State Ends # LOGOUT Starts def communicate102(self,task): #print "communicate" self.sendRequest102() self.receiveResponse102(task) return task.again; def sendRequest102(self): if(self.received): print "->Client request:" # Send a request to the server myPyDatagram102 = PyDatagram() prot = 102 myPyDatagram102.addUint16(prot) self.cWriter.send(myPyDatagram102,self.connection) print " sent" self.received = 0 def receiveResponse102(self,task): print "<-Server response:" while self.cReader.dataAvailable(): datagram2 = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram2): myIterator = PyDatagramIterator(datagram2) print myIterator.getUint16() msg = myIterator.getUint16() print msg, " received" if msg is not None: raw_input("Press Enter to continue...") self.received = 1 # Register raw_input("Press Enter to continue...") taskMgr.add(self.communicate301, 'Heartbeat') #LOGOUT Ends #HeartBeat Starts def communicate301(self): #print "communicate" self.sendRequest301() self.receiveResponse301() #return task.again; def sendRequest301(self,task): if(self.received): print "->Client request:" # Send a request to the server myPyDatagram301 = PyDatagram() prot = 301 myPyDatagram301.addUint16(prot) self.cWriter.send(myPyDatagram301,self.connection) self.received = 0 return task.again def receiveResponse301(self): while self.cReader.dataAvailable(): datagram301 = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram301): myIterator = PyDatagramIterator(datagram301) p = myIterator.getUint16() if p == 213: un = myIterator.getString() cname = myIterator.getString() ctype = myIterator.getUint32() cteam = myIterator.getUint32() if un == MyApp.uname: abc = 'abc' else: print cname+' just joined a game......!! hurray' #print msg, " received" self.received = 1 #HeartBeat Ends #heartbeat def sendRequest113(self): if(self.received): print "->Client request:" # Send a request to the server myPyDatagram113 = PyDatagram() prot = 113 myPyDatagram113.addUint16(prot) print MyApp.uname+'-------' if MyApp.uname == 'chintan': myPyDatagram113.addUint32(18) elif MyApp.uname == 'paras': myPyDatagram113.addUint32(35) else: myPyDatagram113.addUint32(3) self.cWriter.send(myPyDatagram113,self.connection) self.received = 0 #taskMgr.add(self.updateRoutine,'update113') #taskMgr.doMethodLater(1,self.sendRequest301,'HeatBeat') MyApp.retrieve113(self) def retrieve113(self): taskMgr.add(self.updateRoutine,'update113') taskMgr.doMethodLater(1,self.sendRequest301,'HeatBeat') def updateRoutine(self,task): self.receiveResponse301() return task.again;
cReader.addConnection(newConnection) # Begin reading connection return Task.cont def tskReaderPolling(taskdata): if cReader.dataAvailable(): datagram = NetDatagram() # catch the incoming data in this instance # Check the return value; if we were threaded, someone else could have # snagged this data before we did if cReader.getData(datagram): myProcessDataFunction(datagram) return Task.cont taskMgr.add(tskListenerPolling, "Poll the connection listener", -39) taskMgr.add(tskReaderPolling, "Poll the connection reader", -40) port_address = 9099 # same for client and server # a valid server URL. You can also use a DNS name # if the server has one, such as "localhost" or "panda3d.org" ip_address = "localhost" # how long until we give up trying to reach the server? timeout_in_miliseconds = 3000 # 3 seconds myConnection = cManager.openTCPClientConnection(ip_address, port_address, timeout_in_miliseconds) if myConnection: cReader.addConnection(myConnection) # receive messages from server
class OldNetworkSystem(sandbox.EntitySystem): def init(self, port=2000, server="127.0.0.1", serverPort=1999, backlog=1000, compress=False): self.packetCount = 0 self.port = port self.serverPort = serverPort self.serverIP = server self.serverAddress = NetAddress() self.serverAddress.setHost(server, serverPort) self.cManager = QueuedConnectionManager() self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) self.udpSocket = self.cManager.openUDPConnection(self.port) self.cReader.addConnection(self.udpSocket) def begin(self): if self.cReader.dataAvailable(): datagram = NetDatagram() # catch the incoming data in this instance # Check the return value; if we were threaded, someone else could have # snagged this data before we did if self.cReader.getData(datagram): myIterator = PyDatagramIterator(datagram) msgID = myIterator.getUint8() #If not in our protocol range then we just reject if msgID < 0 or msgID > 200: return #Order of these will need to be optimized later #We now pull out the rest of our headers remotePacketCount = myIterator.getUint8() ack = myIterator.getUint8() acks = myIterator.getUint16() hashID = myIterator.getUint16() sourceOfMessage = datagram.getConnection() if msgID == protocol.NEW_SHIP: log.info("New ship") playerPilotID = myIterator.getUint16() shipID = myIterator.getUint16() shipName = myIterator.getString() health = myIterator.getUint8() position = Point3(myIterator.getFloat32(), myIterator.getFloat32(), myIterator.getFloat32()) linearVelocity = Vec3(myIterator.getFloat32(), myIterator.getFloat32(), myIterator.getFloat32()) rotiation = VBase3(myIterator.getFloat32(), myIterator.getFloat32(), myIterator.getFloat32()) angularVelocity = Vec3(myIterator.getFloat32(), myIterator.getFloat32(), myIterator.getFloat32()) ship = sandbox.addEntity(shipID) component = ships.PilotComponent() component.accountEntityID = playerPilotID ship.addComponent(component) component = ships.BulletPhysicsComponent() messenger.send("addSpaceShip", [component, shipName, position, linearVelocity]) ship.addComponent(component) component = ships.ThrustComponent() ship.addComponent(component) component = ships.InfoComponent() component.health = health component.name = shipName ship.addComponent(component) elif msgID == protocol.PLAYER_MOVED_SHIP: log.debug("Player moved ship") accountID = myIterator.getUint16() shipID = myIterator.getUint16() print sandbox.components[shipID] universals.shipNode = sandbox.components[shipID][ships.BulletPhysicsComponent].nodePath elif msgID == protocol.LOGIN_ACCEPTED: log.info("Login accepted") entityID = myIterator.getUint8() universals.day = myIterator.getFloat32() elif msgID == protocol.LOGIN_DENIED: log.info("Login failed") def genBasicData(self, proto): myPyDatagram = PyDatagram() myPyDatagram.addUint8(proto) myPyDatagram.addUint8(self.packetCount) myPyDatagram.addUint8(0) myPyDatagram.addUint16(0) myPyDatagram.addUint16(0) self.packetCount += 1 return myPyDatagram def sendLogin(self, username, hashpassword): datagram = self.genBasicData(protocol.LOGIN) datagram.addString(username) datagram.addString(hashpassword) universals.log.debug("sending login") self.sendData(datagram) def sendData(self, datagram): sent = self.cWriter.send(datagram, self.udpSocket, self.serverAddress) while not sent: print "resending" sent = self.cWriter.send(datagram, self.udpSocket, self.serverAddress)
class OldNetworkSystem(sandbox.EntitySystem): def init(self, port=1999, backlog=1000, compress=False): log.debug("Initing Network System") self.accept("broadcastData", self.broadcastData) self.port = port self.backlog = backlog self.compress = compress self.cManager = QueuedConnectionManager() self.cReader = QueuedConnectionReader(self.cManager, 0) #self.cReader.setRawMode(True) self.cWriter = ConnectionWriter(self.cManager, 0) self.udpSocket = self.cManager.openUDPConnection(self.port) self.cReader.addConnection(self.udpSocket) self.activePlayers = [] # PlayerComponent self.activeConnections = {} # {NetAddress : PlayerComponent} self.lastAck = {} # {NetAddress: time} self.startPolling() self.accept("shipGenerated", self.shipGenerated) def startPolling(self): #taskMgr.add(self.tskReaderPolling, "serverListenTask", -40) taskMgr.doMethodLater(10, self.activeCheck, "activeCheck") #def tskReaderPolling(self, taskdata): def begin(self): if self.cReader.dataAvailable(): datagram = NetDatagram() # catch the incoming data in this instance # Check the return value; if we were threaded, someone else could have # snagged this data before we did if self.cReader.getData(datagram): myIterator = PyDatagramIterator(datagram) msgID = myIterator.getUint8() #If not in our protocol range then we just reject if msgID < 0 or msgID > 200: return self.lastAck[datagram.getAddress()] = datetime.datetime.now() #TODO Switch to ip address and port #Order of these will need to be optimized later #We now pull out the rest of our headers remotePacketCount = myIterator.getUint8() ack = myIterator.getUint8() acks = myIterator.getUint16() hashID = myIterator.getUint16() if msgID == protocol.LOGIN: username = myIterator.getString() password = myIterator.getString() if username not in accountEntities: entity = sandbox.createEntity() component = AccountComponent() component.name = username component.passwordHash = password if not accountEntities: component.owner = True component.address = datagram.getAddress() entity.addComponent(component) accountEntities[username] = entity.id log.info("New player " + username + " logged in.") # self.activePlayers.append(component) self.activeConnections[component.address] = component ackDatagram = protocol.loginAccepted(entity.id) self.sendData(ackDatagram, datagram.getAddress()) #TODO: Send initial states? messenger.send("newPlayerShip", [component, entity]) else: component = sandbox.entities[accountEntities[username]].get_component(AccountComponent) if component.passwordHash != password: log.info("Player " + username + " has the wrong password.") else: component.connection = datagram.getConnection() log.info("Player " + username + " logged in.") def activeCheck(self, task): """Checks for last ack from all known active conenctions.""" for address, lastTime in self.lastAck.items(): if (datetime.datetime.now() - lastTime).seconds > 30: component = self.activeConnections[address] #TODO: Disconnect return task.again def sendData(self, datagram, address): self.cWriter.send(datagram, self.udpSocket, address) def broadcastData(self, datagram): # Broadcast data out to all activeConnections #for accountID in accountEntities.items(): #sandbox.entities[accountID].get_component() for addr in self.activeConnections.keys(): self.sendData(datagram, addr) def processData(self, netDatagram): myIterator = PyDatagramIterator(netDatagram) return self.decode(myIterator.getString()) def shipGenerated(self, ship): datagram = protocol.newShip(ship) log.info("Checking if new ship is valid for udp:", self.cWriter.isValidForUdp(datagram)) self.broadcastData(datagram) datagram = protocol.movedShip(ship) address = self.getAddress(ship.get_component(ships.PilotComponent).accountEntityID) self.sendData(datagram, address) def getAddress(self, entityID): return sandbox.components[entityID][AccountComponent].address
class TCP(): def __init__(self, _core): print("TCP Protocol Startup...") self.core = _core self.config = self.core.client.config # Connection on TCP self.tcpConnection = None def start(self): self.setupTCP() self.startTCPTasks() def setupTCP(self): self.tcpManager = QueuedConnectionManager() self.tcpReader = QueuedConnectionReader(self.tcpManager, 0) self.tcpWriter = ConnectionWriter(self.tcpManager, 0) def startTCPTasks(self): taskMgr.add(self.tcpReaderTask, "tcpReaderTask", -10) print("TCP Reader Started") def tcpReaderTask(self, task): """ Handle any data from clients by sending it to the Handlers. """ while 1: (datagram, data, opcode) = self.tcpNonBlockingRead(self.tcpReader) if opcode is MSG_NONE: # Do nothing or use it as some 'keep_alive' thing. break else: # Handle it self.core.packetManager.handlePacket(opcode, data) return Task.cont # TCP NonBlockingRead?? def tcpNonBlockingRead(self, qcr): """ Return a datagram collection and type if data is available on the queued connection udpReader """ if self.tcpReader.dataAvailable(): datagram = NetDatagram() if self.tcpReader.getData(datagram): data = DatagramIterator(datagram) opcode = data.getUint8() else: data = None opcode = MSG_NONE else: datagram = None data = None opcode = MSG_NONE # Return the datagram to keep a handle on the data return (datagram, data, opcode) def connectToServer(self, _ip, _port): self.tcpConnection = self.tcpManager.openTCPClientConnection( _ip, _port, 1000) if self.tcpConnection != None: self.tcpReader.addConnection(self.tcpConnection)
class Register_Page(DirectObject): def __init__(self): base.setBackgroundColor( 254, 254, 254 ) # sets the background color to black because the # default grey color bugs me for some reason self.loginScreen() # draws the login screen self.usernameBox['focus'] = 1 # sets the cursor to the username field by default self.accept('tab', self.cycleLoginBox) # enables the user to cycle through the text fields with the tab key # this is a standard feature on most login forms self.accept('enter', self.attemptLogin) # submits the login form, or you can just click the Login button def loginScreen(self): # creates a basic login screen that asks for a username/password boxloc = Vec3(0.0, 0.0, 0.0) # all items in the login form will have a position relative to this # this makes it easier to shift the entire form around once we have # some graphics to display with it without having to change the # positioning of every form element # p is the position of the form element relative to the boxloc # coordinates set above it is changed for every form element p = boxloc + Vec3(-0.5, 0, 0.0) self.username = OnscreenText(text = "Username:"******"Username: "******"" , pos = p, scale=.05, initialText="", numLines = 1) # Username textbox where you type in your username p = boxloc + Vec3(-0.49, -0.1, 0.0) self.password = OnscreenText(text = "Password:"******"Password: "******"Confirm password:"******"Password: "******"" , pos = p, scale=.05, initialText="", numLines = 1, obscured = 1) # Password textbox where you type in your password # Note - obscured = 1 denotes that all text entered will be replaced # with a * like a standard password box p = boxloc + Vec3(-0.1, 0, -0.2) self.password2Box = DirectEntry(text = "" , pos = p, scale=.05, initialText="", numLines = 1, obscured = 1) # Password textbox where you type in your password # Note - obscured = 1 denotes that all text entered will be replaced # with a * like a standard password box p = boxloc + Vec3(0, 0, -0.3) self.registerButton = DirectButton(text = ("Register", "Register", "Register", "Register"), pos = p, scale = 0.075, command=self.attemptLogin) # The 'Login' button that will trigger the attemptLogin function # when clicked p = boxloc + Vec3(-0.5, -0.5, 0) self.statusText = OnscreenText(text = "", pos = p, scale = 0.05, fg = (1, 0, 0, 1), align=TextNode.ALeft) # A simple text object that you can display an error/status messages # to the user def updateStatus(self, statustext): self.statusText.setText(statustext) # all this does is change the status text. def attemptLogin(self): # checks to make sure the user inputed a username and password: # if they didn't it will spit out an error message # if they did, it will try to connect to the login server # (under construction) if(self.usernameBox.get() == ""): if(self.passwordBox.get() == ""): self.updateStatus("ERROR: You must enter a username and password before logging in.") else: self.updateStatus("ERROR: You must specify a username") self.passwordBox['focus'] = 0 self.usernameBox['focus'] = 1 elif(self.passwordBox.get() == ""): self.updateStatus("ERROR: You must enter a password") self.usernameBox['focus'] = 0 self.passwordBox['focus'] = 1 elif(self.password2Box.get() == ""): self.updateStatus("ERROR: You must confirm the password") self.passwordBox['focus'] = 0 self.password2Box['focus'] = 1 elif(self.passwordBox.get() != self.password2Box.get()): self.updateStatus("ERROR: Wrong confirmed password, please enter password again") self.passwordBox.set("") self.password2Box.set("") self.passwordBox['focus'] = 1 self.password2Box['focus'] = 0 self.usernameBox['focus'] = 0 else: self.updateStatus("Attempting to login...") print "Attempting to connect to Server with credentials: (" + self.usernameBox.get() + ", " + self.passwordBox.get() + ")" # this is where the networking code will get put in self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) HOST = "localhost"; PORT = 1234; self.connection = self.cManager.openTCPClientConnection(HOST, PORT, 10000) self.received = 1 if self.connection: self.cReader.addConnection(self.connection) #taskMgr.add(self.updateRoutine, 'updateRoutine') taskMgr.doMethodLater(3, self.updateRoutine, 'updateRoutine') def cycleLoginBox(self): # function is triggered by the tab key so you can cycle between # the two input fields like on most login screens # IMPORTANT: When you change the focus to one of the text boxes, # you have to unset the focus on the other textbox. If you do not # do this Panda seems to get confused. if(self.passwordBox['focus'] == 1): self.passwordBox['focus'] = 0 self.password2Box['focus'] = 1 self.usernameBox['focus'] = 0 elif(self.usernameBox['focus'] == 1): self.usernameBox['focus'] = 0 self.passwordBox['focus'] = 1 self.password2Box['focus'] = 0 elif(self.password2Box['focus'] == 1): self.passwordBox['focus'] = 0 self.password2Box['focus'] = 0 self.usernameBox['focus'] = 1
class Server(DirectObject): # TODO: Perhaps a better way to do this? handleNewConnection = None handleLostConnection = None def __init__(self, port, backlog=1000, compress=False): DirectObject.__init__(self) self.port = port self.compress = compress self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) self.passedData = [] self.connect(port, backlog) self.startPolling() def connect(self, port, backlog): # Bind to our socket tcpSocket = self.cManager.openTCPServerRendezvous(port, backlog) self.cListener.addConnection(tcpSocket) def startPolling(self): self.addTask(self.tskListenerPolling, "serverListenTask", -40) self.addTask(self.tskDisconnectPolling, "serverDisconnectTask", -39) def tskListenerPolling(self, task): if self.cListener.newConnectionAvailable(): rendezvous = PointerToConnection() netAddress = NetAddress() newConnection = PointerToConnection() if self.cListener.getNewConnection(rendezvous, netAddress, newConnection): newConnection = newConnection.p() newConnection.setNoDelay(True) newConnection.setKeepAlive(True) if self.handleNewConnection: self.handleNewConnection(newConnection) self.cReader.addConnection( newConnection) # Begin reading connection return Task.cont def tskDisconnectPolling(self, task): while self.cManager.resetConnectionAvailable(): connPointer = PointerToConnection() self.cManager.getResetConnection(connPointer) connection = connPointer.p() # Remove the connection we just found to be "reset" or "disconnected" self.cReader.removeConnection(connection) if self.handleLostConnection: self.handleLostConnection(connection) return Task.cont def processData(self, netDatagram): myIterator = PyDatagramIterator(netDatagram) return self.decode(myIterator.getString()) def encode(self, data, compress=False): # encode(and possibly compress) the data with rencode return rencode.dumps(data, compress) def decode(self, data): # decode(and possibly decompress) the data with rencode return rencode.loads(data) def sendData(self, data, con): myPyDatagram = PyDatagram() myPyDatagram.addString(self.encode(data, self.compress)) self.cWriter.send(myPyDatagram, con) def passData(self, data, connection): self.passedData.append((data, connection)) def getData(self): data = self.passedData self.passedData = [] while self.cReader.dataAvailable(): datagram = NetDatagram() if self.cReader.getData(datagram): data.append( (datagram.getConnection(), self.processData(datagram))) return data
class World(DirectObject): def __init__(self): self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) host = "localhost" port = 9898 self.connection = self.cManager.openTCPClientConnection(host, port, 10000) #self.received = 1 #store a dictionary of active players with username player as key value pair #the dictionary also contain a special player named panda self.players = {} #for display the list on the screen self.temp = [] #store a dictionary of playerObject self.playerObjects = {} self.render = render self.loginSuccessful = False self.isMoving = False self.justStoping = False self.targetPlayer = None if self.connection: self.cReader.addConnection(self.connection) taskMgr.add(self.updateRoutine, 'updateRoutine') #taskMgr.doMethodLater(0.5, self.updateRoutine, 'updateRoutine') #taskMgr.add(self.updatePandaAttack, 'updatePandaAttack') #taskMgr.doMethodLater(3, self.updatePandaAttack, 'updatePandaAttack') self.loginRegister() #################Communication Method################ def loginRegister(self): print "1. Login" print "2. Register" userInput = str(raw_input("Enter 1 or 2: ")) if userInput == "1": self.login() elif userInput == "2": self.register(); else: print "Invalid input" self.loginRegister() def register(self): print "Please enter your username: "******"Please enter your password: "******"{} {} {}".format(REGISTER, username, password) self.sendRequest(msg) #define self.username to specify the username for this object def login(self): print "Please enter your username: "******"Please enter your password: "******"{} {} {}".format(LOGIN, self.username, password) self.sendRequest(msg) #user need to press esc key to logout def logout(self, x, y, z, h): print "logout called" player = self.players[self.username] msg = "{} {},{},{},{},{}".format(LOGOUT, self.username, player.getX(), player.getY(), player.getZ(), player.getH()) print msg self.sendRequest(msg) sys.exit() def updateMovement(self, isMove, x, y, z, h): #send code username,ismove,x,y,z,h to the server according to the protocol msg = "{} {},{},{},{},{},{}".format(UPDATE_PLAYER_MOVE, self.username, isMove, x, y, z, h) self.sendRequest(msg) def possibleAttackRequest(self, distance): msg = "{} {},{}".format(PANDA_ATTACK_REQUEST, self.username, distance) self.sendRequest(msg) def composeStringMessage(self, msg): myPyDatagram = PyDatagram() myPyDatagram.addString(msg) return myPyDatagram def retrieveStringMessage(self,datagram): myIterator = PyDatagramIterator(datagram) msg = myIterator.getString() #print msg, " received" return msg # def sendRequest(self): # if(self.received): # print "->Client request:" # # Send a request to the server # mylist = ["apple", "ball", "cat", "dog"] # # msg = random.choice(mylist) # request = self.composeStringMessage(msg) # ack = self.cWriter.send(request,self.connection) # print msg, " sent" # self.received = 0 def sendRequest(self, msg): request = self.composeStringMessage(msg) ack = self.cWriter.send(request,self.connection) #print msg, " sent" #self.received = 0 def receiveResponse(self): #print "<-Server response:" while self.cReader.dataAvailable(): datagram = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram): msg = self.retrieveStringMessage(datagram) msgs = msg.split(' ') #print msgs[0] if msgs[0] == REGISTER_SUCCESSFUL: self.registerSuccessfulResponse() elif msgs[0] == USERNAME_EXIST: self.usernameExistResponse() elif msgs[0] == LOGIN_SUCCESSFUL: self.loginSuccessfulResponse(msgs[1]) elif msgs[0] == ADD_NEW_PLAYER: self.addNewPlayerResponse(msgs[1]) elif msgs[0] == LOGIN_FAIL: self.loginFailResponse() elif msgs[0] == LOGOUT: self.logoutResponse(msgs[1]) elif msgs[0] == UPDATE_PLAYER_MOVE_RESPONSE: self.updateMoveResponse(msgs[1]) elif msgs[0] == PANDA_ATTACK: self.pandaAttackResponse(msgs[1]) #self.received = 1 # def communicate(self): # #print "communicate" # #self.sendRequest() # self.receiveResponse() def updateRoutine(self,task): #self.communicate() self.receiveResponse() return task.again; def registerSuccessfulResponse(self): print "You have successfully registered. Please login to start the game." self.login() def usernameExistResponse(self): print "Username already exist. Please choose another username." self.register() #initail a dictionary of players def loginSuccessfulResponse(self, playerListMsg): actorsMsg = playerListMsg.split(":") #the dictionary also adds a special player named panda for aMsg in actorsMsg: elements = aMsg.split(",") actor = Player(elements[0], float(elements[1]), float(elements[2]), float(elements[3]), float(elements[4])) self.players[elements[0]] = actor print "login successful" #display other players' Ralph for username, value in self.players.iteritems(): if username == self.username: #display this player's Ralph self.showRalph(value) elif username != self.username and username != "panda": self.createActor(self.render, value) elif username == "panda": self.createPanda(self.render, value) else: pass self.loginSuccessful = True #add new player to the players dictionary def addNewPlayerResponse(self, msg): elements = msg.split(",") actor = Player(elements[0], float(elements[1]), float(elements[2]), float(elements[3]), float(elements[4])) self.players[elements[0]] = actor print "add new player: ", self.players[elements[0]].getUsername(), self.players[elements[0]].getX() self.createActor(self.render, actor) ###Line's Added### textMsg = elements[0]+" has logged in" self.notifyPlayer(textMsg) def loginFailResponse(self): print "Username and password does not match, please re-login or register." self.loginRegister() def logoutResponse(self, username): if username in self.players: del self.players[username] if username in self.playerObjects: playerObject = self.playerObjects[username] playerObject.getActor().delete() del self.playerObjects[username] #self.playerObjects print "{} logout".format(username) ###Lines Added### msg = username+" has logged out" self.notifyPlayer(msg) def notifyPlayer(self,msg): #label = DirectLabel(text=msg) label = OnscreenText(text=msg, style=1, fg=(1,1,1,1), pos=(1.3,-0.95), align=TextNode.ARight, scale = .07) taskMgr.doMethodLater(5, self.destroyLabel, 'destroyLabel', extraArgs=[label]) def destroyLabel(self,label): label.destroy() def updateMoveResponse(self, msg): if self.loginSuccessful: #msg contain username,isMoving,x,y,z,h msgs = msg.split(",") username = msgs[0] if username == self.username: #self already move, no need to update pass else: if username in self.playerObjects.keys(): player = self.players[username] player.setX(float(msgs[2])) player.setY(float(msgs[3])) player.setZ(float(msgs[4])) actor = self.playerObjects[username].getActor() actor.setPos(float(msgs[2]), float(msgs[3]), float(msgs[4])) actor.setH(float(msgs[5])) self.playerObjects[username].move(msgs[1]) def pandaAttackResponse(self, msg): #msg contain targetUsername #print "pan Att: ", msg #msgs = msg.split(",") targetUsername = msg targetPlayer = self.players[targetUsername] pandaActor = self.pandaObject.getActor() pandax = pandaActor.getX() panday = pandaActor.getY() pandaz = pandaActor.getZ() x = targetPlayer.getX() y = targetPlayer.getY() z = targetPlayer.getZ() distance = self.getDistance(pandax, panday, pandaz, x, y, z) if distance < PANDA_ATTACK_RANGE: if pandax > x and panday > y: self.pandaObject.setH(135) elif pandax > x and panday < y: self.pandaObject.setH(180) elif pandax < x and panday > y: self.pandaObject.setH(135) else: self.pandaObject.setH(90) #self.pandaObject.turn(180) self.pandaObject.move(x-0.5, y-0.5, z) panda = self.players["panda"] panda.setX(pandax); panda.setY(panday); panda.setZ(pandaz); #self.setTargetPlayer(msg) def setTargetPlayer(self, username): self.targetPlayer = self.players[username] def getTargetPlayer(self): return self.targetPlayer def createActor(self, render, actor): playerObject = PlayerObject(render, actor) self.playerObjects[actor.getUsername()] = playerObject # nameplate = TextNode('textNode username_' + str(actor.username)) # nameplate.setText(actor.username) # npNodePath = actor.actor.attachNewNode(nameplate) # npNodePath.setScale(1.0) # npNodePath.setBillboardPointEye() # npNodePath.setZ(8.0) def createPanda(self, render, actor): self.pandaObject = PandaObject(render, actor) def checkPossibleAttack(self, x, y, z): panda = self.players["panda"] pandax = panda.getX(); panday = panda.getY(); pandaz = panda.getZ(); distance = self.getDistance(pandax, panday, pandaz, x, y, z) if distance < PANDA_ATTACK_RANGE: self.possibleAttackRequest(distance) def getDistance(self, pandax, panday, pandaz, x, y, z): return math.sqrt( math.pow(pandax-x, 2) + math.pow(panday-y, 2) + math.pow(pandaz-z, 2) ) ################################################################# ################Ralph code ##################### def showRalph(self, player): # self.render = render self.keyMap = {"left":0, "right":0, "forward":0, "cam-left":0, "cam-right":0} base.win.setClearColor(Vec4(0,0,0,1)) # Post the instructions #self.title = addTitle("Panda3D Tutorial: Roaming Ralph (Walking on Uneven Terrain)") self.inst1 = addInstructions(0.95, "[ESC]: Quit") self.inst2 = addInstructions(0.90, "[Left Arrow]: Rotate Ralph Left") self.inst3 = addInstructions(0.85, "[Right Arrow]: Rotate Ralph Right") self.inst4 = addInstructions(0.80, "[Up Arrow]: Run Ralph Forward") self.inst6 = addInstructions(0.70, "[A]: Rotate Camera Left") self.inst7 = addInstructions(0.65, "[S]: Rotate Camera Right") self.inst8 = addInstructions(0.60, "[l] Show Players on the right corner") # Set up the environment # # This environment model contains collision meshes. If you look # in the egg file, you will see the following: # # <Collide> { Polyset keep descend } # # This tag causes the following mesh to be converted to a collision # mesh -- a mesh which is optimized for collision, not rendering. # It also keeps the original mesh, so there are now two copies --- # one optimized for rendering, one for collisions. self.environ = loader.loadModel("models/world") self.environ.reparentTo(render) self.environ.setPos(0,0,0) # Create the main character, Ralph ralphStartPos = self.environ.find("**/start_point").getPos() self.ralph = Actor("models/ralph", {"run":"models/ralph-run", "walk":"models/ralph-walk"}) self.ralph.reparentTo(render) self.ralph.setScale(.2) #self.ralph.setPos(ralphStartPos) self.ralph.setPos(player.getX(), player.getY(), player.getZ()) self.ralph.setH(player.getH()) ##################################### # Create a floater object. We use the "floater" as a temporary # variable in a variety of calculations. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) # Accept the control keys for movement and rotation #self.accept("escape", sys.exit) self.accept("escape", self.logout, [self.ralph.getX(), self.ralph.getY(), self.ralph.getZ(), self.ralph.getH()]) self.accept("arrow_left", self.setKey, ["left",1]) self.accept("arrow_right", self.setKey, ["right",1]) self.accept("arrow_up", self.setKey, ["forward",1]) self.accept("a", self.setKey, ["cam-left",1]) self.accept("s", self.setKey, ["cam-right",1]) self.accept("arrow_left-up", self.setKey, ["left",0]) self.accept("arrow_right-up", self.setKey, ["right",0]) self.accept("arrow_up-up", self.setKey, ["forward",0]) self.accept("a-up", self.setKey, ["cam-left",0]) self.accept("s-up", self.setKey, ["cam-right",0]) taskMgr.add(self.move,"moveTask") # Game state variables self.isMoving = False # Set up the camera base.disableMouse() base.camera.setPos(self.ralph.getX(),self.ralph.getY()+10,2) # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. self.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0,0,1000) self.ralphGroundRay.setDirection(0,0,-1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) self.camGroundRay = CollisionRay() self.camGroundRay.setOrigin(0,0,1000) self.camGroundRay.setDirection(0,0,-1) self.camGroundCol = CollisionNode('camRay') self.camGroundCol.addSolid(self.camGroundRay) self.camGroundCol.setFromCollideMask(BitMask32.bit(0)) self.camGroundCol.setIntoCollideMask(BitMask32.allOff()) self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Uncomment this line to see the collision rays #self.ralphGroundColNp.show() #self.camGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring #self.cTrav.showCollisions(render) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(-5, -5, -5)) directionalLight.setColor(Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) #Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value '''method to show player list''' def showPlayers(self, set): for i in self.temp: i.destroy() self.temp = [] y=[] i = 0 while(i!=set.__len__()): y.append(0.95-(i*0.05)) i=i+1 i = 0 while(i!=y.__len__()): if set[i] == "panda": pass else: self.temp.append(OnscreenText(text=set[i], style=1, fg=(1,1,1,1), pos=(1.3, y[i]), align=TextNode.ARight, scale = .07)) i=i+1 # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): '''Call to Show player list''' x = self.players.keys() self.accept("l", self.showPlayers, [x]) ''' call end ''' # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. base.camera.lookAt(self.ralph) if (self.keyMap["cam-left"]!=0): base.camera.setX(base.camera, -20 * globalClock.getDt()) if (self.keyMap["cam-right"]!=0): base.camera.setX(base.camera, +20 * globalClock.getDt()) # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.ralph.getPos() # If a move-key is pressed, move ralph in the specified direction. if (self.keyMap["left"]!=0): self.ralph.setH(self.ralph.getH() + 300 * globalClock.getDt()) if (self.keyMap["right"]!=0): self.ralph.setH(self.ralph.getH() - 300 * globalClock.getDt()) if (self.keyMap["forward"]!=0): self.ralph.setY(self.ralph, -25 * globalClock.getDt()) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. if (self.keyMap["forward"]!=0) or (self.keyMap["left"]!=0) or (self.keyMap["right"]!=0): if self.isMoving is False: self.ralph.loop("run") self.isMoving = True self.justStoping = False else: if self.isMoving: self.ralph.stop() self.ralph.pose("walk",5) self.isMoving = False self.justStoping = True #print self.ralph.getX(), self.ralph.getY(), self.ralph.getZ(), self.ralph.getH() if(self.isMoving or self.justStoping): self.updateMovement(self.isMoving, self.ralph.getX(), self.ralph.getY(), self.ralph.getZ(), self.ralph.getH()) #check if in panda attach range self.checkPossibleAttack(self.ralph.getX(), self.ralph.getY(), self.ralph.getZ()) player = self.players[self.username] player.setX(self.ralph.getX()) player.setY(self.ralph.getY()) player.setZ(self.ralph.getZ()) player.setH(self.ralph.getH()) self.justStoping = False # If the camera is too far from ralph, move it closer. # If the camera is too close to ralph, move it farther. camvec = self.ralph.getPos() - base.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if (camdist > 10.0): base.camera.setPos(base.camera.getPos() + camvec*(camdist-10)) camdist = 10.0 if (camdist < 5.0): base.camera.setPos(base.camera.getPos() - camvec*(5-camdist)) camdist = 5.0 # Now check for collisions. self.cTrav.traverse(render) # Adjust ralph's Z coordinate. If ralph's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = [] for i in range(self.ralphGroundHandler.getNumEntries()): entry = self.ralphGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): self.ralph.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.ralph.setPos(startpos) # Keep the camera at one foot above the terrain, # or two feet above ralph, whichever is greater. entries = [] for i in range(self.camGroundHandler.getNumEntries()): entry = self.camGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): base.camera.setZ(entries[0].getSurfacePoint(render).getZ()+1.0) if (base.camera.getZ() < self.ralph.getZ() + 2.0): base.camera.setZ(self.ralph.getZ() + 2.0) # The camera should look in ralph's direction, # but it should also try to stay horizontal, so look at # a floater which hovers above ralph's head. self.floater.setPos(self.ralph.getPos()) self.floater.setZ(self.ralph.getZ() + 2.0) base.camera.lookAt(self.floater) return task.cont
class Server: def __init__(self): self.activeConnections = [] # lists all connections self.players = {} # keys are the players logins, values are the players datagram connections self.parties = {} # keys are the parties names, values are dicts representing parties data self.sessions = {} # keys are the datagram connections, values are dicts storing the characters of the player and its party self.playersinlobby = [] # lists players in the party screen self.charid = 0 # used for random team generation self.chars = [] # lists of dicts representing characters data self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cReader.setTcpHeaderSize(4) self.send = Send(self.cManager) port = 3001 if len(sys.argv) > 1: port = sys.argv[1] self.tcpSocket = self.cManager.openTCPServerRendezvous(port, 10) self.cListener.addConnection(self.tcpSocket) print("Server listening on port", port) taskMgr.add(self.tskListenerPolling, "Poll the connection listener", -39) taskMgr.add(self.tskReaderPolling, "Poll the connection reader", -40) def processData(self, datagram): iterator = PyDatagramIterator(datagram) source = datagram.getConnection() callback = iterator.getString() getattr(globals()[callback], 'execute')(self, iterator, source) def updateAllPartyLists(self): parties = deepcopy(self.parties) for party in list(parties.values()): del party['map']['tiles'] for player in self.playersinlobby: self.send.UPDATE_PARTY_LIST(parties, player) def tskListenerPolling(self, taskdata): if self.cListener.newConnectionAvailable(): rendezvous = PointerToConnection() netAddress = NetAddress() newConnection = PointerToConnection() if self.cListener.getNewConnection(rendezvous, netAddress, newConnection): newConnection = newConnection.p() self.activeConnections.append(newConnection) self.cReader.addConnection(newConnection) print('A new client is connected', newConnection) return Task.cont def tskReaderPolling(self, taskdata): if self.cReader.dataAvailable(): datagram=NetDatagram() if self.cReader.getData(datagram): self.processData(datagram) return Task.cont
class ConnectionManager: def __init__(self): self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) self.rqTable = ServerRequestTable() self.rsTable = ServerResponseTable() self.connection = None def startConnection(self): """Create a connection with the remote host. If a connection can be created, create a task with a sort value of -39 to read packets from the socket. """ try: if self.connection == None: self.connection = self.cManager.openTCPClientConnection( Constants.SERVER_IP, Constants.SERVER_PORT, 1000) if self.connection: self.cReader.addConnection(self.connection) taskMgr.add(self.updateRoutine, 'updateRoutine-Connection', -39) taskMgr.doMethodLater(5, self.checkConnection, 'checkConnection') return True except: pass return False def closeConnection(self): """Close the current connection with the remote host. If an existing connection is found, remove both the Main2 task, which is responsible for the heartbeat, and the Connection task, which is responsible for reading packets from the socket, then properly close the existing connection. """ if self.connection != None: taskMgr.remove('updateRoutine-Main2') taskMgr.remove('updateRoutine-Connection') taskMgr.remove('checkConnection') self.cManager.closeConnection(self.connection) self.connection = None def sendRequest(self, requestCode, args={}): """Prepare a request packet to be sent. If the following request code exists, create an instance of this specific request using any extra arguments, then properly send it to the remote host. """ if self.connection != None: request = self.rqTable.get(requestCode) if request != None: request.set(self.cWriter, self.connection) request.send(args) def handleResponse(self, responseCode, data): """Prepare a response packet to be processed. If the following response code exists, create an instance of this specific response using its data to be executed. """ response = self.rsTable.get(responseCode) if response != None: #response.set(main) response.execute(data) def checkConnection(self, task): if not self.cReader.isConnectionOk(self.connection): self.closeConnection() self.showDisconnected(0) return task.done return task.again def updateRoutine(self, task): """A once-per-frame task used to read packets from the socket.""" while self.cReader.dataAvailable(): # Create a datagram to store all necessary data. datagram = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram): # Prepare the datagram to be iterated. data = PyDatagramIterator(datagram) # Retrieve a "short" that contains the response code. responseCode = data.getUint16() # Pass into another method to execute the response. if responseCode != Constants.MSG_NONE: self.handleResponse(responseCode, data) return task.cont
class NetworkManager: def __init__(self): print "Network Manager Started" def connection_open(self): self.cManager = QueuedConnectionManager() self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager,0) self.activeConnections=[] # We'll want to keep track of these later self.cListener = QueuedConnectionListener(self.cManager, 0) port_address=9099 #No-other TCP/IP services are using this port backlog=1000 #If we ignore 1,000 connection attempts, something is wrong! self.tcpSocket = self.cManager.openTCPServerRendezvous(port_address,backlog) self.cListener.addConnection(self.tcpSocket) print "Network Connection Opened" taskMgr.add(self.tskListenerPolling,"Poll the connection listener",-39) taskMgr.add(self.tskReaderPolling,"Poll the connection reader",-40) def connection_close(self): for aClient in self.activeConnections: self.cReader.removeConnection(aClient) self.activeConnections=[] # close down our listener self.cManager.closeConnection(self.tcpSocket) print "Network Connection Closed" def tskListenerPolling(self, taskdata): if self.cListener.newConnectionAvailable(): rendezvous = PointerToConnection() netAddress = NetAddress() newConnection = PointerToConnection() if self.cListener.getNewConnection(rendezvous,netAddress,newConnection): newConnection = newConnection.p() self.activeConnections.append(newConnection) # Remember connection self.cReader.addConnection(newConnection) # Begin reading connection return Task.cont def tskReaderPolling(self, taskdata): if self.cReader.dataAvailable(): datagram=NetDatagram() # catch the incoming data in this instance # Check the return value; if we were threaded, someone else could have # snagged this data before we did if self.cReader.getData(datagram): if base.client == True: self.client_processing(datagram) else: self.server_processing(datagram) return Task.cont def server_messager(self,msg,args=[]): if msg == "map_set": order = PyDatagram() order.addUint16(MAP_SET) order.addInt32(args[0]) self.send_package(order) elif msg == "client_update": order = PyDatagram() order.addUint16(CLIENT_INIT_UPDATE) order.addString(args[0]) order.addString(args[1]) order.addInt32(args[2]) order.addInt32(args[3]) self.send_package(order) elif msg == "chat_send": r = args[0][0] g = args[0][1] b = args[0][2] order = PyDatagram() order.addUint16(SERVER_CHAT) order.addInt32(r) order.addInt32(g) order.addInt32(b) order.addString(args[1]) self.send_package(order) base.menu_manager.menus["mp-game"].chat_add((r,g,b,1),args[1]) elif msg == "ready_button": order = PyDatagram() order.addUint16(SERVER_READY) order.addInt32(args[0]) order.addInt32(args[1]) self.send_package(order) base.menu_manager.menus["mp-game"].obj_list[args[0]]["indicatorValue"]=args[1] base.menu_manager.menus["mp-game"].start_game_check() elif msg == "server_loaded": order = PyDatagram() order.addUint16(SERVER_LOADED) self.send_package(order) elif msg == "all_loaded": order = PyDatagram() order.addUint16(ALL_LOADED) self.send_package(order) elif msg == "game_start": order = PyDatagram() order.addUint16(GAME_START) self.send_package(order) elif msg == "army_kill": order = PyDatagram() order.addUint16(ARMY_KILL) order.addInt32(args[0]) self.send_package(order) elif msg == "build_start": order = PyDatagram() order.addUint16(BUILD_START) order.addInt32(args[0]) order.addInt8(args[1]) order.addString(args[2]) self.send_package(order) elif msg == "tower_capture": order = PyDatagram() order.addUint16(TOWER_CAPTURE) order.addInt32(args[0]) order.addInt8(args[1]) self.send_package(order) elif msg == "build_complete": order = PyDatagram() order.addUint16(BUILD_COMPLETE) order.addInt32(args[0]) order.addInt8(args[1]) order.addString(args[2]) self.send_package(order) elif msg == "build_cancel": order = PyDatagram() order.addUint16(BUILD_CANCEL) order.addInt32(args[0]) self.send_package(order) elif msg == "battle_start": order = PyDatagram() order.addUint16(BATTLE_START) order.addInt32(args[0]) order.addFloat32(args[1]) order.addFloat32(args[2]) order.addInt32(args[3]) order.addFloat32(args[4]) order.addFloat32(args[5]) order.addInt32(args[6]) self.send_package(order) elif msg == "battle_clash": order = PyDatagram() order.addUint16(BATTLE_CLASH) order.addInt32(args[0]) order.addInt32(args[1]) order.addInt32(args[2]) order.addString(args[3]) order.addInt8(args[4]) self.send_package(order) elif msg == "battle_turn": order = PyDatagram() order.addUint16(BATTLE_TURN) order.addInt32(args[0]) order.addInt32(args[1]) self.send_package(order) elif msg == "battle_end": order = PyDatagram() order.addUint16(BATTLE_END) order.addInt32(args[0]) self.send_package(order) elif msg == "battle_armyadd": order = PyDatagram() order.addUint16(BATTLE_ARMYADD) order.addInt32(args[0]) order.addInt32(args[1]) order.addFloat32(args[2]) order.addFloat32(args[3]) self.send_package(order) def client_messager(self,msg,args=[]): if msg == "chat_send": order = PyDatagram() order.addUint16(CLIENT_CHAT) order.addInt32(args[0][0]) order.addInt32(args[0][1]) order.addInt32(args[0][2]) order.addString(args[1]) self.send_package(order) elif msg == "ready_button": order = PyDatagram() order.addUint16(CLIENT_READY) order.addInt32(args[0]) order.addInt32(args[1]) self.send_package(order) elif msg == "client_loaded": order = PyDatagram() order.addUint16(CLIENT_LOADED) self.send_package(order) elif msg == "game_init_request": order = PyDatagram() order.addUint16(CLIENT_INIT_REQUEST) order.addString(args[0]) order.addString(args[1]) self.send_package(order) elif msg == "build_start_request": order = PyDatagram() order.addUint16(BUILD_START_REQUEST) order.addInt32(args[0]) order.addInt32(args[1]) order.addString(args[2]) self.send_package(order) elif msg == "build_cancel_request": order = PyDatagram() order.addUint16(BUILD_CANCEL_REQUEST) order.addInt32(args[0]) self.send_package(order) def client_processing(self,datagram): data_iter = PyDatagramIterator(datagram) msgID = data_iter.getUint16() if msgID == PRINT_MESSAGE: messageToPrint = data_iter.getString() print messageToPrint if msgID == ARMY_MOVE: army_id = data_iter.getInt16() ax = data_iter.getFloat64() ay = data_iter.getFloat64() tx = data_iter.getFloat64() ty = data_iter.getFloat64() base.armies[army_id].node_path.setX(ax) base.armies[army_id].node_path.setY(ay) base.armies[army_id].move_to_point(tx,ty) if msgID == CLIENT_INIT_UPDATE: p1_name = data_iter.getString() p1_kingdom = data_iter.getString() p1_ready = data_iter.getInt32() game_map = data_iter.getInt32() base.menu_manager.menus["mp-game"].client_update(p1_name,p1_kingdom,p1_ready,game_map) if msgID == SERVER_CHAT: r = data_iter.getInt32() g = data_iter.getInt32() b = data_iter.getInt32() text = data_iter.getString() base.menu_manager.menus["mp-game"].chat_add((r,g,b),text) if msgID == SERVER_READY: but_id = data_iter.getInt32() state = data_iter.getInt32() base.menu_manager.menus["mp-game"].obj_list[but_id]["indicatorValue"]=state base.menu_manager.menus["mp-game"].start_game_check() if msgID == SERVER_LOADED: base.menu_manager.menus["mp-load"].load() if msgID == ALL_LOADED: base.menu_manager.menus["mp-load"].load_complete() if msgID == GAME_START: base.menu_manager.menu_goto("mp-load") if msgID == MAP_SET: map = data_iter.getInt32() base.menu_manager.menus["mp-game"].map_selected = map mapname = base.menu_manager.menus["mp-game"].maplist[map]["fullname"] mapimage = base.menu_manager.menus["mp-game"].maplist[map]["preview"] base.menu_manager.menus["mp-game"].obj_list[11]["text"]=mapname base.menu_manager.menus["mp-game"].obj_list[10].setImage(mapimage) if msgID == BATTLE_TURN: bat = data_iter.getInt32() turn = data_iter.getInt32() base.battles[bat].turn_change(turn) if msgID == BATTLE_START: a1 = data_iter.getInt32() a1_x = data_iter.getFloat32() a1_y = data_iter.getFloat32() a2 = data_iter.getInt32() a2_x = data_iter.getFloat32() a2_y = data_iter.getFloat32() army_start = data_iter.getInt32() base.armies[a1].stop() base.armies[a2].stop() base.armies[a1].node_path.setPos(a1_x,a1_y,0) base.armies[a2].node_path.setPos(a2_x,a2_y,0) base.battles.append(TimObjects.Battle([base.armies[a1],base.armies[a2]],army_start)) if msgID == BATTLE_CLASH: battle = data_iter.getInt32() a1 = data_iter.getInt32() a2 = data_iter.getInt32() result = data_iter.getString() buff = data_iter.getInt8() base.battles[battle].clash(base.armies[a1],base.armies[a2],result,buff) if msgID == BATTLE_ARMYADD: bat = data_iter.getInt32() army = data_iter.getInt32() a_x = data_iter.getFloat32() a_y = data_iter.getFloat32() base.battles[bat].add_army(base.armies[army]) base.armies[army].node_path.setPos(a_x,a_y,0) if msgID == BATTLE_END: bat = data_iter.getInt32() base.battles[bat].end() if msgID == BUILD_START: t_id = data_iter.getInt32() player = data_iter.getInt8() type = data_iter.getString() base.towers[t_id].build_start() if msgID == TOWER_CAPTURE: t_id = data_iter.getInt32() player = data_iter.getInt8() base.towers[t_id].change_owner(player) if msgID == BUILD_CANCEL: t_id = data_iter.getInt32() base.towers[t_id].build_cancel() if msgID == BUILD_COMPLETE: t_id = data_iter.getInt32() player = data_iter.getInt8() type = data_iter.getString() base.towers[t_id].create_counter() def server_processing(self,datagram): data_iter = PyDatagramIterator(datagram) msgID = data_iter.getUint16() if msgID == PRINT_MESSAGE: messageToPrint = data_iter.getString() print messageToPrint if msgID == ARMY_MOVE_REQUEST: army_id = data_iter.getInt16() ax = data_iter.getFloat64() ay = data_iter.getFloat64() tx = data_iter.getFloat64() ty = data_iter.getFloat64() base.armies[army_id].set_target(False,tx,ty) if msgID == CLIENT_CHAT: r = data_iter.getInt32() g = data_iter.getInt32() b = data_iter.getInt32() text = data_iter.getString() self.server_messager("chat_send",[(r,g,b),text]) #base.main_menu.chat_add((r,g,b,1),text) if msgID == CLIENT_READY: but_id = data_iter.getInt32() state = data_iter.getInt32() self.server_messager("ready_button",[but_id,state]) #base.main_menu.chat_add((r,g,b,1),text) if msgID == CLIENT_LOADED: self.server_messager("all_loaded",[]) base.menu_manager.menus["mp-load"].load_complete() if msgID == CLIENT_INIT_REQUEST: pn = data_iter.getString() pk = data_iter.getString() base.menu_manager.menus["mp-game"].obj_list[6]["text"] = pn base.menu_manager.menus["mp-game"].obj_list[7]["text"] = pk self.server_messager("client_update",[base.menu_manager.menus["mp-game"].obj_list[4]["text"], base.menu_manager.menus["mp-game"].obj_list[5]["text"], base.menu_manager.menus["mp-game"].obj_list[8]["indicatorValue"], base.menu_manager.menus["mp-game"].map_selected]) if msgID == BUILD_START_REQUEST: t_id = data_iter.getInt32() player = data_iter.getInt32() type = data_iter.getString() base.towers[t_id].build_start() if msgID == BUILD_CANCEL_REQUEST: t_id = data_iter.getInt32() player = data_iter.getInt32() type = data_iter.getString() base.towers[t_id].build_cancel() def msgAllClients(self): myPyDatagram=self.myNewPyDatagram() # build a datagram to send for aClient in self.activeConnections: self.cWriter.send(myPyDatagram,aClient) def send_package(self,package): # print "packaged" for aClient in self.activeConnections: print "Package",package,"sent" self.cWriter.send(package,aClient) def army_move(self,army_id,tx,ty): order = PyDatagram() if base.client == True: order.addUint16(ARMY_MOVE_REQUEST) else: order.addUint16(ARMY_MOVE) ax = base.armies[army_id].node_path.getX() ay = base.armies[army_id].node_path.getY() order.addInt16(army_id) order.addFloat64(ax) order.addFloat64(ay) order.addFloat64(tx) order.addFloat64(ty) if base.client == True: self.cWriter.send(order,base.server_connection) else: self.send_package(order) base.armies[army_id].move_to_point(tx,ty) def tower_train(self,tower_id,build_object): order = PyDatagram() if base.client == True: order.addUint16(REQUEST_TOWER_TRAIN) else: order.addUint16(TOWER_TRAIN) order.addInt16(army_id) order.addFloat64(tx) order.addFloat64(ty) if base.client == True: self.cWriter.send(order,base.server_connection) else: self.send_package(order) base.towers[tower_id].train_counter() # def request_army_move(self,army_id,tx,ty): # order = PyDatagram() # order.addUint16(REQUEST_MOVE_COUNTER) # order.addInt16(army_id) # order.addFloat64(tx) # order.addFloat64(ty) # self.cWriter.send(order,base.server_connection) def myNewPyDatagram(self): # Send a test message myPyDatagram = PyDatagram() myPyDatagram.addUint16(PRINT_MESSAGE) myPyDatagram.addString("You got ze message!") return myPyDatagram def client_connect(self,ip): port_address=9099 # same for client and server # a valid server URL. You can also use a DNS name # if the server has one, such as "localhost" or "panda3d.org" ip_address=ip # how long until we give up trying to reach the server? timeout_in_miliseconds=3000 # 3 seconds base.server_connection=self.cManager.openTCPClientConnection(ip_address,port_address,timeout_in_miliseconds) if base.server_connection: self.cReader.addConnection(base.server_connection) # receive messages from server self.activeConnections.append(base.server_connection) print "Connected to server",ip return True print "Connection failed" return False
class MyApp(ShowBase): def __init__(self): ShowBase.__init__(self) self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) self.player = Player() self.opponents = dict() self.logStat = -1 host = "localhost" port = 9252 self.connection = self.cManager.openTCPClientConnection( host, port, 10000) self.received = 1 self.playersText = [] if self.connection: self.cReader.addConnection(self.connection) taskMgr.add(self.updateRoutine, 'updateRoutine') taskMgr.add(self.login, 'login') #taskMgr.doMethodLater(3, self.updateRoutine, 'updateRoutine') taskMgr.doMethodLater(.1, self.heartbeat, 'heartbeat') self.accept("q", self.listPlayers) self.accept("q-up", self.delistPlayers) self.accept("escape", self.disconnect) self.accept("arrow_up", self.move) def login(self, task): self.option = 0 self.option = str(raw_input("1-Login\n2-Register\n")) if self.option == "1": un = str(raw_input("Username: "******"Password: "******"2": un = str(raw_input("Username: "******"Password: "******"data here" datagram = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram): data = PyDatagramIterator(datagram) responseCode = data.getUint16() print responseCode if responseCode == 201: self.getPlayer(data) elif responseCode == 202: self.register(data) elif responseCode == 203: self.getOpponent(data) elif responseCode == 214: self.movePlayer(data) elif responseCode == 219: self.dropPlayer(data) else: print "nothing found" def heartbeat(self, task): pkg = PyDatagram() pkg.addUint16(113) self.cWriter.send(pkg, self.connection) return task.again def updateRoutine(self, task): self.check() return task.again def getPlayer(self, data): self.logStat = data.getUint16() if self.logStat == 0: self.player.id = data.getInt32() self.player.username = data.getString() self.player.x = data.getFloat32() self.player.y = data.getFloat32() self.player.z = data.getFloat32() self.player.rotation = data.getFloat32() else: print "login failed" taskMgr.add(self.login, 'login') def register(self, data): self.logStat = data.getUint16() if self.logStat == 0: print "Account Made" taskMgr.add(self.login, 'login') else: print "Username Taken" taskMgr.add(self.login, 'login') def listPlayers(self): i = 0.55 for p in self.opponents: self.playersText.append( addInstructions( i, self.opponents[p].username + " " + "{:.2f}".format(self.opponents[p].x) + " " + "{:.2f}".format(self.opponents[p].y) + " " + "{:.2f}".format(self.opponents[p].z) + " " + "{:.2f}".format(self.opponents[p].rotation))) i -= 0.05 def delistPlayers(self): for x in self.playersText: x.destroy() def getOpponent(self, data): opponent = Player() opponent.id = data.getInt32() opponent.username = data.getString() opponent.x = data.getFloat32() opponent.y = data.getFloat32() opponent.z = data.getFloat32() opponent.rotation = data.getFloat32() self.opponents[opponent.id] = opponent
class MyApp(ShowBase): def __init__(self): ShowBase.__init__(self) self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) host = "localhost" port = 9252 self.connection = self.cManager.openTCPClientConnection(host, port, 10000) self.received = 1 if self.connection: self.cReader.addConnection(self.connection) taskMgr.add(self.updateRoutine, 'updateRoutine') print 'Hello You Are Now Connected To The Server' #self.heartbeat() self.options() #options for the clients when game starts def options(self): self.option = 0 self.option = str(raw_input("Please Selection An Option\n1-Enter Chat\n2-Messages\n3-Quit\n")) if self.option == "1": self.chat() if self.option == "2": self.messages() if self.option == "3": sys.exit(0) #function to chat def chat(self): self.username = "" self.message = "" self.username = str(raw_input("Please enter your username: "******"Please enter your message: ")) chat_message = self.username + " " + self.message request = self.chatRequest(chat_message) self.cWriter.send(request,self.connection) #package chat request def chatRequest(self, chat_info): pkg = PyDatagram() pkg.addUint16(112) pkg.addString(chat_info) return pkg #message options for the clients when game starts def messages(self): self.option = 0 self.option = str(raw_input("Please Selection An Option\n1-Send A Message\n2-Check Messages\n3-Return\n")) if self.option == "1": self.message() if self.option == "2": self.checkMessages() if self.option == "3": self.options() #function to message def checkMessages(self): self.username = str(raw_input("Please enter your username: "******"" self.to_Username = "******" self.message = "" self.from_Username = str(raw_input("Please enter your username: "******"Please enter which username you want to send the message: ")) self.message = str(raw_input("Please enter your message: ")) chat_message = self.from_Username + " " +self.to_Username+ " " + self.message request = self.messageRequest(chat_message) self.cWriter.send(request,self.connection) #package message request def messageRequest(self, chat_info): pkg = PyDatagram() pkg.addUint16(115) pkg.addString(chat_info) return pkg #check for messages for server def check(self): while self.cReader.dataAvailable(): datagram = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram): data = PyDatagramIterator(datagram) responseCode = data.getUint16() if responseCode == 212: print self.getString(data) self.options() elif responseCode == 201: #login code if (self.getString(data)=="Unsuccessful login"): #appears if login unsuccessful print " " print "Unsuccessful login" print " " self.options() else: print "Your are logged in" #appear if login successful self.login_options()#appears the login options elif responseCode == 203: #register code if (self.getString(data)=="Registration successful"): #appear if registration was successful print "You are now registered" print "Please login" #user must login print " " self.options() else: print " "#appear if registration wasn't successful print "Registration was unsuccessful. Pick a different username and please try again " print " " self.options()#user must attempt to register again elif responseCode == 215: print self.getString(data) self.messages() elif responseCode == 216: print self.getString(data) self.messages() else: print "nothing found" #function that unpackage the message from server def getString(self, data): msg = data.getString() return msg #heart beat function def heartbeat(self): request = self.heartbeatRequest() self.cWriter.send(request,self.connection) #heart beat packaged def heartbeatRequest(self): pkg = PyDatagram() pkg.addUint16(123) return pkg #updateRoutine for the program def updateRoutine(self,task): self.heartbeat() self.check() return task.again;
class MyApp(ShowBase): uname = None def __init__(self): ShowBase.__init__(self) self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) host = "localhost" port = 6002 self.connection = self.cManager.openTCPClientConnection( host, port, 10000) self.received = 1 if self.connection: self.cReader.addConnection(self.connection) #taskMgr.add(self.updateRoutine, 'updateRoutine') # LOGIN Request Starts self.uname = raw_input('Enter username :'******'Enter password :'******'Login') if (self.received): print "->Client request:" # Send a request to the server myPyDatagram101 = PyDatagram() prot = 101 myPyDatagram101.addUint16(prot) myPyDatagram101.addString(self.uname) myPyDatagram101.addString(self.password) self.cWriter.send(myPyDatagram101, self.connection) self.received = 0 taskMgr.add(self.receiveResponse101, 'Login') def sendRequest101(self): if (self.received): print "->Client request:" # Send a request to the server myPyDatagram101 = PyDatagram() prot = 101 myPyDatagram101.addUint16(prot) myPyDatagram101.addString(self.uname) myPyDatagram101.addString(self.password) self.cWriter.send(myPyDatagram101, self.connection) self.received = 0 def receiveResponse101(self, task): while self.cReader.dataAvailable(): datagram = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram): self.myIterator = PyDatagramIterator(datagram) print "<-Server response:" print self.myIterator.getUint16() self.msg = self.myIterator.getUint32() self.l = self.myIterator.getUint32() if self.msg is not None: if self.l is not 0: for x in range(0, self.l): print self.myIterator.getString() print self.myIterator.getUint32() print self.myIterator.getUint32() print self.msg, " received" #raw_input("Press Enter to continue...") self.received = 0 taskMgr.remove('Login') #1-Character creatopm #taskMgr.add(self.sendRequest104, 'CharacterCreation') #2-heartbeat of playgame after login MyApp.sendRequest113(self) return task.again # LOGIN Request End # CHARACTER CREATION Starts def sendRequest104(self, task): if (self.received): print "->Client request:" # Send a request to the server myPyDatagram = PyDatagram() prot = 104 cname = raw_input('Character Name :') faction_id_104 = raw_input('press 0 for Red Or 1 for Blue ? :') classType_104 = raw_input('press 0 for Axe Or 1 for Sword ? :') myPyDatagram.addUint16(prot) myPyDatagram.addString(cname) myPyDatagram.addUint32(faction_id_104) myPyDatagram.addUint32(classType_104) self.cWriter.send(myPyDatagram, self.connection) print "104 sent" self.received = 0 taskMgr.add(self.receiveResponse104, "characterresponse") def receiveResponse104(self, task): while self.cReader.dataAvailable(): datagram = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram): self.myIterator1 = PyDatagramIterator(datagram) print '------' print self.myIterator1.getUint16() self.msg = self.myIterator1.getUint32() if self.msg is not None: print "<-Server response:" print self.msg, " received" raw_input("Press Enter to continue...") self.received = 0 taskMgr.remove('CharacterCreation') taskMgr.add(self.sendRequest106, 'move') return task.again #CHARACTER CREATION Ends # Move Starts def sendRequest106(self, task): if (self.received): print "->Client request:" # Send a request to the server myPyDatagram106 = PyDatagram() prot = 106 xpos = raw_input('X Position :') ypos = raw_input('Y Position :') zpos = raw_input('Z Position :') hpos = raw_input('Heading (0 to 360):') ismoving = raw_input('Moving ? -- 0 for NO , 1 for YES :') myPyDatagram106.addUint16(prot) myPyDatagram106.addUint32(xpos) myPyDatagram106.addUint32(ypos) myPyDatagram106.addUint32(zpos) myPyDatagram106.addUint32(hpos) myPyDatagram106.addUint32(ismoving) self.cWriter.send(myPyDatagram106, self.connection) self.received = 0 taskMgr.add(self.receiveResponse106, "characterresponse") def receiveResponse106(self, task): while self.cReader.dataAvailable(): datagram6 = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram6): myIterator = PyDatagramIterator(datagram6) print myIterator.getUint16() msg = myIterator.getString() if msg is not None: print "<-Server response:" print msg print myIterator.getUint32() print myIterator.getUint32() print myIterator.getUint32() print myIterator.getUint32() print myIterator.getUint32() raw_input("Press Enter to continue...") self.received = 1 # Attack #raw_input("Press Enter to continue...") taskMgr.add(self.sendRequest108, 'health') return task.again #Move Ends #Change Health Starts def sendRequest108(self, task): if (self.received): print "->Client request:" # Send a request to the server myPyDatagram108 = PyDatagram() prot = 108 change_Health = raw_input('Change in health (-100 to 100):') myPyDatagram108.addUint16(prot) myPyDatagram108.addUint32(change_Health) self.cWriter.send(myPyDatagram108, self.connection) self.received = 0 taskMgr.add(self.receiveResponse108, "healthresponse") def receiveResponse108(self, task): while self.cReader.dataAvailable(): datagram8 = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram8): myIterator = PyDatagramIterator(datagram8) print myIterator.getUint16() msg = myIterator.getString() if msg is not None: print "<-Server response:" print msg print myIterator.getUint32() self.received = 1 # CP State raw_input("Press Enter to continue...") taskMgr.add(self.sendRequest107, 'attack') #Change Health Ends return task.again # Attack Starts def sendRequest107(self, task): if (self.received): print "->Client request:" # Send a request to the server myPyDatagram107 = PyDatagram() prot = 107 attackId = raw_input('Attack Id (0 or 1):') myPyDatagram107.addUint16(prot) myPyDatagram107.addUint32(attackId) self.cWriter.send(myPyDatagram107, self.connection) #print " sent" self.received = 0 taskMgr.add(self.receiveResponse108, "attackresponse") def receiveResponse107(self, task): while self.cReader.dataAvailable(): datagram7 = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram7): myIterator = PyDatagramIterator(datagram7) print myIterator.getUint16() msg = myIterator.getString() if msg is not None: print "<-Server response:" print msg print myIterator.getUint32() raw_input("Press Enter to continue...") self.received = 1 # Change Health taskMgr.add(self.sendRequest112, 'CP Capture') return task.again #Attack Ends #CP Capture Starts def sendRequest112(self, task): if (self.received): print "->Client request:" # Send a request to the server myPyDatagram112 = PyDatagram() prot = 112 CP_id = raw_input('Control Point ID (1 to 5): ') faction_id = raw_input('press 0 for Red Or 1 for Blue ? :') myPyDatagram112.addUint16(prot) myPyDatagram112.addUint32(CP_id) myPyDatagram112.addUint32(faction_id) self.cWriter.send(myPyDatagram112, self.connection) #print " sent" self.received = 0 taskMgr.add(self.receiveResponse112, "CPCaptureRes") def receiveResponse112(self, task): while self.cReader.dataAvailable(): datagram12 = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram12): myIterator = PyDatagramIterator(datagram12) print myIterator.getUint16() msg = myIterator.getUint32() if msg is not None: print "<-Server response:" print msg print myIterator.getUint32() raw_input("Press Enter to continue...") self.received = 1 #HeartBeat #raw_input("Press Enter to continue...") #taskMgr.add(self.communicate105, 'chat') #CP Capture Ends # CHAT Starts def communicate105(self, task): #print "communicate" self.sendRequest105() self.receiveResponse105(task) return task.again def sendRequest105(self): if (self.received): print "->Client request:" # Send a request to the server myPyDatagram105 = PyDatagram() prot = 105 chat = raw_input('Insert Chat Message :') myPyDatagram105.addUint16(prot) myPyDatagram105.addString(chat) self.cWriter.send(myPyDatagram105, self.connection) print " sent" self.received = 0 def receiveResponse105(self, task): print "<-Server response:" while self.cReader.dataAvailable(): datagram5 = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram5): myIterator = PyDatagramIterator(datagram5) print myIterator.getUint16() msg = myIterator.getUint16() print msg, " received" if msg is not None: raw_input("Press Enter to continue...") self.received = 1 # Move raw_input("Press Enter to continue...") taskMgr.add(self.communicate111, 'CP state') #CHAT Ends #CP State Starts def communicate111(self, task): #print "communicate" self.sendRequest111() self.receiveResponse111(task) return task.again def sendRequest111(self): if (self.received): print "->Client request:" # Send a request to the server myPyDatagram111 = PyDatagram() prot = 111 CP_id = raw_input('Control Point ID (1 to 5): ') CP_state = raw_input('Control Point state (1 red, 2 blue, 3 purple): ') myPyDatagram111.addUint16(prot) myPyDatagram111.addUint16(CP_id) myPyDatagram111.addUint16(CP_state) self.cWriter.send(myPyDatagram111, self.connection) print " sent" self.received = 0 def receiveResponse111(self, task): print "<-Server response:" while self.cReader.dataAvailable(): datagram11 = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram11): myIterator = PyDatagramIterator(datagram11) print myIterator.getUint16() msg = myIterator.getUint16() print msg, " received" if msg is not None: raw_input("Press Enter to continue...") self.received = 1 # CP Capture raw_input("Press Enter to continue...") taskMgr.add(self.communicate102, 'Logout') #CP State Ends # LOGOUT Starts def communicate102(self, task): #print "communicate" self.sendRequest102() self.receiveResponse102(task) return task.again def sendRequest102(self): if (self.received): print "->Client request:" # Send a request to the server myPyDatagram102 = PyDatagram() prot = 102 myPyDatagram102.addUint16(prot) self.cWriter.send(myPyDatagram102, self.connection) print " sent" self.received = 0 def receiveResponse102(self, task): print "<-Server response:" while self.cReader.dataAvailable(): datagram2 = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram2): myIterator = PyDatagramIterator(datagram2) print myIterator.getUint16() msg = myIterator.getUint16() print msg, " received" if msg is not None: raw_input("Press Enter to continue...") self.received = 1 # Register raw_input("Press Enter to continue...") taskMgr.add(self.communicate301, 'Heartbeat') #LOGOUT Ends #HeartBeat Starts def communicate301(self): #print "communicate" self.sendRequest301() self.receiveResponse301() #return task.again; def sendRequest301(self, task): if (self.received): print "->Client request:" # Send a request to the server myPyDatagram301 = PyDatagram() prot = 301 myPyDatagram301.addUint16(prot) self.cWriter.send(myPyDatagram301, self.connection) self.received = 0 return task.again def receiveResponse301(self): while self.cReader.dataAvailable(): datagram301 = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram301): myIterator = PyDatagramIterator(datagram301) p = myIterator.getUint16() if p == 213: un = myIterator.getString() cname = myIterator.getString() ctype = myIterator.getUint32() cteam = myIterator.getUint32() if un == MyApp.uname: abc = 'abc' else: print cname + ' just joined a game......!! hurray' #print msg, " received" self.received = 1 #HeartBeat Ends #heartbeat def sendRequest113(self): if (self.received): print "->Client request:" # Send a request to the server myPyDatagram113 = PyDatagram() prot = 113 myPyDatagram113.addUint16(prot) print MyApp.uname + '-------' if MyApp.uname == 'chintan': myPyDatagram113.addUint32(18) elif MyApp.uname == 'paras': myPyDatagram113.addUint32(35) else: myPyDatagram113.addUint32(3) self.cWriter.send(myPyDatagram113, self.connection) self.received = 0 #taskMgr.add(self.updateRoutine,'update113') #taskMgr.doMethodLater(1,self.sendRequest301,'HeatBeat') MyApp.retrieve113(self) def retrieve113(self): taskMgr.add(self.updateRoutine, 'update113') taskMgr.doMethodLater(1, self.sendRequest301, 'HeatBeat') def updateRoutine(self, task): self.receiveResponse301() return task.again
class TCP(): def __init__(self, _core): print ("TCP Protocol Startup...") self.core = _core self.config = self.core.server.config def start(self): self.setupTCP() self.startTCPTasks() def setupTCP(self): self.tcpManager = QueuedConnectionManager() self.tcpReader = QueuedConnectionReader(self.tcpManager, 0) self.tcpWriter = ConnectionWriter(self.tcpManager, 0) self.tcpListener = QueuedConnectionListener(self.tcpManager, 0) self.tcpSocket = self.tcpManager.openTCPServerRendezvous(self.config.TCPPORT, self.config.BACKLOG) self.tcpListener.addConnection(self.tcpSocket) print ("Started Server on: ", self.config.HOSTNAME, self.config.TCPPORT) def startTCPTasks(self): taskMgr.add(self.tcpListenerTask, "tcpListenerTask", 0) print ("TCP Listener Started") taskMgr.add(self.tcpReaderTask, "tcpReaderTask", -10) print ("TCP Reader Started") taskMgr.add(self.tcpDisconnectionHandler, "tcpDisconnectionHandler", 20) print ("TCP Disconnection Handler Started") # TCP Listener Task def tcpListenerTask(self, task): """ Accept new incoming connection from clients, related to TCP """ # Handle new connection if self.tcpListener.newConnectionAvailable(): rendezvous = PointerToConnection() netAddress = NetAddress() newConnection = PointerToConnection() if self.tcpListener.getNewConnection(rendezvous, netAddress, newConnection): newConnection = newConnection.p() # Tell the reader about the new TCP connection self.tcpReader.addConnection(newConnection) # Handle the connection depending on persistent or not if self.core.server.isPersistent: self.core.handleConnection(generateUUID(), newConnection, netAddress) else: self.core.createPlayerObject(generateUUID(),newConnection, netAddress) print ("Server: New Connection from -", str(netAddress.getIpString())) else: print ("Server: Connection Failed from -", str(netAddress.getIpString())) return Task.cont def tcpReaderTask(self, task): """ Handle any data from clients by sending it to the Handlers. """ while 1: (datagram, data, opcode) = self.tcpNonBlockingRead(self.tcpReader) if opcode is MSG_NONE: # Do nothing or use it as some 'keep_alive' thing. break else: # Handle it self.core.packetManager.handlePacket(opcode, data, datagram.getAddress()) return Task.cont # TCP NonBlockingRead?? def tcpNonBlockingRead(self, qcr): """ Return a datagram collection and type if data is available on the queued connection udpReader """ if self.tcpReader.dataAvailable(): datagram = NetDatagram() if self.tcpReader.getData(datagram): data = DatagramIterator(datagram) opcode = data.getUint8() else: data = None opcode = MSG_NONE else: datagram = None data = None opcode = MSG_NONE # Return the datagram to keep a handle on the data return (datagram, data, opcode) # TCP Disconnection Handler def tcpDisconnectionHandler(self, task): # Check for resets if self.tcpManager.resetConnectionAvailable(): resetConnection = PointerToConnection() self.tcpManager.getResetConnection(resetConnection) for client in self.core.server.clients: if self.core.server.clients[client].connection == resetConnection.p(): del self.core.server.clients[client] self.tcpReader.removeConnection(resetConnection.p()) print ("Removed Connection:", resetConnection.p()) print ('Current Clients:', self.core.server.clients) break return Task.cont def sendPacket(self, _pkt, _connection): self.tcpWriter.send(_pkt, _connection) def sendBroadcast(self, _pkt, _skipif=None): for client in self.serverManager.clients: if _skipif == client: pass else: conn = self.serverManager.clients[client].connection self.tcpWriter.send(_pkt, conn)
class client: def __init__(self): self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) self.connection = None def startConnection(self): """Create a connection with the remote host. If a connection can be created, create a task with a sort value of -39 to read packets from the socket. """ try: if self.connection == None: self.connection = self.cManager.openTCPClientConnection('localhost', 9090, 1000) if self.connection: self.cReader.addConnection(self.connection) taskMgr.add(self.updateRoutine, 'updateRoutine-Connection', -39) taskMgr.doMethodLater(5, self.checkConnection, 'checkConnection') return True except: pass self.loginHandler() #send packet myPyDatagram = PyDatagram() myPyDatagram.addUint8(1) myPyDatagram.addString(self.username) myPyDatagram.addString('_') myPyDatagram.addString(self.password) self.cWriter.send(myPyDatagram,self.connection) #receive packet datagram = NetDatagram() if self.cReader.getData(datagram): myProcessDataFunction(datagram) return False def loginHandler(self): self.username = raw_input("Enter username: "******"Enter password: "******"short" that contains the response code. responseCode = data.getUint16() # Pass into another method to execute the response. if responseCode != 0: self.handleResponse(responseCode, data) return task.cont
class TCP(): def __init__(self, _core): print("TCP Protocol Startup...") self.core = _core self.config = self.core.server.config def start(self): self.setupTCP() self.startTCPTasks() def setupTCP(self): self.tcpManager = QueuedConnectionManager() self.tcpReader = QueuedConnectionReader(self.tcpManager, 0) self.tcpWriter = ConnectionWriter(self.tcpManager, 0) self.tcpListener = QueuedConnectionListener(self.tcpManager, 0) self.tcpSocket = self.tcpManager.openTCPServerRendezvous( self.config.TCPPORT, self.config.BACKLOG) self.tcpListener.addConnection(self.tcpSocket) print("Started Server on: ", self.config.HOSTNAME, self.config.TCPPORT) def startTCPTasks(self): taskMgr.add(self.tcpListenerTask, "tcpListenerTask", 0) print("TCP Listener Started") taskMgr.add(self.tcpReaderTask, "tcpReaderTask", -10) print("TCP Reader Started") taskMgr.add(self.tcpDisconnectionHandler, "tcpDisconnectionHandler", 20) print("TCP Disconnection Handler Started") # TCP Listener Task def tcpListenerTask(self, task): """ Accept new incoming connection from clients, related to TCP """ # Handle new connection if self.tcpListener.newConnectionAvailable(): rendezvous = PointerToConnection() netAddress = NetAddress() newConnection = PointerToConnection() if self.tcpListener.getNewConnection(rendezvous, netAddress, newConnection): newConnection = newConnection.p() # Tell the reader about the new TCP connection self.tcpReader.addConnection(newConnection) # Handle the connection depending on persistent or not if self.core.server.isPersistent: self.core.handleConnection(generateUUID(), newConnection, netAddress) else: self.core.createPlayerObject(generateUUID(), newConnection, netAddress) print("Server: New Connection from -", str(netAddress.getIpString())) else: print("Server: Connection Failed from -", str(netAddress.getIpString())) return Task.cont def tcpReaderTask(self, task): """ Handle any data from clients by sending it to the Handlers. """ while 1: (datagram, data, opcode) = self.tcpNonBlockingRead(self.tcpReader) if opcode is MSG_NONE: # Do nothing or use it as some 'keep_alive' thing. break else: # Handle it self.core.packetManager.handlePacket(opcode, data, datagram.getAddress()) return Task.cont # TCP NonBlockingRead?? def tcpNonBlockingRead(self, qcr): """ Return a datagram collection and type if data is available on the queued connection udpReader """ if self.tcpReader.dataAvailable(): datagram = NetDatagram() if self.tcpReader.getData(datagram): data = DatagramIterator(datagram) opcode = data.getUint8() else: data = None opcode = MSG_NONE else: datagram = None data = None opcode = MSG_NONE # Return the datagram to keep a handle on the data return (datagram, data, opcode) # TCP Disconnection Handler def tcpDisconnectionHandler(self, task): # Check for resets if self.tcpManager.resetConnectionAvailable(): resetConnection = PointerToConnection() self.tcpManager.getResetConnection(resetConnection) for client in self.core.server.clients: if self.core.server.clients[ client].connection == resetConnection.p(): del self.core.server.clients[client] self.tcpReader.removeConnection(resetConnection.p()) print("Removed Connection:", resetConnection.p()) print('Current Clients:', self.core.server.clients) break return Task.cont def sendPacket(self, _pkt, _connection): self.tcpWriter.send(_pkt, _connection) def sendBroadcast(self, _pkt, _skipif=None): for client in self.serverManager.clients: if _skipif == client: pass else: conn = self.serverManager.clients[client].connection self.tcpWriter.send(_pkt, conn)
class Connection(ShowBase): def __init__(self): self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) try: host = "localhost" port = 9252 self.connection = self.cManager.openTCPClientConnection(host, port, 10000) self.received = 1 if self.connection: self.cReader.addConnection(self.connection) taskMgr.add(self.updateRoutine, "updateRoutine") # taskMgr.add(self.message, 'message') except: pass # def message(self, task): # self.option = 0 # self.option = str(raw_input("1-Send integer\n2-Send string\n3-Send short\n4-Send float\n")) # if self.option == "1": # msg = int(100 * random.random()) - 50 # request = self.intRequest(msg) # self.cWriter.send(request,self.connection) # print "sent ", msg # taskMgr.remove('message') # elif self.option == "2": # msg = ''.join(random.choice('abcdefghijklmnopqrstuvwxyz') for x in range(7)) # request = self.stringRequest(msg) # self.cWriter.send(request,self.connection) # print "sent ", msg # taskMgr.remove('message') # elif self.option == "3": # msg = int(100 * random.random()) # request = self.shortRequest(msg) # self.cWriter.send(request,self.connection) # print "sent ", msg # taskMgr.remove('message') # elif self.option == "4": # msg = 100 * random.random() # request = self.floatRequest(msg) # self.cWriter.send(request,self.connection) # print "sent ", msg # taskMgr.remove('message') def intRequest(self, msg): pkg = PyDatagram() pkg.addUint16(1) pkg.addInt32(msg) return pkg def stringRequest(self, msg): pkg = PyDatagram() pkg.addUint16(2) pkg.addString(msg) return pkg def shortRequest(self, msg): pkg = PyDatagram() pkg.addUint16(3) pkg.addUint16(msg) return pkg def floatRequest(self, msg): pkg = PyDatagram() pkg.addUint16(4) pkg.addFloat32(msg) return pkg def loginRequest(self, username, password): pkg = PyDatagram() pkg.addUint16(101) pkg.addString(username) pkg.addString(password) return pkg def registerRequest(self, username, password): pkg = PyDatagram() pkg.addUint16(103) pkg.addString(username) pkg.addString(password) return pkg def characterCreationRequest(self, username, classType): pkg = PyDatagram() pkg.addUint16(104) pkg.addString(username) pkg.addUint16(0) pkg.addUint16(classType) return pkg def chatRequest(self, message): pkg = PyDatagram() pkg.addUint16(105) pkg.addString(message) return pkg def moveRequest(self, x, y, z, h, isMoving): pkg = PyDatagram() pkg.addUint16(106) pkg.addFloat32(x) pkg.addFloat32(y) pkg.addFloat32(z) pkg.addFloat32(h) pkg.addUint16(isMoving) return pkg def check(self): while self.cReader.dataAvailable(): print "data here" datagram = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram): data = PyDatagramIterator(datagram) responseCode = data.getUint16() print responseCode if responseCode == 1: self.getInt(data) elif responseCode == 2: self.getString(data) elif responseCode == 3: self.getShort(data) elif responseCode == 4: self.getFloat(data) elif responseCode == 201: self.getLogin(data) elif responseCode == 203: self.getRegistion(data) elif responseCode == 204: self.getCharacterCreation(data) elif responseCode == 205: self.getChat(data) elif responseCode == 206: self.getMove(data) else: print "nothing found" def getInt(self, data): msg = data.getInt32() print "recieved ", msg taskMgr.add(self.message, "message") def getString(self, data): msg = data.getString() print "recieved ", msg taskMgr.add(self.message, "message") def getShort(self, data): msg = data.getUint16() print "recieved ", msg taskMgr.add(self.message, "message") def getFloat(self, data): msg = data.getFloat32() print "recieved ", msg taskMgr.add(self.message, "message") def getLogin(self, data): flag = data.getUint16() if flag == 0: print "Invalid Login" else: listSize = data.getUint16() for i in xrange(listSize): characterName = data.getString() characterId = data.getUint16() characterType = data.getUint16() characterFaction = data.getUint16() # Need to add these to an active characters class def getRegistion(self, data): flag = data.getUint16() if flag == 0: print "Invalid Login" else: print "Account Created" def getCharacterCreation(self, data): flag = data.getUint16() if flag == 0: print "Invalid Character" else: listSize = data.getUint16() for i in xrange(listSize): characterName = data.getString() characterId = data.getUint16() characterType = data.getUint16() characterFaction = data.getUint16() # Need to add these to an active characters class def getChat(self, data): username = data.getString() factionId = data.getUint16() message = data.getString() def getMove(self, data): username = data.getString() x = data.getFloat32() y = data.getFloat32() z = data.getFloat32() h = data.getFloat32() isMoving = data.getUint16() def updateRoutine(self, task): self.check() return task.again
class MyApp(ShowBase): def __init__(self): ShowBase.__init__(self) self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) self.player = Player() self.opponents = dict() self.logStat = -1 host = "localhost" port = 9252 self.connection = self.cManager.openTCPClientConnection(host, port, 10000) self.received = 1 self.playersText = [] if self.connection: self.cReader.addConnection(self.connection) taskMgr.add(self.updateRoutine, 'updateRoutine') taskMgr.add(self.login, 'login') #taskMgr.doMethodLater(3, self.updateRoutine, 'updateRoutine') taskMgr.doMethodLater(.1, self.heartbeat, 'heartbeat') self.accept("q", self.listPlayers) self.accept("q-up", self.delistPlayers) self.accept("escape", self.disconnect) self.accept("arrow_up", self.move) def login(self, task): self.option = 0 self.option = str(raw_input("1-Login\n2-Register\n")) if self.option == "1": un = str(raw_input("Username: "******"Password: "******"2": un = str(raw_input("Username: "******"Password: "******"data here" datagram = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram): data = PyDatagramIterator(datagram) responseCode = data.getUint16() print responseCode if responseCode == 201: self.getPlayer(data) elif responseCode == 202: self.register(data) elif responseCode == 203: self.getOpponent(data) elif responseCode == 214: self.movePlayer(data) elif responseCode == 219: self.dropPlayer(data) else: print "nothing found" def heartbeat(self, task): pkg = PyDatagram() pkg.addUint16(113) self.cWriter.send(pkg,self.connection) return task.again def updateRoutine(self,task): self.check() return task.again; def getPlayer(self, data): self.logStat = data.getUint16() if self.logStat == 0: self.player.id = data.getInt32() self.player.username = data.getString() self.player.x = data.getFloat32() self.player.y = data.getFloat32() self.player.z = data.getFloat32() self.player.rotation = data.getFloat32() else: print "login failed" taskMgr.add(self.login, 'login') def register(self, data): self.logStat = data.getUint16() if self.logStat == 0: print "Account Made" taskMgr.add(self.login, 'login') else: print "Username Taken" taskMgr.add(self.login, 'login') def listPlayers(self): i = 0.55 for p in self.opponents: self.playersText.append( addInstructions(i, self.opponents[p].username + " " + "{:.2f}".format(self.opponents[p].x) + " " + "{:.2f}".format(self.opponents[p].y) + " " + "{:.2f}".format(self.opponents[p].z) + " " + "{:.2f}".format(self.opponents[p].rotation) )) i -= 0.05 def delistPlayers(self): for x in self.playersText: x.destroy() def getOpponent(self, data): opponent = Player() opponent.id = data.getInt32() opponent.username = data.getString() opponent.x = data.getFloat32() opponent.y = data.getFloat32() opponent.z = data.getFloat32() opponent.rotation = data.getFloat32() self.opponents[opponent.id] = opponent
class ConnectionManager: def __init__(self, main): #self.world = world self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) self.main = main self.rqTable = ServerRequestTable() self.rsTable = ServerResponseTable() self.connection = None def startConnection(self): """Create a connection with the remote host. If a connection can be created, create a task with a sort value of -39 to read packets from the socket. """ try: if self.connection == None: self.connection = self.cManager.openTCPClientConnection(Constants.SERVER_IP, Constants.SERVER_PORT, 1000) if self.connection: self.cReader.addConnection(self.connection) taskMgr.add(self.updateRoutine, 'updateRoutine-Connection', -39) taskMgr.doMethodLater(5, self.checkConnection, 'checkConnection') return True except: pass return False def closeConnection(self): """Close the current connection with the remote host. If an existing connection is found, remove both the Main task, which is responsible for the heartbeat, and the Connection task, which is responsible for reading packets from the socket, then properly close the existing connection. """ if self.connection != None: taskMgr.remove('updateRoutine-Main') taskMgr.remove('updateRoutine-Connection') taskMgr.remove('checkConnection') self.cManager.closeConnection(self.connection) self.connection = None def sendRequest(self, requestCode, args = {}): """Prepare a request packet to be sent. If the following request code exists, create an instance of this specific request using any extra arguments, then properly send it to the remote host. """ if self.connection != None: request = self.rqTable.get(requestCode) if request != None: request.set(self.cWriter, self.connection) #print('requestCode:'+str(requestCode)) #print('args:'+str(args)) request.send(args) def handleResponse(self, responseCode, data): """Prepare a response packet to be processed. If the following response code exists, create an instance of this specific response using its data to be executed. """ response = self.rsTable.get(responseCode) if response != None: response.set(self.main) response.execute(data) def checkConnection(self, task): if not self.cReader.isConnectionOk(self.connection): self.closeConnection() #self.showDisconnected(0) return task.done return task.again def updateRoutine(self, task): """A once-per-frame task used to read packets from the socket.""" while self.cReader.dataAvailable(): # Create a datagram to store all necessary data. datagram = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram): # Prepare the datagram to be iterated. data = PyDatagramIterator(datagram) # Retrieve a "short" that contains the response code. responseCode = data.getUint16() # Pass into another method to execute the response. if responseCode != Constants.MSG_NONE: self.handleResponse(responseCode, data) return task.cont
class SocketHandler: logger = Logger("socket_handler") def __init__(self, port=None, host=None, ip_addr="127.0.0.1", backlog=10000, timeout=5000): self.port = port # our port self.host = host # host port self.ip_addr = ip_addr self.backlog = backlog self.timeout = timeout self.socket = None self.connection = None self.active_connections = [] self.handler = None self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) def setup_socket(self): self.socket = self.cManager.openTCPServerRendezvous( self.ip_addr, self.port, self.backlog) if self.socket is None: raise Exception("unable to open new socket at %s:%d" % (self.ip_addr, self.port)) self.cListener.addConnection(self.socket) taskMgr.add(self.listen_suggestions, "poll the suggestion listener") taskMgr.add(self.read_data, "poll the connection reader") def connect_socket(self): if self.connection is None: self.connection = self.cManager.openTCPClientConnection( self.ip_addr, self.host, self.timeout) if self.connection is None: raise Exception("unable to connect to socket at %s:%d" % (self.ip_addr, self.host)) self.cReader.addConnection(self.connection) taskMgr.add(self.read_data, "poll the socket reader") def listen_suggestions(self, task): # to be overridden by inheritors pass def read_data(self, task): if self.cReader.dataAvailable(): dg = NetDatagram() if self.cReader.getData(dg): self.handle_data(dg) return task.cont def handle_data(self, dg): # to be overridden by inheritors pass
class NetworkHost (): """ Handles networking with one or more clients. This class is essentially a server that handles the communication of GameManager's game logic. One player will have a NetworkHost and the rest of players will have NetworkClients. """ def __init__ (self, gameManager): self._connManager = QueuedConnectionManager() self._loadConfig() self._activeConns = [] # Active connections list. self._isActive = False self._backlog = HOST_MAX_BACKLOG self._gameManager = gameManager self._playerInfo = dict() # connections by connectionID (cID) self._creatures = dict() # Creatures by cID. self._localPlayerCID = None self._creatureIDCount = 0 def _initListener (self): """ Initializes this NetworkHost's connection listener. """ self._connListener = QueuedConnectionListener(self._connManager, 0) self._tcpSocket = connManager.openTCPServerRendezvous(self._portAddress, self._backlog) self._connListener.addConnection(self._tcpSocket) def _loadConfig (self): """ Loads network configuration defaults. """ self._portAddress = ConfigVariableInt("default-port", DEFAULT_PORT).getValue() def startHost (self): """ Finishes initialization and begins listening. """ # Initialize Reader and Writer: self._connReader = QueuedConnectionReader(self._connManager, 0) self._connWriter = ConnectionWriter(self._connManager, 0) # Initialize Listener: self._connListener = QueuedConnectionListener(self._connManager, 0) self._tcpSocket = self._connManager.openTCPServerRendezvous( self._portAddress, self._backlog) self._connListener.addConnection(self._tcpSocket) # Begin handling messages (start listening): taskMgr.add(self._onListenerPoll,"Poll the connection listener",-39) taskMgr.add(self._onReaderPoll,"Poll the connection reader",-40) self._isActive = True print ("[Host Started at %s]" % socket.gethostbyname( socket.gethostname())) self._gameManager.onHostInitialized() def _onListenerPoll(self, taskdata): """ Updates list of connections based on the listener's current findings. Does not read messages. See onReaderPoll(). (Assumes self._connListener has been initialized) """ # Check for new connections: if self._connListener.newConnectionAvailable(): rendezvous = PointerToConnection() netAddress = NetAddress() newConnection = PointerToConnection() # If we have a new connection, add it to our list: if self._connListener.getNewConnection(rendezvous,netAddress, newConnection): newConnection = newConnection.p() print ("[Host Received New Connection: %s]" % netAddress) self._activeConns.append(newConnection) # Begin reading messages from this new connection: self._connReader.addConnection(newConnection) # activate the onClientConnected functionalities: self.onClientConnected(newConnection) return Task.cont # Repeat this call on an interval def _onReaderPoll (self, taskdata): """ Called on an interval to interpret messages from the reader. """ if self._connReader.dataAvailable(): newDatagram = NetDatagram() # Double check to make sure (Multithreading safety): if self._connReader.getData(newDatagram): self._interpretDatagram(newDatagram) return Task.cont # Repeat this call on an interval def sendToClient (self, newMsg, conn, msgType): """ Sends a new message to a client at the other end of conn. """ print("[Server Sending %s message type %s]"%(str(conn), str(msgType))) self._connWriter.send(newMsg, conn) def sendToAll (self, newMsg, msgType): """ Writes and sends a new message to all connected clients. """ for conn in self._activeConns: self.sendToClient(newMsg, conn, msgType) def _interpretDatagram (self, datagram): """ Interprets a received datagram and performs actions based on its values. """ msg = PyDatagramIterator(datagram) msgType = msg.getUint8() if msgType == DEBUG_MESSAGE: print (msg.getString()) elif msgType == UPDATE_PLAYER_INFO: data = msg.getString() self._updatePlayerInfoHandler(datagram.getConnection().this, data) elif msgType == SPAWN_CHARACTER: data = msg.getString() dataDict = json.loads(data) self._onSpawnHandler(dataDict) elif msgType == SYNC_ACTION: data = msg.getString() dataDict = json.loads(data) self._onActionSyncHandler(dataDict, datagram.getConnection()) elif msgType == SYNC_RESPAWN: data = msg.getString() dataDict = json.loads(data) self._onRespawnRequestReceived(dataDict) elif msgType == WIN_STATE: data = msg.getString() self._onGameWon(data) def isHosting (self): """ Returns whether this NetworkHost is actively hosting. """ return self._isActive def getMyCID (self): return self._localPlayerCID def registerNewCID (self): newCID = "host" + str(self._creatureIDCount) self._creatureIDCount += 1 return newCID def registerLocalCID (self): newCID = self.registerNewCID() self._localPlayerCID = newCID # === [Local Client to Network] === def onCreatureDeath (self, creature): """ Sends a creature death message to all connected clients. """ msg = createSyncDeathMessage(creature.getCID()) self.sendToAll(msg, SYNC_DEATH) def onLocalPlayerRespawn (self, creature, newLocation): """ Respawns the local player and sends a sync message to all remotes. """ # Fulfill local player request to respawn: creature.respawn(newLocation) # Refill the creature's HP (Automatically syncs!): creature.takeDamage(-1*creature.getMaxHealth()) # Spawn on all connected clients: msg = createRespawnMessage(creature.getCID(), newLocation) self.sendToAll(msg, SYNC_RESPAWN) def localPlayerWins (self): """ End the game display the win screen. """ self._gameManager.onWinStateAchieved(self._playerInfo[self.getMyCID()]) msg = createWinMessage(self._playerInfo[self.getMyCID()]) self.sendToAll(msg, WIN_STATE) def updateLocalPlayerInfo (self, info=None): """ Updates info for this local player and sends it to all connected clients. """ if not info: self._playerInfo[self.getMyCID()] = PlayerInfo(cID=self.getMyCID()) else: # If info == None, we are just initializing. self._playerInfo[self.getMyCID()] = info infoMsg = createPlayerInfoMessage(info) self.sendToAll(infoMsg, UPDATE_PLAYER_INFO) # === === # === [Gameplay specific] === def _onGameWon (self, data): """ Boo. A remote client won. Oh well. Still have to sync that win across all other clients. """ # Show winner locally: winnerData = PlayerInfo(fromJson=data) self._gameManager.onWinStateAchieved(winnerData) msg = createWinMessage(winnerData) self.sendToAll(msg, WIN_STATE) def syncAction (self, cID, actionID, **kwargs): """ The local player has performed an action that must be synced across the network. Send a message to all clients telling them to perform a related action on that character. """ msg = createSyncActionMessage(cID, actionID, **kwargs) self.sendToAll(msg, SYNC_ACTION) def spawnGameObject (self, gameObject): """ Tracks the given gameObject and sends it to all clients. """ # First, track it locally: self._creatures[gameObject.getCID()] = gameObject # Send to all clients: msg = createSpawnCharacterMessage(gameObject, gameObject.getCID()) self.sendToAll(msg, SPAWN_CHARACTER) def dropItem (self, itemEnum, pos): """ Spawn a new item locally and sync! """ itemID = self.registerNewCID() # Create item locally: newItem = ITEM_ID_DICT[itemEnum](self._gameManager, itemID, coords=pos) self._gameManager.getTileMap().spawnItem(newItem, pos) # Track new item: self._creatures[itemID] = newItem msg = createSpawnItemMessage(newItem) self.sendToAll(msg, SPAWN_ITEM) def _onSpawnHandler (self, dataDict): """ Handles networking spawning characters """ # Spawn object locally if the object at cID doesn't already exist. if not dataDict['objID'] in self._creatures.keys(): # Spawn object of charType at pos objectType = getCharacterTypeAsClass(dataDict['charType']) newPos = Point2D(dataDict['pos'][0], dataDict['pos'][1]) newChar = objectType(parentCtrlr=None, cID=dataDict['objID'], gameManager=self._gameManager, coords=newPos) self._creatures[dataDict['objID']] = newChar self._gameManager.getTileMap().spawnObject(newChar, newPos) print("[Server Spawned %s]" % dataDict['objID']) # If we have a player info for this player, use their name for the # displayName: if dataDict['objID'] in self._playerInfo: newName = self._playerInfo[dataDict['objID']].cName newChar.setNameDisplay(newName) else: # Ignore Overwrite pass # Tell all other clients to spawn objects: newMsg = createSpawnCharacterMessage(self._creatures[dataDict['objID']], dataDict['objID']) self.sendToAll(newMsg, SPAWN_CHARACTER) def _onActionSyncHandler (self, dataDict, msgConn): """ Attempts to queue an action for execution on a target denoted by dataDict['objID'] """ copyMsg = createSyncActionMessage(**dataDict) syncedAction = ACTION_NETWORKING_DICT[dataDict['actionID']] # Add a few local variables to dataDict: targetObj = self._creatures[dataDict['objID']] # TODO Maybe make this part of dataDict! dataDict['tileMap'] = self._gameManager.getTileMap() if 'targetCID' in dataDict: # If there is another target: # Assign the target: dataDict['target'] = self._creatures[dataDict['targetCID']] dataDict['isServer'] = True # Let sync function know we are server # Create the newAction newAction = syncedAction(targetObj, **dataDict) targetObj.startAction(newAction) # queue or start the new action # Send action to all clients except the client that sent the sync msg: for client in self.getAllClientsExcept(msgConn): self.sendToClient(copyMsg, client, SYNC_ACTION) def _onRespawnRequestReceived (self, dataDict): """ Respawns the remote clients character in a new position and then syncs to all clients (including the one who requested). """ newPos = self._gameManager.getTileMap().getRandomEmptyFloor() targetObj = self._creatures[dataDict['objID']] # Set the target's HP to full and sync that: targetObj.takeDamage(-1*targetObj.getMaxHealth()) targetObj.respawn(newPos) # Sync the respawn to all clients: newMsg = createRespawnMessage(targetObj.getCID(), newPos) self.sendToAll(newMsg, SYNC_RESPAWN) def getAllClientsExcept (self, exceptConn): clientList = list() for conn in self._activeConns: if conn != exceptConn: clientList.append(conn) return clientList def onClientConnected (self, clientConn): """ If we have a map and/or any positional data, give it to this client. Also signal to the GameManager and all remote clients that a new player connected! """ connID = clientConn.this tileMap = self._gameManager.getTileMap() if tileMap != None: data = tileMap.getTileMapStr() msg = createMapMessage(data) self.sendToClient(msg, clientConn, MAP_MESSAGE) # Send player info to the new client: for player in self._playerInfo: # Don't send an info message about the player to the same player! if player != connID: newInfoMsg = createPlayerInfoMessage(self._playerInfo[player]) self.sendToClient(newInfoMsg, clientConn, UPDATE_PLAYER_INFO) # Send all creatures to the new client: for creatureID in self._creatures: newMsg = createSpawnCharacterMessage(self._creatures[creatureID], creatureID) self.sendToClient(newMsg, clientConn, SPAWN_CHARACTER) def _updatePlayerInfoHandler (self, connID, data=None): """ Adds data to self._playerInfo. If info doesn't exist, creates a new one for clientConn. """ if data != None: newPlayerData = PlayerInfo(fromJson=data) else: newPlayerData = PlayerInfo(cID=connID) # Update the playerInfo dict with the new data: self._playerInfo[newPlayerData.cID] = newPlayerData self._gameManager.updatePartyInfo(self._playerInfo, self.getMyCID()) # Send player info to every client: for player in self._playerInfo: newInfoMsg = createPlayerInfoMessage(self._playerInfo[player]) #Send every player to every client: self.sendToAll(newInfoMsg, UPDATE_PLAYER_INFO) # Update the creature's floating display name locally: if newPlayerData.cID in self._creatures: self._creatures[newPlayerData.cID]\ .setNameDisplay(newPlayerData.cName) def syncHealthChange (self, creatureID, newHealth): """ Called after the host runs a damage/healing action on a creature. Lets all clients know to update to a new value. """ data = createSyncHealthMessage(creatureID, newHealth) self.sendToAll(data, SYNC_HEALTH)
class Connection(GlobalClockMixin, TaskMixin): def __init__(self, base, host, port): self.base = base self.host = host self.port = port self._conn = None self._retry_elapsed = 0 self._retry_next = 0 self._data_last_received = 0 self.manager = QueuedConnectionManager() self.reader = QueuedConnectionReader( self.manager, 0, # number of threads ) # we're using our own protocol so we don't want panda reading our headers and getting # all foobared by it (not setting raw mode causes `dataAvailable` to block # once there is actually data to process) self.reader.setRawMode(True) self.writer = ConnectionWriter( self.manager, 0, # number of threads ) def connect(self, connected_callback, task): """ Attempts to connect to the server and if unable to will retry adding a second to the wait time to each consecutive failure. """ self._retry_elapsed += self.get_dt() if self._retry_elapsed < self._retry_next: return task.cont logging.debug( 'attempting to connect to server at %s:%d', self.host, self.port ) self._conn = self.manager.openTCPClientConnection( self.host, self.port, 10000, # timeout ms ) if self._conn: logging.debug('connection established') self.reader.addConnection(self._conn) # reset the counters in case the connection drops and we have to restart the # connection process self._retry_elapsed = 0 self._retry_next = 0 # add a task to poll the connection for data self.add_task( self.task_read_polling, name='connection_reader_poll', sort=-39, ) connected_callback() return # no connection so retry in a bit self._retry_elapsed = 0 if self._retry_next == 0: self._retry_next = 1 elif self._retry_next > 9: self._retry_next = 10 else: self._retry_next += 1 logging.error( 'Unable to connect to server %s:%s, will retry in %d seconds', self.host, self.port, self._retry_next, ) return task.cont def task_read_polling(self, task): if self.reader.dataAvailable(): logging.debug('data available from server') datagram = Datagram() if self.reader.getData(datagram): logging.debug('received data from server: %s', datagram) logging.debug('received data from server: %s', datagram.getMessage()) # TODO: provide a way to supply a data callback self._data_last_received = 0 else: # no data received logging.debug('no data') self._data_last_received += self.get_dt() if self._data_last_received >= 10: logging.error('connection to server lost') return return task.cont def shutdown(self): logging.info('connection reader shutting down') self.reader.shutdown()
class ConnectionManager: def __init__(self, main): self.main = main self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) self.rqTable = ServerRequestTable() self.rsTable = ServerResponseTable() self.connection = None def startConnection(self): """Create a connection with the remote host. If a connection can be created, create a task with a sort value of -39 to read packets from the socket. """ if self.connection == None: self.connection = self.cManager.openTCPClientConnection(Constants.SERVER_IP, Constants.SERVER_PORT, 1000) if self.connection: self.cReader.addConnection(self.connection) return True return False def initTasks(self): """Initialize tasks to check on connection and send heartbeat. This must be done here because in `Main` we do not initialize Panda3D until after a connection is started. Thus, `taskMgr` is not defined when `startConnection()` is called. We rely on the callee to also run `initTasks()` after a successful connection is created. """ if self.connection != None: taskMgr.add(self.updateRoutine, "updateRoutine-Connection") taskMgr.doMethodLater(5, self.checkConnection, "checkConnection") taskMgr.doMethodLater(1.0 / Constants.TICKRATE, self.sendHeartbeat, "sendHeartbeat") def closeConnection(self): """Close the current connection with the remote host. If an existing connection is found, remove both the Main task, which is responsible for the heartbeat, and the Connection task, which is responsible for reading packets from the socket, then properly close the existing connection. """ if self.connection != None: taskMgr.remove("updateRoutine-Connection") taskMgr.remove("checkConnection") self.cManager.closeConnection(self.connection) self.connection = None def sendRequest(self, requestCode, args={}): """Prepare a request packet to be sent. If the following request code exists, create an instance of this specific request using any extra arguments, then properly send it to the remote host. """ if self.connection != None: request = self.rqTable.get(requestCode) if request != None: request.set(self.cWriter, self.connection) request.send(args) def handleResponse(self, responseCode, data): """Prepare a response packet to be processed. If the following response code exists, create an instance of this specific response using its data to be executed. """ response = self.rsTable.get(responseCode) if response != None: response.set(self.main) response.execute(data) def checkConnection(self, task): if not self.cReader.isConnectionOk(self.connection): self.closeConnection() self.showDisconnected(0) return task.done return task.again def updateRoutine(self, task): """A once-per-frame task used to read packets from the socket.""" while self.cReader.dataAvailable(): # Create a datagram to store all necessary data. datagram = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram): # Prepare the datagram to be iterated. data = PyDatagramIterator(datagram) # Retrieve a "short" that contains the response code. responseCode = data.getUint16() # Pass into another method to execute the response. if responseCode != Constants.MSG_NONE: self.handleResponse(responseCode, data) return task.cont def sendHeartbeat(self, task): if self.connection != None: self.sendRequest(Constants.C_HEARTBEAT) return task.again
class Server(object): # https://www.panda3d.org/manual/index.php/Client-Server_Connection def __init__(self, host="localhost", port=5001): taskMgr = Task.TaskManager() self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) self.activeConnections = [] # We'll want to keep track of these later self.readerCallbacks = [] backlog = 1000 #If we ignore 1,000 connection attempts, something is wrong! self.tcpSocket = self.cManager.openTCPServerRendezvous(port, backlog) self.cListener.addConnection(self.tcpSocket) taskMgr.add(self.tskListenerPolling, "Poll the connection listener", -39) taskMgr.add(self.tskReaderPolling, "Poll the connection reader", -40) print("started server! ({} at {})".format(port, host)) def Start(self): # derived servers can overwrite this function if needed pass def tskListenerPolling(self, taskdata): # listen for new connections # TODO(victor): what happens if a client shuts down? # print("server.tskListenerPolling()") if self.cListener.newConnectionAvailable(): rendezvous = PointerToConnection() netAddress = NetAddress() newConnection = PointerToConnection() if self.cListener.getNewConnection(rendezvous, netAddress, newConnection): newConnection = newConnection.p() self.activeConnections.append( newConnection) # Remember connection self.cReader.addConnection( newConnection) # Begin reading connection print("server: received new connection!") return Task.cont def tskReaderPolling(self, taskdata): # reader callback if not self.cReader.dataAvailable(): return Task.cont # catch the incoming data in this instance # Check the return value; if we were threaded, someone else could have # snagged this data before we did datagram = NetDatagram() if not self.cReader.getData(datagram): return Task.cont for callback in self.readerCallbacks: callback(datagram) return Task.cont def addReaderCallback(self, callbackFunction): self.readerCallbacks.append(callbackFunction) def BroadcastMessage(self, datagram): # send the same message to all clients for client in self.activeConnections: self.cWriter.send(datagram, client) def Close(self): # remove all clients for client in self.activeConnections: self.cReader.removeConnection(client) self.activeConnections = [] # close down our listener self.cManager.closeConnection(self.tcpSocket)