import curses
import queue
import threading
+import time
from plomrogue.game import GameBase
from plomrogue.parser import Parser
from plomrogue.mapping import YX, MapGeometrySquare, MapGeometryHex
}
cmd_MAP.argtypes = 'string:map_geometry yx_tuple:pos string'
+def cmd_FOV(game, content):
+ game.fov = content
+cmd_FOV.argtypes = 'string'
+
def cmd_MAP_CONTROL(game, content):
game.map_control_content = content
cmd_MAP_CONTROL.argtypes = 'string'
self.register_command(cmd_GAME_ERROR)
self.register_command(cmd_PLAY_ERROR)
self.register_command(cmd_TASKS)
+ self.register_command(cmd_FOV)
self.map_content = ''
self.player_id = -1
self.info_db = {}
for k in keys_conf:
self.keys[k] = keys_conf[k]
self.show_help = False
+ self.disconnected = True
+ self.force_instant_connect = True
+ self.input_lines = []
+ self.fov = ''
curses.wrapper(self.loop)
def flash(self):
curses.flash()
+ def connect(self):
+
+ def handle_recv(msg):
+ if msg == 'BYE':
+ self.socket.close()
+ else:
+ self.queue.put(msg)
+
+ self.log_msg('@ attempting connect')
+ socket_client_class = PlomSocketClient
+ if self.host.startswith('ws://') or self.host.startswith('wss://'):
+ socket_client_class = WebSocketClient
+ try:
+ self.socket = socket_client_class(handle_recv, self.host)
+ self.socket_thread = threading.Thread(target=self.socket.run)
+ self.socket_thread.start()
+ self.disconnected = False
+ self.socket.send('TASKS')
+ self.switch_mode('login')
+ except ConnectionRefusedError:
+ self.log_msg('@ server connect failure')
+ self.disconnected = True
+ self.switch_mode('waiting_for_server')
+ self.do_refresh = True
+
+ def reconnect(self):
+ self.log_msg('@ attempting reconnect')
+ self.send('QUIT')
+ time.sleep(0.1) # FIXME necessitated by some some strange SSL race
+ # conditions with ws4py, find out what exactly
+ self.switch_mode('waiting_for_server')
+ self.connect()
+
def send(self, msg):
try:
if hasattr(self.socket, 'plom_closed') and self.socket.plom_closed:
self.socket.send(msg)
except (BrokenPipeError, BrokenSocketConnection):
self.log_msg('@ server disconnected :(')
+ self.disconnected = True
+ self.force_instant_connect = True
self.do_refresh = True
def log_msg(self, msg):
self.restore_input_values()
def loop(self, stdscr):
- import time
import datetime
def safe_addstr(y, x, line):
stdscr.insstr(y, self.size.x - 2, ' ')
stdscr.addstr(y, x, cut)
- def connect():
-
- def handle_recv(msg):
- if msg == 'BYE':
- self.socket.close()
- else:
- self.queue.put(msg)
-
- socket_client_class = PlomSocketClient
- if self.host.startswith('ws://') or self.host.startswith('wss://'):
- socket_client_class = WebSocketClient
- while True:
- try:
- self.socket = socket_client_class(handle_recv, self.host)
- self.socket_thread = threading.Thread(target=self.socket.run)
- self.socket_thread.start()
- self.socket.send('TASKS')
- self.switch_mode('login')
- return
- except ConnectionRefusedError:
- self.log_msg('@ server connect failure, trying again …')
- draw_screen()
- stdscr.refresh()
- time.sleep(1)
-
- def reconnect():
- self.send('QUIT')
- time.sleep(0.1) # FIXME necessitated by some some strange SSL race
- # conditions with ws4py, find out what exactly
- self.switch_mode('waiting_for_server')
- connect()
-
def handle_input(msg):
command, args = self.parser.parse(msg)
command(*args)
if not self.game.turn_complete:
return
pos_i = self.explorer.y * self.game.map_geometry.size.x + self.explorer.x
- info = 'TERRAIN: %s\n' % self.game.map_content[pos_i]
- for t in self.game.things:
- if t.position == self.explorer:
- info += 'PLAYER @: %s\n' % t.name
- if self.explorer in self.game.portals:
- info += 'PORTAL: ' + self.game.portals[self.explorer] + '\n'
- else:
- info += 'PORTAL: (none)\n'
- if self.explorer in self.game.info_db:
- info += 'ANNOTATION: ' + self.game.info_db[self.explorer]
- else:
- info += 'ANNOTATION: waiting …'
+ info = 'outside field of view'
+ if self.game.fov[pos_i] == '.':
+ info = 'TERRAIN: %s\n' % self.game.map_content[pos_i]
+ for t in self.game.things:
+ if t.position == self.explorer:
+ info += 'PLAYER @: %s\n' % t.name
+ if self.explorer in self.game.portals:
+ info += 'PORTAL: ' + self.game.portals[self.explorer] + '\n'
+ else:
+ info += 'PORTAL: (none)\n'
+ if self.explorer in self.game.info_db:
+ info += 'ANNOTATION: ' + self.game.info_db[self.explorer]
+ else:
+ info += 'ANNOTATION: waiting …'
lines = msg_into_lines_of_width(info, self.window_width)
height_header = 2
for i in range(len(lines)):
map_y += 1
def draw_help():
- content = "%s mode help (hit any key to disappear)\n\n%s\n\n" % (self.mode.name,
- self.mode.help_intro)
+ content = "%s mode help\n\n%s\n\n" % (self.mode.name,
+ self.mode.help_intro)
if self.mode == self.mode_play:
content += "Available actions:\n"
if 'MOVE' in self.game.tasks:
self.explorer = YX(0, 0)
self.input_ = ''
input_prompt = '> '
- connect()
- last_ping = datetime.datetime.now()
- interval = datetime.timedelta(seconds=30)
+ interval = datetime.timedelta(seconds=5)
+ last_ping = datetime.datetime.now() - interval
while True:
+ if self.disconnected and self.force_instant_connect:
+ self.force_instant_connect = False
+ self.connect()
now = datetime.datetime.now()
if now - last_ping > interval:
- self.send('PING')
+ if self.disconnected:
+ self.connect()
+ else:
+ self.send('PING')
last_ping = now
if self.do_refresh:
draw_screen()
self.switch_mode('play')
elif self.input_ in {'/' + self.keys['switch_to_study'], '/study'}:
self.switch_mode('study')
- elif self.input_ == '/reconnect':
- reconnect()
elif self.input_.startswith('/nick'):
tokens = self.input_.split(maxsplit=1)
if len(tokens) == 2:
elif self.mode == self.mode_teleport and key == '\n':
if self.input_ == 'YES!':
self.host = self.teleport_target_host
- reconnect()
+ self.reconnect()
else:
self.log_msg('@ teleport aborted')
self.switch_mode('play')