|
@@ -8,11 +8,11 @@ from twisted.internet import protocol
|
|
|
from twisted.internet import reactor
|
|
|
from twisted.python import log
|
|
|
from twisted.python.logfile import DailyLogFile
|
|
|
-
|
|
|
-# from twisted.enterprise import adbapi
|
|
|
import pendulum
|
|
|
from subprocess import check_output
|
|
|
|
|
|
+from colorama import Fore, Back, Style
|
|
|
+
|
|
|
# This isn't the best configuration, but it's simple
|
|
|
# and works. Mostly.
|
|
|
|
|
@@ -38,8 +38,15 @@ version = check_output(
|
|
|
universal_newlines=True,
|
|
|
).strip()
|
|
|
|
|
|
+
|
|
|
+def merge(color_string):
|
|
|
+ """ Given a string of colorama ANSI, merge them if you can. """
|
|
|
+ return color_string.replace("m\x1b[", ";")
|
|
|
+
|
|
|
+
|
|
|
# Cleans all ANSI
|
|
|
cleaner = re.compile(r"\x1b\[[0-9;]*[A-Zmh]")
|
|
|
+
|
|
|
# Looks for ANSI (that should be considered to be a newline)
|
|
|
# This needs to see what is send when something enters / leaves
|
|
|
# the player's current sector. (That doesn't work/isn't
|
|
@@ -64,29 +71,55 @@ class Observer(object):
|
|
|
def __init__(self):
|
|
|
self.dispatch = {}
|
|
|
|
|
|
- def emit(signal, message):
|
|
|
- if signal in dispatch:
|
|
|
+ def emit(self, signal, message):
|
|
|
+ """ emit a signal, return True if sent somewhere. """
|
|
|
+ if signal in self.dispatch:
|
|
|
# something to do
|
|
|
- for listener in dispatch[signal]:
|
|
|
+ ret = False
|
|
|
+ for listener in self.dispatch[signal]:
|
|
|
+ ret = True
|
|
|
reactor.callLater(0, listener, message)
|
|
|
- return True
|
|
|
+ return ret
|
|
|
return False
|
|
|
|
|
|
- def connect(signal, func):
|
|
|
- if not signal in dispatch:
|
|
|
- dispatch[signal] = []
|
|
|
+ def connect(self, signal, func):
|
|
|
+ """ Connect a signal to a given function. """
|
|
|
+ if not signal in self.dispatch:
|
|
|
+ self.dispatch[signal] = []
|
|
|
|
|
|
- dispatch[signal].append(func)
|
|
|
+ self.dispatch[signal].append(func)
|
|
|
|
|
|
- def disconnect(signal, func):
|
|
|
- if signal in dispatch:
|
|
|
- dispatch[signal].remove(func)
|
|
|
+ def disconnect(self, signal, func):
|
|
|
+ """ Disconnect a signal with a certain function. """
|
|
|
+ if signal in self.dispatch:
|
|
|
+ self.dispatch[signal].remove(func)
|
|
|
+ if len(self.dispatch[signal]) == 0:
|
|
|
+ self.dispatch.pop(signal)
|
|
|
+
|
|
|
+ def get_funcs(self, signal):
|
|
|
+ """ Gives a copy of the dispatch for a given signal. """
|
|
|
+ if signal in self.dispatch:
|
|
|
+ return list(self.dispatch[signal])
|
|
|
+ else:
|
|
|
+ return []
|
|
|
+
|
|
|
+ def set_funcs(self, signal, funcs):
|
|
|
+ """ Replaces the dispatch for a given signal. """
|
|
|
+ if signal in self.dispatch:
|
|
|
+ if len(funcs) == 0:
|
|
|
+ self.dispatch.pop(signal)
|
|
|
+ else:
|
|
|
+ self.dispatch = list(funcs)
|
|
|
+ else:
|
|
|
+ if len(funcs) != 0:
|
|
|
+ self.dispatch = list(funcs)
|
|
|
|
|
|
|
|
|
class Game(protocol.Protocol):
|
|
|
def __init__(self):
|
|
|
self.buffer = ""
|
|
|
- self.game = ""
|
|
|
+ self.game = None
|
|
|
+ self.to_player = True
|
|
|
|
|
|
def connectionMade(self):
|
|
|
log.msg("Connected to Game Server")
|
|
@@ -94,6 +127,19 @@ class Game(protocol.Protocol):
|
|
|
self.queue_game = self.factory.queue_game
|
|
|
self.observer = self.factory.observer
|
|
|
self.setPlayerReceived()
|
|
|
+ self.observer.connect("user", self.show_user)
|
|
|
+ self.observer.connect("user-game", self.show_game)
|
|
|
+
|
|
|
+ def show_user(self, user):
|
|
|
+ """ This doesn't always show up. :P
|
|
|
+
|
|
|
+ Because we're still connecting to the game server when
|
|
|
+ the player object has already sent the 'user' signal.
|
|
|
+ """
|
|
|
+ log.msg("## User:", user)
|
|
|
+
|
|
|
+ def show_game(self, game):
|
|
|
+ log.msg("## User-Game:", game)
|
|
|
|
|
|
def setPlayerReceived(self):
|
|
|
""" Get deferred from client queue, callback clientDataReceived. """
|
|
@@ -113,26 +159,31 @@ class Game(protocol.Protocol):
|
|
|
|
|
|
def lineReceived(self, line):
|
|
|
""" line received from the game. """
|
|
|
- log.msg(">> [{0}]".format(line))
|
|
|
- if "TWGS v2.20b" in line and "www.eisonline.com" in line:
|
|
|
- # Must not be unicode
|
|
|
+ if LOG_LINES:
|
|
|
+ log.msg(">> [{0}]".format(line))
|
|
|
|
|
|
- # Is there a way to NOT have this logged?
|
|
|
+ if "TWGS v2.20b" in line and "www.eisonline.com" in line:
|
|
|
self.queue_game.put(
|
|
|
"TWGS Proxy build "
|
|
|
+ version
|
|
|
+ " is active. \x1b[1;34m~\x1b[0m to activate.\n\r\n\r",
|
|
|
)
|
|
|
+
|
|
|
if "TradeWars Game Server" in line and "Copyright (C) EIS" in line:
|
|
|
# We are not in a game
|
|
|
- self.game = ""
|
|
|
+ if not self.game is None:
|
|
|
+ # We were in a game.
|
|
|
+ self.game = None
|
|
|
+ self.observer.emit("user-game", (self.factory.player.user, self.game))
|
|
|
+
|
|
|
if "Selection (? for menu): " in line:
|
|
|
game = line[-1]
|
|
|
if game >= "A" and game < "Q":
|
|
|
self.game = game
|
|
|
log.msg("Game: {0}".format(self.game))
|
|
|
- self.game = game
|
|
|
- # self.setGame(game)
|
|
|
+ self.observer.emit("user-game", (self.factory.player.user, self.game))
|
|
|
+
|
|
|
+ self.observer.emit("game-line", line)
|
|
|
|
|
|
def dataReceived(self, chunk):
|
|
|
""" Data received from the Game.
|
|
@@ -154,8 +205,8 @@ class Game(protocol.Protocol):
|
|
|
# be out of order. (I'd be responding -- before it
|
|
|
# was displayed to the user.)
|
|
|
|
|
|
- # Possibly: if self.passon ... send to player
|
|
|
- self.queue_game.put(chunk)
|
|
|
+ if self.to_player:
|
|
|
+ self.queue_game.put(chunk)
|
|
|
|
|
|
self.buffer += chunk.decode("utf-8", "ignore")
|
|
|
|
|
@@ -176,6 +227,8 @@ class Game(protocol.Protocol):
|
|
|
self.lineReceived(line)
|
|
|
self.buffer = part[2]
|
|
|
|
|
|
+ self.observer.emit("prompt", cleanANSI(self.buffer))
|
|
|
+
|
|
|
def connectionLost(self, why):
|
|
|
log.msg("Game connectionLost because: %s" % why)
|
|
|
self.queue_game.put(False)
|
|
@@ -242,7 +295,7 @@ class Player(protocol.Protocol):
|
|
|
self.queue_game.get().addCallback(self.gameDataReceived)
|
|
|
|
|
|
def gameDataReceived(self, chunk):
|
|
|
- """ Data received from the client/player. """
|
|
|
+ """ Data received from the game. """
|
|
|
if chunk is False:
|
|
|
self.transport.loseConnection()
|
|
|
else:
|
|
@@ -269,8 +322,11 @@ class Player(protocol.Protocol):
|
|
|
# but I don't need the buffer anymore, so:
|
|
|
self.buffer = ""
|
|
|
# Pass user value on to whatever needs it.
|
|
|
+ self.observer.emit("user", self.user)
|
|
|
|
|
|
- self.queue_player.put(chunk)
|
|
|
+ if not self.observer.emit("player", chunk):
|
|
|
+ # Was not dispatched. Send to game.
|
|
|
+ self.queue_player.put(chunk)
|
|
|
|
|
|
def connectionLost(self, why):
|
|
|
log.msg("lost connection %s" % why)
|