def registerHost(username, map, players, playerSlots): p = net.Packet() p.add(net.Uint8(net.PACKET_REGISTERHOST)) p.add(net.String(username)) p.add(net.String(map)) p.add(net.Uint8(players)) p.add(net.Uint8(playerSlots)) net.context.send(p, address)
def serverUpdate(self, aiWorld, entityGroup, packetUpdate): p = net.Packet() if packetUpdate: self.criticalUpdate = len(self.criticalPackets) > 0 for packet in self.criticalPackets: p.add(packet) del self.criticalPackets[:] else: self.criticalUpdate = False p.add(net.Uint8(self.id)) return p
def connectTo(ip, port=None): if port == None: if ip.find(":") != -1: ip, port = ip.split(":") else: port = 1337 port = int(port) engine.log.info("Notifying lobby server of intention to connect to " + ip + ":" + str(port)) p = net.Packet() p.add(net.Uint8(net.PACKET_CLIENTCONNECTNOTIFICATION)) p.add(net.String(ip)) p.add(net.Uint16(port)) net.context.send(p, address)
def update(self, backend): # Only send out an update packet if we need to packetUpdate = False if engine.clock.time - self.lastPacketUpdate >= net.SERVER_TICK: packetUpdate = True self.lastPacketUpdate = engine.clock.time # Reset packet update timer sendSpawn = False spawnPacket = net.Packet() if len(self.spawnPackets) > 0 and packetUpdate: sendSpawn = True for p in self.spawnPackets: spawnPacket.add(p) del self.spawnPackets[:] entityList = backend.entityGroup.entities.values() updatedEntities = [] controllerPacket = net.Packet() for entity in (x for x in entityList if x.active and x.isLocal): # Do a server update for local entities. # The controller packet is only sent if we've exceeded the regular packet update interval. p = entity.controller.serverUpdate(backend.aiWorld, backend.entityGroup, packetUpdate) if p != None and entity.controller.needsToSendUpdate(): controllerPacket.add(p) updatedEntities.append(entity) # Make sure we update our own copy of the entities. sendController = False if len(controllerPacket.dataObjects) > 0: sendController = True data = PyDatagram() controllerPacket.addTo(data) self.processPacket(data, backend) deletePacket = net.Packet() sendDelete = False if len(self.deletePackets) > 0 and packetUpdate: sendDelete = True for p in self.deletePackets: deletePacket.add(p) del self.deletePackets[:] if packetUpdate: outboundPacket = net.Packet() outboundPacket.add(spawnPacket) outboundPacket.add(controllerPacket) outboundPacket.add(deletePacket) for chat in self.chatPackets: outboundPacket.add(chat) sendChat = len(self.chatPackets) > 0 del self.chatPackets[:] for request in self.clientSpawnPacketRequests: entity = backend.entityGroup.getEntity(request[0]) if entity != None: if net.netMode == net.MODE_CLIENT: outboundPacket.add( entity.controller.buildSpawnPacket()) else: temp = net.Packet() temp.add(entity.controller.buildSpawnPacket()) net.context.send(temp, request[1]) engine.log.info("Sending missed spawn packet (ID " + str(request[0]) + ") to client " + net.addressToString(request[1])) else: engine.log.warning( "Client requested spawn packet for non-existent entity." ) del self.clientSpawnPacketRequests[:] sendCheckSum = False if net.netMode == net.MODE_SERVER and engine.clock.time - self.lastCheckSumSent > 5.0: self.lastCheckSumSent = engine.clock.time checkSumPacket = net.Packet() checkSumPacket.add(net.Uint8(net.PACKET_ENTITYCHECKSUM)) checkSumPacket.add( net.Uint8( len([ x for x in entityList if x.active and x.getId() < 256 ]))) outboundPacket.add(checkSumPacket) sendCheckSum = True if sendSpawn or sendController or sendDelete or sendCheckSum or sendChat: net.context.broadcast(outboundPacket) packets = net.context.readTick() for packet in packets: data = PyDatagram(packet[0]) rebroadcast = self.processPacket(data, backend, packet[1]) self.incomingPackets += 1 self.totalIncomingPacketSize += len(packet[0]) if net.netMode == net.MODE_SERVER and rebroadcast: net.context.broadcastDatagramExcept(data, packet[1]) del packets if len(entityList) > len(updatedEntities): for entity in (x for x in entityList if x.active and not x in updatedEntities): entity.controller.clientUpdate(backend.aiWorld, backend.entityGroup) clientAddress = [] if net.netMode == net.MODE_SERVER else [ net.context.hostConnection ] emptyPacket = net.Packet() emptyPacket.add(net.Uint8(net.PACKET_EMPTY)) for client in (x for x in net.context.activeConnections.values() + clientAddress if net.timeFunction() - x.lastSentPacketTime > 0.5 and x.ready): net.context.send(emptyPacket, client.address) net.context.writeTick()
def processPacket(self, packet, backend, sender=None): iterator = PyDatagramIterator(packet) lastId = "None" lastController = "None" try: rebroadcast = True while iterator.getRemainingSize() > 0: type = net.Uint8.getFrom(iterator) if type == net.PACKET_CONTROLLER: rebroadcast = True id = net.Uint8.getFrom(iterator) entity = backend.entityGroup.getEntity(id) if entity != None: lastId = str(id) lastController = entity.controller entity.controller.clientUpdate(backend.aiWorld, backend.entityGroup, iterator) else: engine.log.warning( "Received controller packet with no matching entity. ID: " + str(id) + " Last entity updated: " + lastId + " - controller: " + str(lastController)) if sender != None and ( (not id in self.requestedEntitySpawns.keys()) or (engine.clock.time - self.requestedEntitySpawns[id] > 2.0) ): # Only send a request once every two seconds p = net.Packet() p.add(net.Uint8(net.PACKET_REQUESTSPAWNPACKET)) p.add(net.Uint8(id)) net.context.send(p, sender) self.requestedEntitySpawns[id] = engine.clock.time engine.log.info( "Sending request for missing entity spawn packet. Entity ID: " + str(id)) return rebroadcast elif type == net.PACKET_SPAWN: controllerType = net.Uint8.getFrom(iterator) entity = controllers.types[controllerType].readSpawnPacket( backend.aiWorld, backend.entityGroup, iterator) if entity.getId() in self.requestedEntitySpawns.keys(): del self.requestedEntitySpawns[entity.getId()] if entity != None and backend.entityGroup.getEntity( entity.getId()) == None: backend.entityGroup.addEntity(entity) elif entity != None: engine.log.warning( "Spawned entity " + str(entity.getId()) + " already exists. Cancelling spawn.") entity.delete(backend.entityGroup, killed=False, localDelete=False) rebroadcast = True elif type == net.PACKET_DELETE: id = net.Uint8.getFrom(iterator) entity = backend.entityGroup.getEntity(id) killed = net.Boolean.getFrom(iterator) if entity != None: if killed: # The boolean indicates that the entity was not only deleted, it was killed. Also, let the entity know this was a remote delete packet. entity.kill(backend.aiWorld, backend.entityGroup, False) else: entity.delete(backend.entityGroup, False, False) rebroadcast = True elif type == net.PACKET_REQUESTSPAWNPACKET: self.clientSpawnPacketRequests.append( (net.Uint8.getFrom(iterator), sender)) rebroadcast = False elif type == net.PACKET_SETUP: if net.netMode == net.MODE_CLIENT: messenger.send("client-setup", [iterator]) else: return False rebroadcast = False elif type == net.PACKET_CHAT: messenger.send("chat-incoming", [ net.String.getFrom(iterator), net.String.getFrom(iterator) ]) # Username and message rebroadcast = True elif type == net.PACKET_ENDMATCH: engine.log.info("Received match end packet.") messenger.send("end-match", [iterator]) rebroadcast = True elif type == net.PACKET_NEWCLIENT: messenger.send( "server-new-connection", [sender, net.String.getFrom(iterator) ]) # Sender address and username rebroadcast = False elif type == net.PACKET_DISCONNECT: engine.log.info( net.addressToString(sender) + " disconnected.") messenger.send("disconnect", [sender]) rebroadcast = False elif type == net.PACKET_SERVERFULL: messenger.send("server-full") elif type == net.PACKET_CONFIRMREGISTER: messenger.send("lobby-confirm-register") rebroadcast = False elif type == net.PACKET_EMPTY: rebroadcast = False elif type == net.PACKET_CLIENTREADY: rebroadcast = False messenger.send("client-ready", [sender]) elif type == net.PACKET_NEWCLIENTNOTIFICATION: address = net.String.getFrom(iterator) port = net.Uint16.getFrom(iterator) # Make sure we get all the data out of the packet to ensure proper processing. # This packet has already been handled by the NetContext. rebroadcast = False elif type == net.PACKET_ENTITYCHECKSUM: checksum = net.Uint8.getFrom( iterator ) # Number of active entities we're supposed to have if net.netMode == net.MODE_CLIENT and checksum != len([ x for x in backend.entityGroup.entities.values() if x.active and x.getId() < 256 ]): # We don't have the right number of entities p = net.Packet() p.add(net.Uint8(net.PACKET_REQUESTENTITYLIST)) net.context.send(p, sender) engine.log.info( "Entity checksum failed. Requesting full entity list." ) rebroadcast = False elif type == net.PACKET_REQUESTENTITYLIST: p = net.Packet() p.add(net.Uint8(net.PACKET_ENTITYLIST)) entityList = [ x for x in backend.entityGroup.entities.values() if x.active and x.getId() < 256 ] p.add(net.Uint8(len(entityList))) for entity in entityList: p.add(net.Uint8(entity.getId())) net.context.send(p, sender) engine.log.info("Sending entity list to " + net.addressToString(sender)) rebroadcast = False elif type == net.PACKET_ENTITYLIST: total = net.Uint8.getFrom(iterator) entities = [] missingEntities = [] for _ in range(total): id = net.Uint8.getFrom(iterator) if id not in backend.entityGroup.entities.keys(): missingEntities.append(id) entities.append(id) # Delete any extra entities, assuming they aren't ones that we just spawned on our end. for entity in ( x for x in backend.entityGroup.entities.values() if x.active and x.getId() < 256): if entity.getId( ) not in entities and engine.clock.time - entity.spawnTime > 5.0: entity.delete(backend.entityGroup, False, False) if len(missingEntities) > 0: # Request spawn packets for any missing entities p = net.Packet() for id in missingEntities: p.add(net.Uint8(net.PACKET_REQUESTSPAWNPACKET)) p.add(net.Uint8(id)) self.requestedEntitySpawns[id] = engine.clock.time engine.log.info( "Sending request for missing entity spawn packet. Entity ID: " + str(id)) net.context.send(p, sender) rebroadcast = False else: rebroadcast = False except AssertionError: engine.log.warning("Packet iteration failed. Discarding packet.") rebroadcast = False return rebroadcast
def chatHandler(self, username, message): p = net.Packet() p.add(net.Uint8(net.PACKET_CHAT)) p.add(net.String(username)) p.add(net.String(message)) self.chatPackets.append(p)
def getHosts(): engine.log.info("Requesting host list from lobby server") p = net.Packet() p.add(net.Uint8(net.PACKET_REQUESTHOSTLIST)) net.context.send(p, address)