Pierre-Marie de Rodat avatar Pierre-Marie de Rodat committed 07c75d1

Replace gevent multitasking by threading.

The conversion is partial, since some concurrency bugs remains, but tasks are
now scheduled fairly.

Comments (0)

Files changed (3)

 # -*- coding: utf-8 -*-
 
 import collections
+from Queue import Queue
+import socket
 import StringIO
-
-import gevent
-import gevent.queue
-import gevent.socket as socket
+import threading
 
 import map
 from packet import *
     def __init__(self, username):
         self.username = username
         self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        self.receiving_coroutine = None
-        self.sending_coroutine = None
-        self.sending_queue = gevent.queue.Queue(maxsize=5)
+        self.receiving_thread = None
+        self.sending_thread = None
+        self.sending_queue = Queue(maxsize=100)
         self.map = None
         self.spawned = False
         self.spawn_position = None
 
         # Login is successful, start network coroutines and initialize data.
         self.connected = True
-        self.receiving_coroutine = gevent.Greenlet.spawn(self.receive_forever)
-        self.sending_coroutine = gevent.Greenlet.spawn(self.send_forever)
-        self.player_coroutine = gevent.Greenlet.spawn(self.serve_player)
+        self.receiving_thread = threading.Thread(target=self.receive_forever)
+        self.sending_thread = threading.Thread(target=self.send_forever)
         self.map = map.Map()
         self.player = map.Player(self.map)
+        self.receiving_thread.start()
+        self.sending_thread.start()
 
     def expect_packet(self, packet, expected):
         if isinstance(packet, Disconnect):
         while True:
             packet = self.recv_packet()
             self.handlers[packet.packet_id](packet)
-            gevent.sleep()
 
     def send_packet(self, packet):
         try:
             packet = self.sending_queue.get()
             self.send_packet(packet)
 
-    def serve_player(self):
-        '''
-        Send to the server the player position every 50 ms once spawn.
-        '''
-        while self.connected:
-            if self.spawned:
-                self.put_packet(self.player.get_position_packet())
-            gevent.sleep(0.05)
-
     def on_disconnection(self, exception):
         '''
         Simple hook, can be overridden by subclasses. 'exception' contains the
         self.on_disconnection(None)
 
     def handle_keepalive(self, packet):
-        # The server testst the connection sending a Keep Alive packet.
+        # The server tests the connection sending a Keep Alive packet.
         # We must send back the same packet.
         self.put_packet(packet)
 
         pass
 
     def handle_spawnposition(self, packet):
-        print 'Got spawnposition'
         self.spawn_position = (packet.x, packet.y, packet.z)
         if not self.spawned:
             self.player.set_position(packet.x, packet.y, packet.z)
 
     def handle_playerposition(self, packet):
-        print 'Got playerposition: %s' % packet
         self.player.set_position(packet.x, packet.y, packet.z, packet.stance)
         self.spawned = True
 
     def handle_playerpositionlook(self, packet):
-        print 'Got playerpositionlook: %s' % packet
         self.player.set_position(packet.x, packet.y, packet.z, packet.stance)
         self.player.set_look(packet.yaw, packet.pitch)
         if not self.spawned:
             self.spawned = True
+        # Acknowledge the server that we agree with him, not to be kicked.
+        self.put_packet(self.player.get_position_packet())
 
     def handle_prechunk(self, packet):
         if packet.mode:
             self.map.put((packet.x, packet.z), map.Chunk())
         else:
             self.map.remove((packet.x, packet.z))
-        if len(self.map.chunks) % 30 == 0:
-            print '-> %s' % len(self.map.chunks)
 
     def handle_mapchunk(self, packet):
         chunk_x = packet.x >> 4
 # -*- coding: utf-8 -*-
 
 import collections
+import math
 
 from packet import PlayerPositionLookClient
 
             stance=self.stance, on_ground=self.on_ground,
             yaw=self.yaw, pitch=self.pitch
         )
+
+    def center(self):
+        '''
+        Put the player at the center of the current block.
+        '''
+        self.set_position(
+            x=math.floor(self.x) + 0.5,
+            z=math.floor(self.z) + 0.5
+        )
 import math
 import random
 import sys
-
-import gevent
-import gevent.event
+import threading
+import time
 
 from client import Client
 import packet
 class MyClient(Client):
     def __init__(self, username):
         super(MyClient, self).__init__(username)
-        self.is_ready = gevent.event.Event()
+        self.is_ready = threading.Event()
 
     def connect(self, address):
         super(MyClient, self).connect(address)
                 direction = random.random() * math.pi
                 dx = math.sin(direction) * speed
                 dz = math.cos(direction) * speed
-            gevent.sleep(.1)
+            time.sleep(.1)
         c.put_packet(packet.Disconnect(reason='Goodbye!'))
-        gevent.sleep(1)
+        time.sleep(1)
         c.close()
     except KeyboardInterrupt:
         c.close()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.