websocket support

This commit is contained in:
headshot2017 2022-03-27 21:01:18 -04:00
parent 9230b1b785
commit a2ad80303d
4 changed files with 144 additions and 78 deletions

96
AOsocket.py Normal file
View File

@ -0,0 +1,96 @@
import socket
import platform
import websocket
from game_version import *
class AOtcpSocket(object):
def __init__(self):
self.sock = socket.socket()
self.isWS = False
def connect(self, ip, port):
try:
self.sock.connect((ip, port))
except:
return False
self.sock.settimeout(0.1)
return True
def recv(self):
tempdata = ""
gotIt = False
while not gotIt:
try:
contents = self.sock.recv(16384)
except (socket.timeout, socket.error) as err:
error = err.args[0]
if error == "timed out" or error == 10035 or err.errno == 11:
return -2, []
else: # connection lost
return -1, []
if not contents.endswith("%"):
tempdata += contents
continue
else:
gotIt = True
if tempdata:
contents = tempdata + contents
tempdata = ""
totals = contents.split('%')
del totals[-1]
for i in range(len(totals)):
totals[i] = totals[i].split("#")
del totals[i][-1]
return 0, totals
def send(self, data):
return self.sock.send(data)
def close(self):
self.sock.close()
class AOwebSocket(object):
def __init__(self):
self.sock = websocket.WebSocket()
self.isWS = True
self.header = {
"User-Agent": "AO2XP %s, Python %s, %s %s %s %s %s" % (GAME_VERSION, platform.python_version(), platform.system(), platform.release(), platform.version(), platform.machine(), platform.processor())
}
def connect(self, ip, port):
try:
self.sock.connect("ws://%s:%s" % (ip, port), header=self.header)
except:
return False
self.sock.settimeout(0.1)
return True
def recv(self):
try:
contents = self.sock.recv()
except websocket.WebSocketTimeoutException:
return -2, []
except websocket.WebSocketConnectionClosedException:
return -1, []
totals = contents.split('%')
del totals[-1]
for i in range(len(totals)):
totals[i] = totals[i].split("#")
del totals[i][-1]
return 0, totals
def send(self, data):
return self.sock.send(str(data))
def close(self):
self.sock.close()

View File

@ -1,4 +1,4 @@
import socket, thread, time, os, buttons, urllib, charselect, ini, random
import thread, time, os, buttons, urllib, charselect, ini, random
from os.path import exists
from ConfigParser import ConfigParser
@ -6,6 +6,7 @@ from pybass_constants import *
from PyQt4 import QtGui, QtCore
from functools import partial
import AOsocket
import images
AOpath = "base/"
@ -2486,7 +2487,6 @@ class gui(QtGui.QWidget):
self.soundslider.setValue(ini.read_ini_int("AO2XP.ini", "Audio", "Sound volume", 100))
self.blipslider.setValue(ini.read_ini_int("AO2XP.ini", "Audio", "Blip volume", 100))
self.tcp.settimeout(0.1)
#thread.start_new_thread(self.tcp_thread, ())
self.tcpthread = TCP_Thread(self)
self.tcpthread.MS_Chat.connect(self.netmsg_ms)
@ -2747,38 +2747,19 @@ class TCP_Thread(QtCore.QThread):
if self.parent.msgqueue and not sendtick:
self.parent.tcp.send(self.parent.msgqueue[0])
sendtick = 4
try:
contents = self.parent.tcp.recv(8192)
except (socket.timeout, socket.error) as err:
error = err.args[0]
if error == "timed out" or error == 10035:
continue
else:
self.parent.emit(QtCore.SIGNAL('showMessage(QString, QString, QString)'), 'critical', 'Connection lost', str(err))
self.parent.willDisconnect = True
self.quit()
return
if not contents:
self.parent.emit(QtCore.SIGNAL('showMessage(QString, QString, QString)'), 'critical', 'Connection lost', 'the server closed the connection')
error, total = self.parent.tcp.recv()
if error == -2:
continue
elif error == -1:
self.parent.emit(QtCore.SIGNAL('showMessage(QString, QString, QString)'), 'critical', 'Connection lost', "%s connection to server lost." % ("WebSocket" if self.parent.tcp.isWS else "TCP"))
self.parent.willDisconnect = True
self.quit()
return
if not contents.endswith("%"):
tempdata += contents
continue
else:
if tempdata:
contents = tempdata + contents
tempdata = ""
total = contents.split('%')
for msg in total:
network = msg.split('#')
for network in total:
header = network[0]
del network[-1]
#del network[-1]
if header == 'MS':
if len(network) < 15:
print '[warning]', 'malformed/incomplete MS#chat (IC chat) network message was received'

View File

@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-
import socket, thread, time, random, traceback, requests, json
import thread, time, random, traceback, requests, json
from os.path import exists
from PyQt4 import QtGui, QtCore
import hardware
import AOsocket
from game_version import *
AOpath = "base/"
@ -199,10 +200,11 @@ class lobby(QtGui.QWidget):
desc = server["description"]
ip = server["ip"]
port = server["port"]
ws_port = server["ws_port"] if "ws_port" in server else 0
serveritem = QtGui.QListWidgetItem(name)
if self.tab == 0: self.serverlist.addItem(serveritem)
self.actual_serverlist.append((ip, port, name, desc))
self.actual_serverlist.append((ip, port, name, desc, ws_port))
def moveToGame(self, stuff):
tcp, charlist, musiclist, background, evidence, areas, features, joinooc, hplist, webAO_bucket = stuff
@ -315,8 +317,8 @@ class lobby(QtGui.QWidget):
if self.serverlist.item(i) == item:
if self.tab == 0:
self.serverinfo.setText(self.actual_serverlist[i][3])
self.aoserverinfo.setIP(text, *self.actual_serverlist[i][:2])
print '[debug]', 'ind: ' + str(i) + ', ip: ' + self.actual_serverlist[i][0] + ', port: ' + str(self.actual_serverlist[i][1])
self.aoserverinfo.setIP(text, self.actual_serverlist[i][0], self.actual_serverlist[i][1], self.actual_serverlist[i][-1])
print '[debug]', 'ind: ' + str(i) + ', ip: ' + self.actual_serverlist[i][0] + ', port: ' + str(self.actual_serverlist[i][1]) + ", websocket port: " + str(self.actual_serverlist[i][-1])
elif self.tab == 1:
self.aoserverinfo.setIP(text, *self.favoriteslist[i][:2])
print '[debug]', 'ind: ' + str(i) + ', ip: ' + self.favoriteslist[i][0] + ', port: ' + str(self.favoriteslist[i][1])
@ -417,13 +419,16 @@ class AOServerInfo(QtCore.QThread):
super(AOServerInfo, self).__init__()
self.ip = ""
self.port = 0
self.ws_port = 0
self.name = "jm"
self.webAO_bucket = ""
self.useWS = False
self.disconnect = False
def setIP(self, name, ip, port):
def setIP(self, name, ip, port, ws_port=0):
self.ip = ip
self.port = int(port)
self.ws_port = int(ws_port)
self.name = name
def stop(self):
@ -434,15 +439,24 @@ class AOServerInfo(QtCore.QThread):
def run(self):
self.disconnect = False
self.tcp = socket.socket()
self.tcp = AOsocket.AOwebSocket()
try:
self.tcp.connect((self.ip, self.port))
if self.ws_port == 0: raise Exception # make it jump to except: and use TCP
print "[debug]", "trying websocket..."
self.tcp.connect(self.ip, self.ws_port)
except:
self.setOnlinePlayers.emit("couldn't retrieve players")
return
self.tcp.settimeout(0.2)
self.tcp = AOsocket.AOtcpSocket()
try:
print "[debug]", "trying TCP..."
self.tcp.connect(self.ip, self.port)
except:
self.setOnlinePlayers.emit("couldn't retrieve players")
return
tempdata = ""
print "[debug]", "connected! websocket: %s" % self.tcp.isWS
self.tcp.sock.settimeout(0.1)
got_stuff = False
gotChars = False
hplist = []
joinooc = []
@ -477,27 +491,14 @@ class AOServerInfo(QtCore.QThread):
self.setWindowTitle.emit("AO2XP: "+self.name)
return
try:
contents = self.tcp.recv(16384)
except (socket.timeout, socket.error) as err:
error = err.args[0]
if error == "timed out" or error == 10035:
continue
else:
self.setOnlinePlayers.emit("Something wrong happened" if not got_stuff else "Connection lost")
return
if not contents.endswith("%"):
tempdata += contents
error, totals = self.tcp.recv()
if error == -2: # timeout
continue
else:
if tempdata:
contents = tempdata + contents
tempdata = ""
elif error == -1: # disconnected
self.setOnlinePlayers.emit("Something wrong happened" if not got_stuff else "Connection lost")
return
totals = contents.split('%')
for g in totals:
network = g.split('#')
for network in totals:
header = network[0]
if header == 'PN':
@ -543,7 +544,6 @@ class AOServerInfo(QtCore.QThread):
if self.disconnect:
continue
del network[0]
del network[len(network)-1]
gotChars = True
charlist = [ [char.split('&')[0], 0, "male"] for char in network ]
self.setConnectProgress.emit('Requesting music list (%d)...' % maxmusic)
@ -554,7 +554,6 @@ class AOServerInfo(QtCore.QThread):
if self.disconnect:
continue
del network[0]
del network[len(network)-1]
musiclist = [music for music in network]
@ -565,8 +564,7 @@ class AOServerInfo(QtCore.QThread):
elif header == 'CharsCheck':
if self.disconnect or not gotChars:
continue
network.pop(0)
network.pop(len(network)-1)
del network[0]
for i in range(len(network)):
charlist[i][1] = int(network[i])
@ -580,7 +578,6 @@ class AOServerInfo(QtCore.QThread):
if self.disconnect:
continue
del network[0]
del network[len(network)-1]
if len(network) > 0:
evidence = [evi.split("&") for evi in network]
else:
@ -597,15 +594,12 @@ class AOServerInfo(QtCore.QThread):
elif header == 'HP':
if self.disconnect:
continue
del network[0]
del network[len(network)-1]
type = int(network[0])
health = int(network[1])
type = int(network[1])
health = int(network[2])
hplist.append([type, health])
elif header == "ARUP": #AO2 2.6 new feature: area update
del network[0]
del network[len(network)-1]
type = int(network[0])
if type == 0: #player count
areas[type] = [network[i] for i in range(1, len(network))]
@ -623,8 +617,6 @@ class AOServerInfo(QtCore.QThread):
elif header == 'CT':
if self.disconnect:
continue
del network[0]
del network[len(network)-1]
name = network[0].decode("utf-8").replace('<dollar>', '$').replace('<percent>', '%').replace('<and>', '&').replace('<num>', '#').replace('<pound>', '#')
chatmsg = network[1].decode("utf-8").replace('<dollar>', '$').replace('<percent>', '%').replace('<and>', '&').replace('<num>', '#').replace('<pound>', '#')
name = network[1].decode("utf-8").replace('<dollar>', '$').replace('<percent>', '%').replace('<and>', '&').replace('<num>', '#').replace('<pound>', '#')
chatmsg = network[2].decode("utf-8").replace('<dollar>', '$').replace('<percent>', '%').replace('<and>', '&').replace('<num>', '#').replace('<pound>', '#')
joinooc.append("%s: %s" % (name, chatmsg))

View File

@ -6,11 +6,11 @@ import os
import platform
def pip_install(*args):
print "installing " + ", ".join(args)
command = [sys.executable, "-m", "pip", "install"]
command.extend(args)
subprocess.call(command)
print "installing requests"
pip_install('requests')
import requests
@ -72,7 +72,6 @@ zip_ref = zipfile.ZipFile(BASSOPUSZIP, 'r')
zip_ref.extract(BASSOPUSDLL)
zip_ref.close()
print "installing apng, six, appdirs, packaging"
pip_install("apng", "six", "appdirs", "packaging")
try:
@ -80,17 +79,15 @@ try:
if Image.__version__ != "5.3.0":
jm = raw_input("Pillow version 5.3.0 is recommended for compatibility with AO2XP; You have version %s\nReplace with version 5.3.0? (Y/N) > " % Image.__version__).lower()
if jm == "y":
print "installing Pillow 5.3.0"
pip_install("Pillow==5.3.0")
else:
print "Pillow 5.3.0 already exists, skipping"
except ImportError:
print "installing Pillow 5.3.0"
pip_install("Pillow==5.3.0")
print "installing pyinstaller"
pip_install('pyinstaller==3.6')
pip_install("websocket-client")
if platform.system() == "Windows":
print "downloading pyqt4"