|
@@ -6,6 +6,7 @@ import re
|
|
|
from twisted.internet import defer
|
|
|
from twisted.internet import protocol
|
|
|
from twisted.internet import reactor
|
|
|
+from twisted.internet import task
|
|
|
from twisted.python import log
|
|
|
from twisted.python.logfile import DailyLogFile
|
|
|
import pendulum
|
|
@@ -115,11 +116,106 @@ class Observer(object):
|
|
|
self.dispatch = list(funcs)
|
|
|
|
|
|
|
|
|
+class MCP(object):
|
|
|
+ def __init__(self, game):
|
|
|
+ self.game = game
|
|
|
+ self.queue_game = None
|
|
|
+ # we don't have this .. yet!
|
|
|
+ self.prompt = None
|
|
|
+ self.observer = None
|
|
|
+ self.keepalive = None
|
|
|
+
|
|
|
+ def finishSetup(self):
|
|
|
+ if self.queue_game is None:
|
|
|
+ self.queue_game = self.game.queue_game
|
|
|
+ if self.observer is None:
|
|
|
+ self.observer = self.game.observer
|
|
|
+ self.observer.connect("hotkey", self.activate)
|
|
|
+
|
|
|
+ def stayAwake(self):
|
|
|
+ """ Send a space to the game to keep it alive/don't timeout. """
|
|
|
+ log.msg("Gameserver, stay awake.")
|
|
|
+ self.game.queue_player.put(" ")
|
|
|
+
|
|
|
+ def activate(self, _):
|
|
|
+ log.msg("MCP menu called.")
|
|
|
+ # We want the raw one, not the ANSI cleaned getPrompt.
|
|
|
+ prompt = self.game.buffer
|
|
|
+ if not self.prompt is None:
|
|
|
+ # silly, we're already active
|
|
|
+ log.msg("I think we're already active. Ignoring request.")
|
|
|
+ return
|
|
|
+ # Or will the caller setup/restore the prompt?
|
|
|
+ self.prompt = prompt
|
|
|
+ # queue_game = to player
|
|
|
+ self.displayMenu()
|
|
|
+ self.observer.connect("player", self.fromPlayer)
|
|
|
+ # TODO: Add background "keepalive" event so the game doesn't time out on us.
|
|
|
+ self.keepalive = task.LoopingCall(self.stayAwake)
|
|
|
+ self.keepalive.start(30)
|
|
|
+
|
|
|
+ def displayMenu(self):
|
|
|
+ nl = "\n\r"
|
|
|
+ c = merge(Style.BRIGHT + Fore.YELLOW + Back.BLUE)
|
|
|
+ r = Style.RESET_ALL
|
|
|
+ c1 = merge(Style.BRIGHT + Fore.BLUE)
|
|
|
+ c2 = merge(Style.NORMAL + Fore.BLUE)
|
|
|
+
|
|
|
+ self.queue_game.put(nl + c + "TradeWars Proxy active." + r + nl)
|
|
|
+ self.queue_game.put(
|
|
|
+ " " + c1 + "T" + c2 + " - " + c1 + "Display current Time" + nl
|
|
|
+ )
|
|
|
+ self.queue_game.put(" " + c1 + "P" + c2 + " - " + c1 + "Port CIM Report" + nl)
|
|
|
+ self.queue_game.put(" " + c1 + "X" + c2 + " - " + c1 + "eXit" + nl)
|
|
|
+ self.queue_game.put(" " + c + "-=>" + r + " ")
|
|
|
+
|
|
|
+ def fromPlayer(self, chunk):
|
|
|
+ """ Data from player (in bytes). """
|
|
|
+ chunk = chunk.decode("utf-8", "ignore")
|
|
|
+
|
|
|
+ nl = "\n\r"
|
|
|
+ c = merge(Style.BRIGHT + Fore.YELLOW + Back.BLUE)
|
|
|
+ r = Style.RESET_ALL
|
|
|
+ c1 = merge(Style.BRIGHT + Fore.BLUE)
|
|
|
+ c2 = merge(Style.NORMAL + Fore.BLUE)
|
|
|
+
|
|
|
+ key = chunk.upper()
|
|
|
+ if key == "T":
|
|
|
+ self.queue_game.put(c + key + r + nl)
|
|
|
+ now = pendulum.now()
|
|
|
+ log.msg("Time")
|
|
|
+ self.queue_game.put(
|
|
|
+ nl + c1 + "It is currently " + now.to_datetime_string() + "." + nl
|
|
|
+ )
|
|
|
+ self.displayMenu()
|
|
|
+ elif key == "P":
|
|
|
+ log.msg("Port")
|
|
|
+ self.queue_game.put(c + key + r + nl)
|
|
|
+ self.queue_game.put(nl + c + "NO, NOT YET!" + r + nl)
|
|
|
+ self.displayMenu()
|
|
|
+ elif key == "X":
|
|
|
+ log.msg('"Quit, return to "normal". (Whatever that means!)')
|
|
|
+ self.queue_game.put(c + key + r + nl)
|
|
|
+ self.observer.disconnect("player", self.fromPlayer)
|
|
|
+ self.queue_game.put(nl + c1 + "Returning to game" + c2 + "..." + r + nl)
|
|
|
+ self.queue_game.put(self.prompt)
|
|
|
+ self.prompt = None
|
|
|
+ self.keepalive.stop()
|
|
|
+ self.keepalive = None
|
|
|
+ else:
|
|
|
+ if key.isprintable():
|
|
|
+ self.queue_game.put(r + nl)
|
|
|
+ self.queue_game.put("Excuse me? I don't understand '" + key + "'." + nl)
|
|
|
+ self.displayMenu()
|
|
|
+
|
|
|
+
|
|
|
class Game(protocol.Protocol):
|
|
|
def __init__(self):
|
|
|
self.buffer = ""
|
|
|
self.game = None
|
|
|
+ self.usergame = (None, None)
|
|
|
self.to_player = True
|
|
|
+ self.mcp = MCP(self)
|
|
|
|
|
|
def connectionMade(self):
|
|
|
log.msg("Connected to Game Server")
|
|
@@ -127,18 +223,11 @@ 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)
|
|
|
+ self.mcp.finishSetup()
|
|
|
|
|
|
def show_game(self, game):
|
|
|
+ self.usergame = game
|
|
|
log.msg("## User-Game:", game)
|
|
|
|
|
|
def setPlayerReceived(self):
|
|
@@ -154,7 +243,10 @@ class Game(protocol.Protocol):
|
|
|
self.transport.loseConnection()
|
|
|
else:
|
|
|
# Pass received data to the server
|
|
|
- self.transport.write(chunk)
|
|
|
+ if type(chunk) == str:
|
|
|
+ self.transport.write(chunk.encode())
|
|
|
+ else:
|
|
|
+ self.transport.write(chunk)
|
|
|
self.setPlayerReceived()
|
|
|
|
|
|
def lineReceived(self, line):
|
|
@@ -185,6 +277,10 @@ class Game(protocol.Protocol):
|
|
|
|
|
|
self.observer.emit("game-line", line)
|
|
|
|
|
|
+ def getPrompt(self):
|
|
|
+ """ Return the current prompt, stripped of ANSI. """
|
|
|
+ return cleanANSI(self.buffer)
|
|
|
+
|
|
|
def dataReceived(self, chunk):
|
|
|
""" Data received from the Game.
|
|
|
|
|
@@ -227,7 +323,7 @@ class Game(protocol.Protocol):
|
|
|
self.lineReceived(line)
|
|
|
self.buffer = part[2]
|
|
|
|
|
|
- self.observer.emit("prompt", cleanANSI(self.buffer))
|
|
|
+ self.observer.emit("prompt", self.getPrompt())
|
|
|
|
|
|
def connectionLost(self, why):
|
|
|
log.msg("Game connectionLost because: %s" % why)
|
|
@@ -323,11 +419,15 @@ class Player(protocol.Protocol):
|
|
|
self.buffer = ""
|
|
|
# Pass user value on to whatever needs it.
|
|
|
self.observer.emit("user", self.user)
|
|
|
+ # Unfortunately, the ones interested in this don't exist yet.
|
|
|
|
|
|
if not self.observer.emit("player", chunk):
|
|
|
# Was not dispatched. Send to game.
|
|
|
self.queue_player.put(chunk)
|
|
|
|
|
|
+ if chunk == b"~":
|
|
|
+ self.observer.emit("hotkey", None)
|
|
|
+
|
|
|
def connectionLost(self, why):
|
|
|
log.msg("lost connection %s" % why)
|
|
|
self.queue_player.put(False)
|