|
@@ -13,6 +13,7 @@ import pendulum
|
|
|
from subprocess import check_output
|
|
|
|
|
|
from colorama import Fore, Back, Style
|
|
|
+from itertools import cycle
|
|
|
|
|
|
# This isn't the best configuration, but it's simple
|
|
|
# and works. Mostly.
|
|
@@ -126,19 +127,37 @@ class MCP(object):
|
|
|
self.prompt = None
|
|
|
self.observer = None
|
|
|
self.keepalive = None
|
|
|
+ # Port Data
|
|
|
+ self.portdata = None
|
|
|
+ self.portcycle = 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
|
|
|
+ # 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)
|
|
|
+ self.observer.connect("notyet", self.notyet)
|
|
|
+
|
|
|
+ def notyet(self, _):
|
|
|
+ """ No, not yet! """
|
|
|
+ nl = "\n\r"
|
|
|
+ r = Style.RESET_ALL
|
|
|
+
|
|
|
+ log.msg("NNY!")
|
|
|
+ prompt = self.game.buffer
|
|
|
+ self.queue_game.put(r + nl + "Proxy: I can't activate at this time." + nl)
|
|
|
+ self.queue_game.put(prompt)
|
|
|
|
|
|
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 startAwake(self):
|
|
|
+ self.keepalive = task.LoopingCall(self.stayAwake)
|
|
|
+ self.keepalive.start(30)
|
|
|
+
|
|
|
def activate(self, _):
|
|
|
log.msg("MCP menu called.")
|
|
|
# We want the raw one, not the ANSI cleaned getPrompt.
|
|
@@ -153,8 +172,9 @@ class MCP(object):
|
|
|
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)
|
|
|
+ self.startAwake()
|
|
|
+ # self.keepalive = task.LoopingCall(self.stayAwake)
|
|
|
+ # self.keepalive.start(30)
|
|
|
|
|
|
def displayMenu(self):
|
|
|
nl = "\n\r"
|
|
@@ -193,8 +213,14 @@ class MCP(object):
|
|
|
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.portReport()
|
|
|
+ # self.queue_game.put(nl + c + "NO, NOT YET!" + r + nl)
|
|
|
+ # self.displayMenu()
|
|
|
+
|
|
|
+ elif key == 'D':
|
|
|
+ self.queue_game.put(nl + "Diagnostics" + nl "portdata:" + nl + repr(self.portdata) + nl)
|
|
|
self.displayMenu()
|
|
|
+
|
|
|
elif key == "X":
|
|
|
log.msg('"Quit, return to "normal". (Whatever that means!)')
|
|
|
self.queue_game.put(c + key + r + nl)
|
|
@@ -204,12 +230,109 @@ class MCP(object):
|
|
|
self.prompt = None
|
|
|
self.keepalive.stop()
|
|
|
self.keepalive = None
|
|
|
+ self.game.to_player = True
|
|
|
else:
|
|
|
if key.isprintable():
|
|
|
self.queue_game.put(r + nl)
|
|
|
self.queue_game.put("Excuse me? I don't understand '" + key + "'." + nl)
|
|
|
self.displayMenu()
|
|
|
|
|
|
+ def portReport(self):
|
|
|
+ """ Activate CIM and request Port Report """
|
|
|
+ self.game.to_player = False
|
|
|
+ self.portdata = None
|
|
|
+ self.observer.connect('prompt', self.portPrompt)
|
|
|
+ self.observer.connect('game-line', self.portParse)
|
|
|
+ self.game.queue_player.put("^")
|
|
|
+
|
|
|
+ def portPrompt(self, prompt):
|
|
|
+ if prompt == ': ':
|
|
|
+ log.msg("CIM Prompt")
|
|
|
+ if self.portdata is None:
|
|
|
+ log.msg("R - Port Report")
|
|
|
+ self.portdata = dict()
|
|
|
+ self.game.queue_player.put("R")
|
|
|
+ self.portcycle = cycle(['/', '-', '\\', '|'])
|
|
|
+ self.queue_game.put(' ')
|
|
|
+ else:
|
|
|
+ log.msg("Q - Quit")
|
|
|
+ self.game.queue_player.put("Q")
|
|
|
+ self.portcycle = None
|
|
|
+
|
|
|
+ def portBS(self, info):
|
|
|
+ if info[0] == '-':
|
|
|
+ bs = 'B'
|
|
|
+ else:
|
|
|
+ bs = 'S'
|
|
|
+ return (bs, int(info[1:].strip()))
|
|
|
+
|
|
|
+ def portParse(self, line):
|
|
|
+ if line == '':
|
|
|
+ return
|
|
|
+ if line == ': ':
|
|
|
+ return
|
|
|
+
|
|
|
+ log.msg("parse line:", line)
|
|
|
+
|
|
|
+ if line.startswith('Command [TL='):
|
|
|
+ return
|
|
|
+
|
|
|
+ if line == ': ENDINTERROG':
|
|
|
+ log.msg("CIM Done")
|
|
|
+ log.msg(self.portdata)
|
|
|
+ self.queue_game.put("\x08 \x08" + "\n\r")
|
|
|
+ self.observer.disconnect('prompt', self.portPrompt)
|
|
|
+ self.observer.disconnect('game-line', self.portParse)
|
|
|
+ self.game.to_player = True
|
|
|
+ # self.keepalive.start(30)
|
|
|
+ self.startAwake()
|
|
|
+ self.displayMenu()
|
|
|
+ return
|
|
|
+
|
|
|
+ # Give some sort of feedback to the user.
|
|
|
+ if self.portcycle:
|
|
|
+ self.queue_game.put("\x08" + next(self.portcycle))
|
|
|
+
|
|
|
+ # Ok, we need to parse this line
|
|
|
+ # 436 2870 100% - 1520 100% - 2820 100%
|
|
|
+ # 2 1950 100% - 1050 100% 2780 100%
|
|
|
+ # 5 2800 100% - 2330 100% - 1230 100%
|
|
|
+ # 8 2890 100% 1530 100% - 2310 100%
|
|
|
+ # 9 - 2160 100% 2730 100% - 2120 100%
|
|
|
+ # 324 - 2800 100% 2650 100% - 2490 100%
|
|
|
+ # 492 990 100% 900 100% 1660 100%
|
|
|
+ # 890 1920 100% - 2140 100% 1480 100%
|
|
|
+ # 1229 - 2870 100% - 1266 90% 728 68%
|
|
|
+ # 1643 - 3000 100% - 3000 100% - 3000 100%
|
|
|
+ # 1683 - 1021 97% 1460 100% - 2620 100%
|
|
|
+ # 1898 - 1600 100% - 1940 100% - 1860 100%
|
|
|
+ # 2186 1220 100% - 900 100% - 1840 100%
|
|
|
+ # 2194 2030 100% - 1460 100% - 1080 100%
|
|
|
+ # 2577 2810 100% - 1550 100% - 2350 100%
|
|
|
+ # 2629 2570 100% - 2270 100% - 1430 100%
|
|
|
+ # 3659 - 1720 100% 1240 100% - 2760 100%
|
|
|
+ # 3978 - 920 100% 2560 100% - 2590 100%
|
|
|
+ # 4302 348 25% - 2530 100% - 316 23%
|
|
|
+ # 4516 - 1231 60% - 1839 75% 7 0%
|
|
|
+ work = line.replace('%', '')
|
|
|
+ parts = re.split(r"(?<=\d)\s", work)
|
|
|
+ if len(parts) == 8:
|
|
|
+ port = int(parts[0].strip())
|
|
|
+ data = dict()
|
|
|
+ data['fuel'] = dict( )
|
|
|
+ data['fuel']['sale'], data['fuel']['units'] = self.portBS(parts[1])
|
|
|
+ data['fuel']['pct'] = int(parts[2].strip())
|
|
|
+ data['org'] = dict( )
|
|
|
+ data['org']['sale'], data['org']['units'] = self.portBS(parts[3])
|
|
|
+ data['org']['pct'] = int(parts[4].strip())
|
|
|
+ data['equ'] = dict( )
|
|
|
+ data['equ']['sale'], data['equ']['units'] = self.portBS(parts[5])
|
|
|
+ data['equ']['pct'] = int(parts[6].strip())
|
|
|
+ self.portdata[port] = data
|
|
|
+ else:
|
|
|
+ self.queue_game.put("?")
|
|
|
+ log.msg("Line in question is: [{0}].".format(line))
|
|
|
+ log.msg(repr(parts))
|
|
|
|
|
|
class Game(protocol.Protocol):
|
|
|
def __init__(self):
|
|
@@ -224,6 +347,7 @@ class Game(protocol.Protocol):
|
|
|
self.queue_player = self.factory.queue_player
|
|
|
self.queue_game = self.factory.queue_game
|
|
|
self.observer = self.factory.observer
|
|
|
+ self.factory.game = self
|
|
|
self.setPlayerReceived()
|
|
|
self.observer.connect("user-game", self.show_game)
|
|
|
self.mcp.finishSetup()
|
|
@@ -343,6 +467,7 @@ class GlueFactory(protocol.ClientFactory):
|
|
|
self.queue_player = player.queue_player
|
|
|
self.queue_game = player.queue_game
|
|
|
self.observer = player.observer
|
|
|
+ self.game = None
|
|
|
|
|
|
def closeIt(self):
|
|
|
log.msg("closeIt")
|
|
@@ -371,6 +496,8 @@ class Player(protocol.Protocol):
|
|
|
self.buffer = ""
|
|
|
self.user = None
|
|
|
self.observer = Observer()
|
|
|
+ self.game = None
|
|
|
+ self.glue = None
|
|
|
|
|
|
def connectionMade(self):
|
|
|
""" connected, setup queues.
|
|
@@ -384,6 +511,7 @@ class Player(protocol.Protocol):
|
|
|
|
|
|
# Connect GlueFactory to this Player object.
|
|
|
factory = GlueFactory(self)
|
|
|
+ self.glue = factory
|
|
|
|
|
|
# Make connection to the game server
|
|
|
reactor.connectTCP(HOST, PORT, factory, 5)
|
|
@@ -394,6 +522,10 @@ class Player(protocol.Protocol):
|
|
|
|
|
|
def gameDataReceived(self, chunk):
|
|
|
""" Data received from the game. """
|
|
|
+ # If we have received game data, it has to be connected.
|
|
|
+ if self.game is None:
|
|
|
+ self.game = self.glue.game
|
|
|
+
|
|
|
if chunk is False:
|
|
|
self.transport.loseConnection()
|
|
|
else:
|
|
@@ -428,10 +560,21 @@ class Player(protocol.Protocol):
|
|
|
self.queue_player.put(chunk)
|
|
|
|
|
|
if chunk == b"~":
|
|
|
+ if self.game:
|
|
|
+ prompt = self.game.getPrompt()
|
|
|
+ if "Selection (? for menu)" in prompt:
|
|
|
+ self.observer.emit("notyet", prompt)
|
|
|
+ if "Enter your choice:" in prompt:
|
|
|
+ self.observer.emit("notyet", prompt)
|
|
|
+ if re.match(r"Computer command \[TL=.* \(\?=Help\)\? :", prompt):
|
|
|
+ self.observer.emit("notyet", prompt)
|
|
|
+ if re.match(r"Command \[TL=.* \(\?=Help\)\? :", prompt):
|
|
|
+ self.observer.emit("hotkey", prompt)
|
|
|
+
|
|
|
# Selection (? for menu): (the game server menu)
|
|
|
# Enter your choice: (game menu)
|
|
|
# Command [TL=00:00:00]:[1800] (?=Help)? : <- YES!
|
|
|
- self.observer.emit("hotkey", None)
|
|
|
+ # Computer command [TL=00:00:00]:[613] (?=Help)?
|
|
|
|
|
|
def connectionLost(self, why):
|
|
|
log.msg("lost connection %s" % why)
|