diff --git a/AO2XPbase/ao2xp_themes/default/theme.py b/AO2XPbase/ao2xp_themes/default/theme.py index a0dadf5..9e53515 100644 --- a/AO2XPbase/ao2xp_themes/default/theme.py +++ b/AO2XPbase/ao2xp_themes/default/theme.py @@ -15,6 +15,8 @@ self.emotedropdown.setGeometry(164 - 28, 344 + 66 + 4, 72, 20) self.colordropdown.setGeometry(self.emotedropdown.x(), 376 + 64, 72, 20) self.posdropdown.setGeometry(self.emotedropdown.x() + self.emotedropdown.size().width() + 4, self.emotedropdown.y(), 72, 20) +self.demoslider.setGeometry(self.icchatinput.x(), self.icchatinput.y(), VIEWPORT_W, 23) + self.flipbutton.move(self.posdropdown.x() + self.posdropdown.width() + 4, self.colordropdown.y() - 5) self.sfxbutton.move(self.flipbutton.x(), self.flipbutton.y() + 14) self.nointerruptbtn.move(self.flipbutton.x() + 140, self.flipbutton.y()) diff --git a/gameview.py b/gameview.py index 516e302..fb78ac8 100644 --- a/gameview.py +++ b/gameview.py @@ -3,6 +3,7 @@ from os.path import exists, basename from ConfigParserEdit import ConfigParser from constants import * from collections import OrderedDict +from bisect import bisect_left from pybass_constants import * from PyQt4 import QtGui, QtCore @@ -1030,6 +1031,8 @@ class gui(QtGui.QWidget): self.areaitems = QtGui.QListWidget() self.areaitems.itemDoubleClicked.connect(self.onAreaClick) + self.demoitems = QtGui.QListWidget() + self.demoitems.itemDoubleClicked.connect(self.onDemoClick) self.icLog = ChatLogs(self.gametab_log, 0, self.ooclog.logfile) self.icLog.setReadOnly(True) @@ -1185,6 +1188,7 @@ class gui(QtGui.QWidget): self.musicareatabs.addTab(self.gametab_music, "&Music") self.musicareatabs.addTab(self.areaitems, "&Areas") self.musicareatabs.addTab(self.gametab_players, 'Pla&yers') + self.musicareatabs.addTab(self.demoitems, "Demos") self.icchatinput = QtGui.QLineEdit(self) self.icchatinput.returnPressed.connect(self.onICreturn) @@ -1344,6 +1348,11 @@ class gui(QtGui.QWidget): self.pinglabel = QtGui.QLabel(self) + self.demoslider = QtGui.QSlider(QtCore.Qt.Horizontal, self) + self.demoslider.valueChanged.connect(self.demoSeek) + self.demoslider.setVisible(False) + self.demoslider.setMinimum(0) + self.name.show() self.char.show() self.court.show() @@ -2122,6 +2131,12 @@ class gui(QtGui.QWidget): area = item.text().split('\n')[0] self.sendMC(area) + def onDemoClick(self, item): + self.tcpthread.stop() + self.demoplayer.start(item.text()) + self.demoslider.setVisible(True) + self.icchatinput.setVisible(False) + def sendMC(self, content): if "cccc_ic_support" in self.features and self.showname: self.tcp.send('MC#' + content + '#' + str(self.mychar) + '#' + self.showname + '#%') @@ -3501,6 +3516,9 @@ class gui(QtGui.QWidget): if self.onscreen_timer_times == [0, 0, 0, 0, 0]: self.onscreen_timer.stop() + def demoSeek(self, time): + self.demoplayer.seek(time) + def startGame(self, tcp, playerlist, charlist, musiclist, background, evidence, areas, features=[], oocjoin=[], hplist=[], webAO_bucket=""): self.willDisconnect = False self.mychar = -1 @@ -3587,6 +3605,7 @@ class gui(QtGui.QWidget): self.musicitems.clear() self.areaitems.clear() + self.demoitems.clear() self.evidencedropdown.clear() for evi in evidence: self.evidencedropdown.addItem(evi[0].strip()) @@ -3626,6 +3645,10 @@ class gui(QtGui.QWidget): self.blipslider.setValue(ini.read_ini_int("AO2XP.ini", "Audio", "Blip volume", 100)) self.onImportEvidence(True) + + for demo in os.listdir('chatlogs'): + if os.path.splitext(basename(demo))[-1].lower() == ".demo": + self.demoitems.addItem(demo) self.tcpthread = TCP_Thread(self) self.tcpthread.MS_Chat.connect(self.netmsg_ms) @@ -3641,20 +3664,17 @@ class gui(QtGui.QWidget): self.tcpthread.timerUpdate.connect(self.start_pause_timers) self.tcpthread.start() - # self.demoplayer = DemoPlayer(self) - # self.demoplayer.MS_Chat.connect(self.netmsg_ms) - # 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.showCharSelect.connect(self.charselect.showCharSelect) - # self.demoplayer.allEvidence.connect(self.allEvidence) - # self.demoplayer.updatePlayerList.connect(self.updatePlayerList) - # self.demoplayer.rainbowColor.connect(self.text.setStyleSheet) - # self.demoplayer.timerUpdate.connect(self.start_pause_timers) - # self.demoplayer.load_demo('test.demo') - # self.demoplayer.step() + self.demoplayer = DemoPlayer(self) + self.demoplayer.MS_Chat.connect(self.netmsg_ms) + 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.allEvidence.connect(self.allEvidence) + self.demoplayer.updatePlayerList.connect(self.updatePlayerList) + self.demoplayer.rainbowColor.connect(self.text.setStyleSheet) + self.demoplayer.timerUpdate.connect(self.start_pause_timers) self.icchatinput.setFocus() @@ -3674,6 +3694,7 @@ class TCP_Thread(QtCore.QThread): send_attempts = 0 max_attempts = 5 + stop_now = False def __init__(self, parent): super(TCP_Thread, self).__init__(parent) @@ -3686,8 +3707,11 @@ class TCP_Thread(QtCore.QThread): tempdata = "" color = QtGui.QColor() color.setHsv(rainbow, 255, 255) - #color.setHsv(0, 255, 255) while True: + if self.stop_now: + self.quit() + return + if self.parent.disconnectnow: self.parent.disconnectCommon() self.quit() @@ -3738,16 +3762,17 @@ class TCP_Thread(QtCore.QThread): self.send_attempts = 0 handle_packets(self, total) + + def stop(self): + self.stop_now = True class DemoPlayer(QtCore.QObject): - connectionError = QtCore.pyqtSignal(str, str, str) MS_Chat = QtCore.pyqtSignal(list) newChar = QtCore.pyqtSignal(str) newBackground = QtCore.pyqtSignal(str, bool) IC_Log = QtCore.pyqtSignal(str) OOC_Log = QtCore.pyqtSignal(str) charSlots = QtCore.pyqtSignal() - showCharSelect = QtCore.pyqtSignal() allEvidence = QtCore.pyqtSignal(list) rainbowColor = QtCore.pyqtSignal(str) updatePlayerList = QtCore.pyqtSignal(str, int, int, str) @@ -3759,33 +3784,91 @@ class DemoPlayer(QtCore.QObject): self.paused = False self.demo = [] self.demo_length = len(self.demo) - self.index = 0 + self.time = 0 self.wait_timer = QtCore.QTimer(self) self.wait_timer.setSingleShot(True) self.wait_timer.timeout.connect(self.timer_done) + self.mc = [] # Music changes + self.bn = [] # Background changes + self.last_music = "" + self.last_bg = "" + + def start(self, file): + self.time = 0 + self.demo = [] + self.mc = [] + self.bn = [] + self.last_music = "" + self.last_bg = "" + self.load_demo(file) + self.parent.demoslider.setMaximum(self.demo_length - 1) + self.step() + + def playpause(self): + self.paused = not self.paused + if not self.paused and self.time < self.demo_length: + self.step() + def step(self): - packet = self.demo[self.index] - self.index += 1 - print packet + packet = self.demo[self.time] + self.parent.demoslider.blockSignals(True) + self.parent.demoslider.setValue(self.time) + self.parent.demoslider.blockSignals(False) + self.time += 1 + if packet[0] == "wait": self.wait_timer.start(int(packet[1])) else: handle_packets(self, [packet]) - self.step() + if self.time < self.demo_length: + self.wait_timer.start(1) + + def seek(self, time): + self.parent.inbox_timer.stop() + self.parent.inboxqueue = [] + self.wait_timer.stop() + self.time = time + + mc_times = [t[0] for t in self.mc] + t = bisect_left(mc_times, self.time) - 1 + if t >= 0: + music = self.mc[t][1][1] + if music != self.last_music: + handle_packets(self, [self.mc[t][1]]) + self.last_music = music + + bn_times = [t[0] for t in self.bn] + t = bisect_left(bn_times, self.time) - 1 + if t >= 0: + bg = self.bn[t][1][1] + if bg != self.last_bg: + handle_packets(self, [self.bn[t][1]]) + self.last_bg = bg - def load_demo(self, file='test.demo'): + self.step() + + def load_demo(self, file): last_line = "" - self.demo = [] - with open(file) as f: + time = 0 + with open("chatlogs/" + file) as f: for line in f: last_line = last_line + line if last_line.strip()[-1] == "%": - self.demo.append(last_line.split("#")[:-1]) + packet = last_line.split("#")[:-1] + self.demo.append(packet) + if packet[0] == "MC": + self.mc.append((time, packet)) + elif packet[0] == "BN": + self.bn.append((time, packet)) + last_line = "" + time += 1 self.demo_length = len(self.demo) def timer_done(self): + if self.paused: + return self.step() def handle_packets(caller, total): @@ -3796,7 +3879,11 @@ def handle_packets(caller, total): print '[warning]', 'malformed/incomplete MS#chat (IC chat) network message was received' continue - network[CHATMSG] = decode_ao_str(network[CHATMSG].decode('utf-8')) + if isinstance(network[CHATMSG], unicode): + network[CHATMSG] = decode_ao_str(network[CHATMSG]) + else: + network[CHATMSG] = decode_ao_str(network[CHATMSG].decode('utf-8')) + caller.MS_Chat.emit(network) elif header == 'MC':