def tick(self): cur_time = time.time() if not (self.sock.protocol_mode == mcsock.protocol_modes['play']): return if (cur_time-self.last_tick) >= self.tick_delay: self.minecraft_client_tick() self.last_tick = cur_time if (cur_time - self.last_full_update) >= 1.0: self.full_update() self.last_full_update = cur_time end_time = time.time() if end_time-cur_time <= self.tick_delay: eventlet.greenthread.sleep(self.tick_delay-end_time-cur_time) # this should make updates very slightly mildly smoother, but only a little bit else: yatelog.warn('minecraft','tick took longer than the standard tick delay - this usually indicates you need a better CPU or better coding skills')
def __call__(self, *args, **kwargs): if not kwargs.has_key('protomode'): protomode = self.sock.protocol_mode else: protomode = kwargs['protomode'] if not self.idents.has_key(protomode): yatelog.warn( 'MCSock', 'No ident for packet %s in current protocol mode %s' % (self.name, protocol_modes[protomode])) return data = b"" for arg in args: data += arg self.sock.sendraw(self.idents[protomode], data)
def readpack(self): """ Reads a single packet from the socket Used internally, must NOT be called from anywhere but read_thread lest bad things happen After reading the packet, if a handler is registered then we throw it to that handler in a greenlet """ if self.protocol_mode < 3: max_bits = 21 else: max_bits = 32 packlen = self.recv_buff.unpack_varint(max_bits=max_bits) self.recv_buff.add(self.cipher.decrypt(self.tcp_sock.recv(packlen))) packbody = self.recv_buff.read(packlen) pack_buff = buffer.Buffer() pack_buff.add(packbody) if self.compression_enabled: uncompressed_len = pack_buff.unpack_varint() if uncompressed_len > 0: data = zlib.decompress(pack_buff.read()) pack_buff = buffer.Buffer() pack_buff.add(data) try: ident = pack_buff.unpack_varint() k = (self.protocol_version, protocol_modes[self.protocol_mode], 'downstream', ident) if packets.packet_names.has_key(k): if self.handlers.has_key(packets.packet_names[k]): try: if self.blocking_handlers: self.handlers[packets.packet_names[k]](pack_buff) else: self.pool.spawn_n( self.handler_wrapper, packets.packet_names[k], self.handlers[packets.packet_names[k]], pack_buff) except: yatelog.minor_exception( 'MCSock', 'Error scheduling packet handler') else: yatelog.warn( 'MCSock', 'Received unhandled packet: %s' % packets.packet_names[k]) else: yatelog.error('MCSock', 'Unknown packet received: %s' % str(k)) except: yatelog.minor_exception('MCSock', 'Failed decoding received packet')
def get_voxel(self,spatial_pos): yatelog.debug('minecraft','Querying block at %s' % str(spatial_pos)) insane_x = spatial_pos[0] insane_y = spatial_pos[2] insane_z = spatial_pos[1] block = self.world.get_block(insane_x,insane_y,insane_z) if block is None: yate_type = YATE_VOXEL_UNKNOWN yatelog.warn('minecraft','Requested unknown block at %s' % (str(spatial_pos))) vox = base.YateBaseVoxel(spatial_pos=tuple(spatial_pos),basic_type=YATE_VOXEL_UNKNOWN) return vox yatelog.debug('minecraft','Block is %s' % str(block)) blockid = block[0] blockdata = burger_data.blockid_blocks[blockid] yatelog.debug('minecraft','Block at %s: %s' % (str(spatial_pos),blockdata)) if blockdata['hardness'] == 0: yate_type=YATE_VOXEL_EMPTY if blockdata['hardness'] > 0: yate_type=YATE_VOXEL_TOTAL_OBSTACLE vox = base.YateBaseVoxel(spatial_pos=tuple(spatial_pos),basic_type=yate_type,specific_type=blockid) return vox
def timeout_thread(self): """ kill peers that have timed out """ while self.active: eventlet.greenthread.sleep(YATE_KEEPALIVE_TIMEOUT) cur_time = time.time() peer_list = self.known_peers.copy() # thread safety bitches for peer in peer_list: if not self.last_pack.has_key(peer): yatelog.warn( 'YATESock', 'Peer %s:%s never actually sent us a single packet after connecting' % peer) self.known_peers.discard(peer) else: if cur_time - self.last_pack[peer] > YATE_KEEPALIVE_TIMEOUT: yatelog.info('YATESock', 'Peer %s:%s has timed out, bye' % peer) self.known_peers.discard(peer)
def msg_reader_thread(self, msg_type): """ This is used internally to handle all messages of the specified type when they come in from the parser thread """ msg_type_s = msgtype_str[msg_type] while self.active: eventlet.greenthread.sleep(0) if not self.handlers.has_key( msg_type ): # don't bother wasting CPU time on it, just pull from the queue and then do nothing else yatelog.warn('YATESock', 'No handler for %s' % msg_type_s) try: self.in_queues[msg_type].get() except: pass continue eventlet.greenthread.sleep(0) msg_tuple = None while msg_tuple == None: eventlet.greenthread.sleep(0) try: msg_tuple = self.in_queues[msg_type].get() except: yatelog.minor_exception('YATESock', 'Error reading packet from queue') if msg_tuple != None: msg_params = msg_tuple[0] msg_id = msg_tuple[1] from_addr = msg_tuple[2] yatelog.debug( 'YATESock', 'Got message %s from %s:%s: %s' % (msg_type_s, from_addr[0], from_addr[1], msg_params)) if (from_addr in self.known_peers): try: self.handlers[msg_type](msg_params, from_addr, msg_id) except: yatelog.minor_exception('YATESock', 'Error handling message') else: if msg_type == MSGTYPE_CONNECT: self.handle_connect(msg_params, from_addr, msg_id) else: self.send_unknown_peer(to_addr=from_addr)