Moving GUI out of the TCP thread

This commit is contained in:
cidoku 2026-02-08 18:17:11 -03:00
parent 8024b3e806
commit e323bf47dc
5 changed files with 229 additions and 284 deletions

View File

@ -1,4 +1,4 @@
# AO2XP 2.9.3
# AO2XP 2.9.5
This is an alternative Attorney Online 2 client, developed in **Python 2.7**,
specifically made for older computers running Windows XP that cannot run the

View File

@ -5,15 +5,18 @@ from bisect import bisect_left
class DemoPlayer(QtCore.QObject):
MS_Chat = QtCore.pyqtSignal(list)
newChar = QtCore.pyqtSignal(str)
newChar = QtCore.pyqtSignal(int)
newBackground = QtCore.pyqtSignal(str, bool)
IC_Log = QtCore.pyqtSignal(str)
OOC_Log = QtCore.pyqtSignal(str)
charSlots = QtCore.pyqtSignal()
charSlots = QtCore.pyqtSignal(list)
loadAllEvidence = QtCore.pyqtSignal(list)
rainbowColor = QtCore.pyqtSignal(str)
updatePlayerList = QtCore.pyqtSignal(str, int, int, str)
timerUpdate = QtCore.pyqtSignal(int, int, int)
authStatusChanged = QtCore.pyqtSignal(int)
updateAreaList = QtCore.pyqtSignal(list)
setCharList = QtCore.pyqtSignal(list)
def __init__(self, parent):
super(DemoPlayer, self).__init__(parent)

View File

@ -1,28 +1,22 @@
import thread, time, os, urllib, random, re, platform, subprocess
import charselect, ini, AOsocket, images, packets, demo, buttons
# This is the main file where everything happens. Honestly, it sucks and the
# thing is so complex and unsafe that I'm surprised it even works. I wish for
# a simpler client. ~ cidoku
import thread, time, os, urllib, random, platform, subprocess
from os.path import exists, basename
from ConfigParserEdit import ConfigParser
from constants import *
from collections import OrderedDict
from pybass_constants import *
from PyQt4 import QtGui, QtCore
from functools import partial
from ctypes import create_string_buffer
from urllib2 import Request, urlopen
from PyQt4 import QtGui, QtCore
from ConfigParserEdit import ConfigParser
from constants import *
from pybass_constants import BASS_ATTRIB_VOL, BASS_ACTIVE_PAUSED, BASS_STREAM_AUTOFREE, BASS_SAMPLE_LOOP
import charselect, ini, images, packets, demo, buttons, audio
DOWNLOAD_BLACKLIST = []
URL_REGEX = r"https?://(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_+.~#?&/=]*)"
bucket = ""
def delay(msec):
dieTime = QtCore.QTime.currentTime().addMSecs(msec)
while QtCore.QTime.currentTime() < dieTime:
QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 100)
def getCharIni(char, section, value, default=""):
tempini = ConfigParser()
return ini.read_ini(BASE_PATH + 'characters/' + char.lower() + '/char.ini', section, value, default)
@ -242,7 +236,6 @@ class ChatLogs(QtGui.QTextEdit):
class AOCharMovie(QtGui.QLabel):
done = QtCore.pyqtSignal()
usePillow = 0
pillowFrames = []
pillowFrame = 0
pillowSpeed = 0
@ -298,6 +291,21 @@ class AOCharMovie(QtGui.QLabel):
else:
self.setAlignment(QtCore.Qt.AlignCenter)
def findSprite(self, char, emote, prefix):
bases = [
"{char}/{prefix}{emote}",
"{char}/{emote}",
"{char}/{prefix}/{emote}"
]
exts = [".apng", ".png", ".gif", ".webp"]
for base in bases:
for ext in exts:
path = BASE_PATH + "characters/" + base.format(char=char, prefix=prefix, emote=emote) + ext
if exists(path):
return path, ext
return None
def play(self, pChar, pEmote, emotePrefix, scaling = SCALING_AUTO, singleFrameDuration = -1):
if not len(pEmote):
return
@ -319,106 +327,36 @@ class AOCharMovie(QtGui.QLabel):
pChar = pChar.lower()
pEmote = pEmote.lower()
apngPath = testPath(
BASE_PATH + "characters/" + pChar + "/" + emotePrefix + pEmote + ".apng",
BASE_PATH + "characters/" + pChar + "/" + emotePrefix + "/" + pEmote + ".apng",
BASE_PATH + "characters/" + pChar + "/" + pEmote + ".apng",
BASE_PATH + "characters/" + pChar + "/(a)" + pEmote + ".apng",
BASE_PATH + "characters/" + pChar + "/(b)" + pEmote + ".apng",
BASE_PATH + "characters/" + pChar + "/(a)/" + pEmote + ".apng",
BASE_PATH + "characters/" + pChar + "/(b)/" + pEmote + ".apng"
)
placeholderPath = AO2XPpath + "themes/default/oldplaceholder.gif"
imgPath = ""
imgPath, ext = self.findSprite(pChar, pEmote, emotePrefix)
if apngPath:
imgPath = apngPath
self.usePillow = 1
if not imgPath:
if self.prevGifPath:
imgPath = self.prevGifPath
else:
pngPath = testPath(
BASE_PATH + "characters/" + pChar + "/" + emotePrefix + pEmote + ".png",
BASE_PATH + "characters/" + pChar + "/" + emotePrefix + "/" + pEmote + ".png",
BASE_PATH + "characters/" + pChar + "/" + pEmote + ".png",
BASE_PATH + "characters/" + pChar + "/(a)" + pEmote + ".png",
BASE_PATH + "characters/" + pChar + "/(b)" + pEmote + ".png",
BASE_PATH + "characters/" + pChar + "/(a)/" + pEmote + ".png",
BASE_PATH + "characters/" + pChar + "/(b)/" + pEmote + ".png"
)
if pngPath:
imgPath = pngPath
self.usePillow = 0
else:
webpPath = testPath(
BASE_PATH + "characters/" + pChar + "/" + emotePrefix + pEmote + ".webp",
BASE_PATH + "characters/" + pChar + "/" + emotePrefix + "/" + pEmote + ".webp",
BASE_PATH + "characters/" + pChar + "/" + pEmote + ".webp",
BASE_PATH + "characters/" + pChar + "/(a)" + pEmote + ".webp",
BASE_PATH + "characters/" + pChar + "/(b)" + pEmote + ".webp",
BASE_PATH + "characters/" + pChar + "/(a)/" + pEmote + ".webp",
BASE_PATH + "characters/" + pChar + "/(b)/" + pEmote + ".webp"
)
if webpPath:
imgPath = webpPath
self.usePillow = 2
else:
gifPath = testPath(
BASE_PATH + "characters/" + pChar + "/" + emotePrefix + pEmote + ".gif",
BASE_PATH + "characters/" + pChar + "/" + emotePrefix + "/" + pEmote + ".gif",
BASE_PATH + "characters/" + pChar + "/" + pEmote + ".gif",
BASE_PATH + "characters/" + pChar + "/(a)" + pEmote + ".gif",
BASE_PATH + "characters/" + pChar + "/(b)" + pEmote + ".gif",
BASE_PATH + "characters/" + pChar + "/(a)/" + pEmote + ".gif",
BASE_PATH + "characters/" + pChar + "/(b)/" + pEmote + ".gif"
)
if gifPath:
imgPath = gifPath
self.usePillow = 0
else:
if ini.read_ini_bool("AO2XP.ini", "General", "download characters"):
pass
# url = "base/characters/" + pChar.lower() + "/" + emotePrefix + pEmote.lower() + ".gif"
# url = url.replace(" ", "%20")
# thread.start_new_thread(downloadThread, (url, gifPath))
if exists(placeholderPath):
imgPath = placeholderPath
print "[debug] Sprite not found:", pChar, pEmote, emotePrefix
else:
imgPath = ""
self.usePillow = 0
if imgPath == "":
imgPath = self.prevGifPath
# Second check just in case
if imgPath == "":
if exists(placeholderPath):
imgPath = placeholderPath
print "[debug] Sprite not found: ", pChar, pEmote, emotePrefix
else:
imgPath = "placeholder.png"
# if ini.read_ini_bool("AO2XP.ini", "General", "download characters"):
# url = "base/characters/" + pChar.lower() + "/" + emotePrefix + pEmote.lower() + ".gif"
# url = url.replace(" ", "%20")
# thread.start_new_thread(downloadThread, (url, gifPath))
else:
self.prevGifPath = imgPath
#print "[debug]", pChar, emotePrefix, pEmote, "(!) path is null!" if imgPath == "" else imgPath
if not self.usePillow:
self.mMovie.setFileName(imgPath)
self.mMovie.start()
elif self.usePillow == 1: # apng
self.pillowFrames = images.load_apng(apngPath)
if ext == ".apng":
self.pillowFrames = images.load_apng(imgPath)
if len(self.pillowFrames) > 1:
self.pillowTimer.start(int(self.pillowFrames[0][1] * self.pillowSpeed))
else:
self.pillowTimer.start(int(singleFrameDuration * self.pillowSpeed))
self.setPillowFrame()
elif self.usePillow == 2: # webp
elif ext == ".webp":
try:
self.pillowFrames = images.load_webp(webpPath)
self.pillowFrames = images.load_webp(imgPath)
if len(self.pillowFrames) > 1:
self.pillowTimer.start(int(self.pillowFrames[0][1] * self.pillowSpeed))
else:
@ -433,6 +371,9 @@ class AOCharMovie(QtGui.QLabel):
imgPath = "placeholder.png"
self.mMovie.setFileName(imgPath)
self.mMovie.start()
else:
self.mMovie.setFileName(imgPath)
self.mMovie.start()
if self.showOnPlay:
self.show()
@ -669,12 +610,17 @@ class AOMovie(QtGui.QLabel):
self.pillowLabel.hide()
self.hide()
def finish(self):
self.stop()
self.done.emit()
@QtCore.pyqtSlot(int)
def frameChange(self, nFrame):
if nFrame == self.mMovie.frameCount() - 1 and self.playOnce:
delay(self.mMovie.nextFrameDelay())
self.stop()
self.done.emit()
QtCore.QTimer.singleShot(
self.mMovie.nextFrameDelay(),
self.finish
)
@QtCore.pyqtSlot()
def pillowFrameChange(self):
@ -682,7 +628,7 @@ class AOMovie(QtGui.QLabel):
if len(self.pillowFrames) - 1 == self.pillowFrame:
if self.playOnce or (self.usePillow == 2 and self.pillowLoops+1 == self.webpLoops):
delay(int(self.pillowFrames[self.pillowFrame][1] * self.pillowSpeed))
self.msleep(int(self.pillowFrames[self.pillowFrame][1] * self.pillowSpeed))
self.stop()
self.done.emit()
elif len(self.pillowFrames) > 1: # loop
@ -746,7 +692,7 @@ class WTCEView(QtGui.QLabel):
super(WTCEView, self).move(self.parent.viewport.x(), self.parent.viewport.y())
super(WTCEView, self).resize(self.parent.viewport.size())
def frameChange(self, frame):
def frameChange(self):
if self.movie.state() != QtGui.QMovie.Running:
return
img = self.movie.currentImage()
@ -763,17 +709,30 @@ class WTCEView(QtGui.QLabel):
def showWTCE(self, wtce, variant=0):
self.finished()
wtcefile = BASE_PATH + "sounds/general/sfx-testimony2"
if self.parent.wtceSfx:
audio.freeHandle(self.parent.wtceSfx)
if wtce == 'testimony1':
self.movie.setFileName(AO2XPpath + 'themes/default/witnesstestimony.gif')
elif wtce == 'testimony2':
self.movie.setFileName(AO2XPpath + 'themes/default/crossexamination.gif')
elif wtce == "judgeruling":
if variant == 0:
wtcefile = BASE_PATH + "sounds/general/sfx-notguilty"
self.movie.setFileName(AO2XPpath + 'themes/default/notguilty.gif')
elif variant == 1:
wtcefile = BASE_PATH + "sounds/general/sfx-guilty"
self.movie.setFileName(AO2XPpath + 'themes/default/guilty.gif')
else:
return
self.parent.wtceSfx = audio.loadHandle(False, wtcefile+".opus" if exists(wtcefile+".opus") else wtcefile+".wav", 0, 0, 0)
audio.setHandleAttr(self.parent.wtceSfx, BASS_ATTRIB_VOL, self.parent.sliSoundVolume.value() / 100.0)
if self.parent.wtceSfx:
audio.playHandle(self.parent.wtceSfx, True)
self.show()
self.movie.start()
@ -888,7 +847,7 @@ class EditEvidenceDialog(QtGui.QDialog):
def onBrowseClicked(self):
path = str(QtGui.QFileDialog.getOpenFileName(self, "Select an image", BASE_PATH + 'evidence', "Images (*.png)"))
if path:
if not "/evidence/" in path.lower():
if "/evidence/" not in path.lower():
QtGui.QMessageBox.warning(self, 'Wrong directory', 'Please select a file from the "evidence" directory.')
self.onBrowseClicked()
return
@ -921,16 +880,19 @@ class EditEvidenceDialog(QtGui.QDialog):
class TCPThread(QtCore.QThread):
connectionError = QtCore.pyqtSignal(str, str, str)
MS_Chat = QtCore.pyqtSignal(list)
newChar = QtCore.pyqtSignal(str)
newChar = QtCore.pyqtSignal(int)
newBackground = QtCore.pyqtSignal(str, bool)
IC_Log = QtCore.pyqtSignal(str)
OOC_Log = QtCore.pyqtSignal(str)
charSlots = QtCore.pyqtSignal()
charSlots = QtCore.pyqtSignal(list)
showCharSelect = QtCore.pyqtSignal()
loadAllEvidence = QtCore.pyqtSignal(list)
rainbowColor = QtCore.pyqtSignal(str)
updatePlayerList = QtCore.pyqtSignal(str, int, int, str)
timerUpdate = QtCore.pyqtSignal(int, int, int)
authStatusChanged = QtCore.pyqtSignal(int)
updateAreaList = QtCore.pyqtSignal(list)
setCharList = QtCore.pyqtSignal(list)
send_attempts = 0
max_attempts = 5
@ -944,7 +906,6 @@ class TCPThread(QtCore.QThread):
pingtimer = 150
rainbow = 0
sendtick = 0
tempdata = ""
color = QtGui.QColor()
color.setHsv(rainbow, 255, 255)
while True:
@ -961,7 +922,7 @@ class TCPThread(QtCore.QThread):
pingtimer -= 1
if pingtimer == 0:
pingbefore = time.time()
# pingbefore = time.time()
self.parent.tcp.send('CH#%')
pingtimer = 150
@ -1027,8 +988,7 @@ class Chatbox(QtGui.QLabel):
class GUI(QtGui.QWidget):
mainWindow = None
# In theory 3 sounds may play at the same time: character, evidence sweep,
# effect
# In theory 3 sounds may play at the same time: character, evidence sweep, effect
soundChannels = 3
soundChannel = 0
sound = []
@ -2124,7 +2084,7 @@ class GUI(QtGui.QWidget):
def _themeCommon(self):
# IC input and demo slider
viewportRight = max(self.viewport.x() + self.viewport.width(), 512)
# viewportRight = max(self.viewport.x() + self.viewport.width(), 512)
# IC options
gameTabsHeight = self.gameTabs.height() - self.gameTabs.findChild(QtGui.QTabBar).height()
@ -2572,8 +2532,11 @@ class GUI(QtGui.QWidget):
self.tcp.send("RT#judgeruling#" +str(variant)+ "#%")
self.ICChatFocus()
def onPVPacket(self, charName=""):
def onPVPacket(self, char=0):
QtGui.QApplication.restoreOverrideCursor()
self.myChar = char
self.charSelect.hide()
charName = self.charList[char][0]
self.setDisabled(False)
self.gotPV = True
if not self.swapping and charName:
@ -3045,6 +3008,7 @@ class GUI(QtGui.QWidget):
self.speaker.wait()
def disconnectCommon(self):
QtGui.QApplication.restoreOverrideCursor()
self.gotPV = False
self.charName = ""
self.onSwitchInventory(True)
@ -3089,40 +3053,27 @@ class GUI(QtGui.QWidget):
def onOOCReturn(self):
text = encodeAOString(self.OOCInput.text()).replace('\\n', '\n')
if text.startsWith('//'):
code = str(self.OOCInput.text()).replace('//', '', 1).replace('\\NEWLINE', '\n')
try:
exec code
except Exception as e:
msg = 'code error\n'
for arg in e.args:
msg += str(arg) + '\n'
msg = msg.rstrip()
self.OOCLog.append(msg)
return
return
elif text.startsWith("/pos "): # why.......
if text.startsWith("/pos "): # why.......
ind = self.boxPositions.findText(str(text.split(" ")[1]))
if ind >= 0: self.boxPositions.setCurrentIndex(ind)
self.OOCInput.clear()
return
if self.cbMockText.isChecked():
text = mockString(text)
if self.cbAutoCaps.isChecked():
l = QtCore.QStringList(list(text))
l[0] = l[0].toUpper()
# if self.cbMockText.isChecked():
# text = mockString(text)
# if self.cbAutoCaps.isChecked():
# l = QtCore.QStringList(list(text))
# l[0] = l[0].toUpper()
last = [".", "?", "!", ")", "]"]
if not l[-1] in last:
l.append(".")
text = l.join("").replace(" i ", " I ").replace("i'm", "I'm").replace("it's", "It's")
if self.cbSpacing.isChecked():
l = QtCore.QStringList(list(text))
for i in range(1, len(l)+len(l)-1, 2):
l.insert(i, " ")
text = l.join("")
# last = [".", "?", "!", ")", "]"]
# if not l[-1] in last:
# l.append(".")
# text = l.join("").replace(" i ", " I ").replace("i'm", "I'm").replace("it's", "It's")
# if self.cbSpacing.isChecked():
# l = QtCore.QStringList(list(text))
# for i in range(1, len(l)+len(l)-1, 2):
# l.insert(i, " ")
# text = l.join("")
self.sendOOCchat(self.OOCNameInput.text().toUtf8(), text)
self.OOCInput.clear()
@ -4608,38 +4559,10 @@ class GUI(QtGui.QWidget):
if self.onscreenTimerTimes == [0, 0, 0, 0, 0]:
self.onscreenTimer.stop()
def onDemoClicked(self, item):
fname = demo.getDemoFilename(self.demoItems, item)
if not fname:
return
self.playerItems.clear()
self.stopMusic()
self.ICLog.clear()
self.OOCLog.clear()
if not self.demoPlaying:
self.enableWidgets(True)
self.tcpThread.stop()
self.demoPlaying = True
self.demoPlayer = demo.DemoPlayer(self)
self.demoPlayer.MS_Chat.connect(self.netmsgMS)
self.demoPlayer.newChar.connect(self.onPVPacket)
self.demoPlayer.newBackground.connect(self.setBackground)
self.demoPlayer.OOC_Log.connect(self.OOCLog.append)
self.demoPlayer.IC_Log.connect(self.ICLog.append)
self.demoPlayer.charSlots.connect(partial(self.charSelect.setCharList, self.charList))
self.demoPlayer.loadAllEvidence.connect(self.loadAllEvidence)
self.demoPlayer.updatePlayerList.connect(self.updatePlayerList)
self.demoPlayer.rainbowColor.connect(self.text.setStyleSheet)
self.demoPlayer.timerUpdate.connect(self.startPauseOnscreenTimers)
self.demoPlayer.start(fname)
def demoSeek(self, time):
self.demoPlayer.seek(time)
def setCharSlots(self, data):
for i, value in enumerate(data):
self.charList[i][1] = int(value)
self.charSelect.setCharList(self.charList)
def startGame(self, tcp, playerList, charList, musicList, background, evidence, areas, features=[], joinOOC=[], hpList=[], webAO_bucket=""):
self.willDisconnect = False
@ -4786,12 +4709,14 @@ class GUI(QtGui.QWidget):
self.tcpThread.newBackground.connect(self.setBackground)
self.tcpThread.OOC_Log.connect(self.OOCLog.append)
self.tcpThread.IC_Log.connect(self.ICLog.append)
self.tcpThread.charSlots.connect(partial(self.charSelect.setCharList, self.charList))
self.tcpThread.charSlots.connect(self.setCharSlots)
self.tcpThread.showCharSelect.connect(self.charSelect.showCharSelect)
self.tcpThread.loadAllEvidence.connect(self.loadAllEvidence)
self.tcpThread.updatePlayerList.connect(self.updatePlayerList)
self.tcpThread.authStatusChanged.connect(self.authStatusChanged)
self.tcpThread.rainbowColor.connect(self.text.setStyleSheet)
self.tcpThread.timerUpdate.connect(self.startPauseOnscreenTimers)
self.tcpThread.updateAreaList.connect(self.updateAreaList)
self.tcpThread.start()
self.demoPlaying = False
@ -4799,6 +4724,20 @@ class GUI(QtGui.QWidget):
self.startDemoRecorder(background)
self.ICChatInput.setFocus()
def newDemoPlayer(self):
self.demoPlayer = demo.DemoPlayer(self)
self.demoPlayer.MS_Chat.connect(self.netmsgMS)
self.demoPlayer.newChar.connect(self.onPVPacket)
self.demoPlayer.newBackground.connect(self.setBackground)
self.demoPlayer.OOC_Log.connect(self.OOCLog.append)
self.demoPlayer.IC_Log.connect(self.ICLog.append)
self.demoPlayer.charSlots.connect(self.setCharSlots)
self.demoPlayer.loadAllEvidence.connect(self.loadAllEvidence)
self.demoPlayer.updatePlayerList.connect(self.updatePlayerList)
self.demoPlayer.rainbowColor.connect(self.text.setStyleSheet)
self.demoPlayer.timerUpdate.connect(self.startPauseOnscreenTimers)
self.demoPlayer.setCharList.connect(self.onSCPacket)
def startDemo(self, fname):
self.playerList = []
self.charList = []
@ -4820,17 +4759,7 @@ class GUI(QtGui.QWidget):
self.onImportEvidence(True)
self.demoPlayer = demo.DemoPlayer(self)
self.demoPlayer.MS_Chat.connect(self.netmsgMS)
self.demoPlayer.newChar.connect(self.onPVPacket)
self.demoPlayer.newBackground.connect(self.setBackground)
self.demoPlayer.OOC_Log.connect(self.OOCLog.append)
self.demoPlayer.IC_Log.connect(self.ICLog.append)
self.demoPlayer.charSlots.connect(partial(self.charSelect.setCharList, self.charList))
self.demoPlayer.loadAllEvidence.connect(self.loadAllEvidence)
self.demoPlayer.updatePlayerList.connect(self.updatePlayerList)
self.demoPlayer.rainbowColor.connect(self.text.setStyleSheet)
self.demoPlayer.timerUpdate.connect(self.startPauseOnscreenTimers)
self.newDemoPlayer()
self.playerItems.clear()
self.stopMusic()
@ -4850,6 +4779,28 @@ class GUI(QtGui.QWidget):
if bg:
self.demoRecorder.record([["BN", bg, ""]], encode=True)
def onDemoClicked(self, item):
fname = demo.getDemoFilename(self.demoItems, item)
if not fname:
return
self.playerItems.clear()
self.stopMusic()
self.ICLog.clear()
self.OOCLog.clear()
if not self.demoPlaying:
self.enableWidgets(True)
self.tcpThread.stop()
self.demoPlaying = True
self.newDemoPlayer()
self.demoPlayer.start(fname)
def demoSeek(self, time):
self.demoPlayer.seek(time)
def enableWidgets(self, demo = False):
for widget in [
self.OOCInput, self.btnCallMod,
@ -4859,10 +4810,11 @@ class GUI(QtGui.QWidget):
self.tabMusic, self.boxEmotes, self.boxPositions,
self.cbFlip, self.cbPreanim, self.cbNoInterrupt,
self.boxEffects, self.cbSlide, self.cbBench,
self.cbAdditive, self.areaItems,
self.boxColors, self.btnDefenseBar.btnMinus, self.btnProsecutionBar.btnMinus,
self.btnDefenseBar.btnPlus, self.btnProsecutionBar.btnPlus, self.btnWitnessTestimony,
self.btnCrossExamination, self.btnNotGuilty, self.btnGuilty,
self.cbAdditive, self.areaItems, self.boxSounds, self.boxColors,
self.btnDefenseBar.btnMinus, self.btnProsecutionBar.btnMinus,
self.btnDefenseBar.btnPlus, self.btnProsecutionBar.btnPlus,
self.btnWitnessTestimony, self.btnCrossExamination,
self.btnNotGuilty, self.btnGuilty,
self.btnRealization, self.btnShake,
]:
widget.setEnabled(not demo)
@ -4875,7 +4827,35 @@ class GUI(QtGui.QWidget):
else:
self.btnChangeChar.setText('Switch &character')
def updateAreaList(self):
def updateAreaList(self, data=None):
if data:
kind = int(data[0])
self.areas[kind] = [data[i] for i in range(1, len(data))]
# This is much harder than doing it during the handshake because of
# the way the music list is implemented
if self.noARUP:
self.noARUP = False
self.areasLen = len(self.areas[kind])
print '[client]', 'The server has %d areas' % self.areasLen
if self.areasLen:
for i in range(self.areasLen):
area_key, area_val = self.musicList.items()[0]
self.areas[4].append(area_val)
areaitem = QtGui.QListWidgetItem()
self.areaItems.addItem(areaitem)
for j in range(4):
if j != kind:
self.areas[j].append("")
# Remove the area from the music list
self.musicList.popitem(False)
self.loadAllMusic()
try:
for i in range(self.areasLen):
areaPlayers = self.areas[0][i]
@ -4895,3 +4875,20 @@ class GUI(QtGui.QWidget):
except Exception as e:
print "[debug] Couldn't update areas. Details:"
print "[debug]", e
def authStatusChanged(self, status):
statusStrings = ["You have logged out", "Wrong password", "Logged in"]
if status == 1:
self.login = True
self.btnPlayerKick.setDisabled(False)
self.btnPlayerBan.setDisabled(False)
self.OOCLogin.setText("Lo&g out")
elif status == -1:
self.login = False
self.btnPlayerKick.setDisabled(True)
self.btnPlayerBan.setDisabled(True)
self.OOCLogin.setText("Lo&gin")
self.OOCLog.append("<b>%s</b>" % (statusStrings[status+1]))
def onSCPacket(self, data):
self.charList = data

View File

@ -345,10 +345,8 @@ class MasterServer(QtCore.QThread):
def run(self):
try:
tempdata = ""
self.msHttp = requests.get("http://servers.aceattorneyonline.com/servers")
self.msMotd = requests.get("http://servers.aceattorneyonline.com/motd")
if self.msHttp.ok: self.gotServers.emit(json.loads(self.msHttp.content))
if self.msMotd.ok: self.gotOOCMsg.emit(self.msMotd.content)
except Exception as e:

View File

@ -50,15 +50,14 @@ def handlePackets(caller, total, record=True):
caller.OOC_Log.emit("<b>%s:</b> %s" % (name, chatmsg.replace("<", "&lt;").replace("&lt;br />","<br />") if len(network) > 3 and network[3] == "0" else chatmsg))
elif header == 'PV':
caller.parent.myChar = int(network[3])
caller.parent.charSelect.hide()
caller.newChar.emit(caller.parent.charList[caller.parent.myChar][0])
caller.newChar.emit(int(network[3]))
elif header == 'LE':
del network[0]
caller.loadAllEvidence.emit([evi.split('&') for evi in network])
elif header == 'ZZ':
# TODO: Remove from tcp thread
if caller.parent.modcall:
audio.freeHandle(caller.parent.modcall)
caller.parent.modcall = audio.loadHandle(0, "mod_call.wav", 0, 0, 0)
@ -69,31 +68,14 @@ def handlePackets(caller, total, record=True):
caller.OOC_Log.emit('<b>[MOD CALL] ' + network[1].replace("\n", "<br />") + '</b>')
else:
caller.OOC_Log.emit('<b>[MOD CALL] But there was no extra information. (old server?)</b>')
elif header == 'CharsCheck':
del network[0]
for i in range(len(network)):
caller.parent.charList[i][1] = int(network[i])
caller.charSlots.emit()
caller.charSlots.emit(network)
elif header == 'RT':
testimony = network[1]
wtcefile = BASE_PATH + "sounds/general/sfx-testimony2"
if caller.parent.wtceSfx:
audio.freeHandle(caller.parent.wtceSfx)
if testimony == 'judgeruling':
variant = int(network[2])
if variant == 0:
wtcefile = BASE_PATH + "sounds/general/sfx-notguilty"
elif variant == 1:
wtcefile = BASE_PATH + "sounds/general/sfx-guilty"
else:
variant = 0
caller.parent.wtceSfx = audio.loadHandle(False, wtcefile+".opus" if exists(wtcefile+".opus") else wtcefile+".wav", 0, 0, 0)
audio.setHandleAttr(caller.parent.wtceSfx, BASS_ATTRIB_VOL, caller.parent.sliSoundVolume.value() / 100.0)
if caller.parent.wtceSfx:
audio.playHandle(caller.parent.wtceSfx, True)
variant = int(network[2]) if testimony == 'judgeruling' else 0
caller.parent.wtceSignal.emit(testimony, variant)
elif header == 'HP':
@ -102,31 +84,22 @@ def handlePackets(caller, total, record=True):
caller.parent.healthbars.emit(kind, health)
elif header == 'KK':
# TODO: Show message from GUI thread
reason = network[1]
caller.parent.emit(QtCore.SIGNAL('showMessage(QString, QString, QString)'), 'critical', 'Connection lost', 'You were kicked from the server. (%s)' % reason)
elif header == 'KB':
# TODO: Show message from GUI thread
reason = network[1]
caller.parent.emit(QtCore.SIGNAL('showMessage(QString, QString, QString)'), 'critical', 'Connection lost', 'You have been banned from the server. (%s)' % reason)
elif header == 'BB': # message popup (AO 2.9)
# TODO: Show message from GUI thread
message = network[1]
caller.parent.emit(QtCore.SIGNAL('showMessage(QString, QString, QString)'), 'information', 'Message from server', message)
elif header == 'AUTH': # login status (AO 2.9)
status = int(network[1])
statusStrings = ["You have logged out", "Wrong password", "Logged in"]
if status == 1:
caller.parent.login = True
caller.parent.btnPlayerKick.setDisabled(False)
caller.parent.btnPlayerBan.setDisabled(False)
caller.parent.OOCLogin.setText("Lo&g out")
elif status == -1:
caller.parent.login = False
caller.parent.btnPlayerKick.setDisabled(True)
caller.parent.btnPlayerBan.setDisabled(True)
caller.parent.OOCLogin.setText("Lo&gin")
caller.OOC_Log.emit("<b>%s</b>" % (statusStrings[status+1]))
caller.authStatusChanged.emit(int(network[1]))
# elif header == "CHECK": #ping
# pingafter = time.time()
@ -145,33 +118,7 @@ def handlePackets(caller, total, record=True):
elif header == 'ARUP':
del network[0]
kind = int(network[0])
caller.parent.areas[kind] = [network[i] for i in range(1, len(network))]
# This is much harder than doing it during the handshake because of the way the music list is implemented
if caller.parent.noARUP:
caller.parent.noARUP = False
caller.parent.areasLen = len(caller.parent.areas[kind])
print '[client]', 'The server has %d areas' % caller.parent.areasLen
if caller.parent.areasLen:
for i in range(caller.parent.areasLen):
area_key, area_val = caller.parent.musicList.items()[0]
caller.parent.areas[4].append(area_val)
areaitem = QtGui.QListWidgetItem()
caller.parent.areaItems.addItem(areaitem)
for j in range(4):
if j != kind:
caller.parent.areas[j].append("")
# Remove the area from the music list
caller.parent.musicList.popitem(False)
caller.parent.loadAllMusic()
caller.parent.updateAreaList()
caller.updateAreaList.emit(network)
elif header == 'TI':
del network[0]
@ -186,4 +133,4 @@ def handlePackets(caller, total, record=True):
# For demos
elif header == 'SC':
del network[0]
caller.parent.charList = [ [char.split('&')[0].decode('utf-8'), 0, "male", True ] for char in network ]
caller.setCharList.emit([ [char.split('&')[0].decode('utf-8'), 0, "male", True ] for char in network ])