Preliminary matchmaking

I don't know how well it works yet until more testing is done, but
matchmaking works now.
This commit is contained in:
polaris
2014-04-08 16:10:59 -04:00
parent d5086d0909
commit 63cdaf3666
3 changed files with 55 additions and 19 deletions

View File

@@ -20,6 +20,7 @@
from multiprocessing.managers import BaseManager
from multiprocessing import freeze_support
import other.utils as utils
server_list = {}
@@ -264,7 +265,7 @@ def update_server_list(gameid, session, value):
# Add new server
value['__session__'] = session
print "Added %s to the server list for %s" % (gameid, value)
utils.print_log("Added %s to the server list for %s" % (value, gameid))
server_list[gameid].append(value)
def delete_server(gameid, session):
@@ -283,9 +284,6 @@ def start_server():
address = ("127.0.0.1", 27500)
password = ""
#server_list["tetrisds"] = []
#server_list["tetrisds"].append({'__session__': 0, 'key': "helloworld", 'value': "Hello, world!", 'extra': "Test"})
GamespyServerDatabase.register("get_server_list", callable=lambda:server_list)
GamespyServerDatabase.register("find_servers", callable=find_servers)
GamespyServerDatabase.register("update_server_list", callable=update_server_list)

View File

@@ -198,6 +198,12 @@ while 1:
if "statechanged" in k:
if k['statechanged'] == "1": # Create server
if k['publicport'] != "0" and k['publicip'] != "0" and k['maxplayers'] != "0":
# dwc_mtype controls what kind of server query we're looking for.
# dwc_mtype = 0 is used when looking for a matchmaking game.
# dwc_mtype = 1 is unknown.
# dwc_mtype = 2 is used when hosting a friends only game (possibly other uses too).
# dwc_mtype = 3 is used when looking for a friends only game (possibly other uses too).
# Some memory could be saved by clearing out any unwanted fields from k before sending.
server_manager.update_server_list(k['gamename'] , session_id, k)
elif k['statechanged'] == "2": # Close server

View File

@@ -8,6 +8,8 @@ from twisted.internet import reactor
import socket
import ctypes
import time
from threading import Thread
import gamespy.gs_utility as gs_utils
import other.utils as utils
@@ -101,6 +103,12 @@ class Session(LineReceiver):
self.addr = addr
self.forward_to_client = False
self.forward_client = ()
self.is_searching = False
# Amount of time (in seconds) we can search for a match before getting kicked off.
# Set to -1 to allow keep searching forever until a server appears.
#self.timeout = 60 * 10
self.timeout = -1
def rawDataReceived(self, data):
# First 2 bytes are the packet size.
@@ -191,23 +199,16 @@ class Session(LineReceiver):
#print "%08x" % options
#print "%d %08x" % (max_servers, source_ip)
# Get dictionary from master server list server.
self.server_list = get_server_list(query_game, filter, fields, max_servers)._getvalue()
if self.is_searching == False:
self.is_searching = True
# Generate encrypted server list and send to client.
print self.server_list
for server in self.server_list:
# Generate binary server list data
data = generate_server_list_data(self.addr, fields, server)
# I still want the connection to close properly when the client disconnects, so put the server search
# part into its own thread.
# The game will create a new connection for every search query, so don't worry about setting
# self.is_searching to False.
t = Thread(target = self.find_server, args=(query_game, filter, fields, max_servers, game_name, challenge))
t.start()
# Encrypt data
enc = gs_utils.EncTypeX()
data = enc.encrypt(secret_key_list[game_name], challenge, data)
# Send to client
self.transport.write(bytes(data))
utils.print_log("Sent server list message to %s:%s..." % (self.addr.host, self.addr.port))
break
elif data[2] == '\x02': # Send message request
@@ -226,6 +227,37 @@ class Session(LineReceiver):
else:
utils.print_log("Received unknown command (%02x) from %s:%s... %s" % (ord(data[2]), self.addr.host, self.addr.port, data))
def find_server(self, query_game, filter, fields, max_servers, game_name, challenge):
# Get dictionary from master server list server.
# The game sends a search query only once so we must loop until something is found.
# Search for the specified amount of time, or if self.timeout is set to -1, until a match is found.
start = time.time()
while True:
self.server_list = get_server_list(query_game, filter, fields, max_servers)._getvalue()
if self.server_list != []:
break
time.sleep(5) # Sleep 1 second
if self.timeout != -1 and time.time() - start > self.timeout:
break
# Generate encrypted server list and send to client.
print self.server_list
for server in self.server_list:
# Generate binary server list data
data = generate_server_list_data(self.addr, fields, server)
# Encrypt data
enc = gs_utils.EncTypeX()
data = enc.encrypt(secret_key_list[game_name], challenge, data)
# Send to client
self.transport.write(bytes(data))
utils.print_log("Sent server list message to %s:%s..." % (self.addr.host, self.addr.port))
break
class SessionFactory(Factory):
def __init__(self):