From: Christian Heller <c.heller@plomlompom.de> Date: Sun, 6 Dec 2020 18:31:04 +0000 (+0100) Subject: Replace annotation polling with annotation push, cache info display. X-Git-Url: https://plomlompom.com/repos/%7B%7Bprefix%7D%7D/static/%7B%7Bdb.prefix%7D%7D/do_tasks?a=commitdiff_plain;h=a81ea397900267331c15c1cda5d349b22a49ea16;p=plomrogue2 Replace annotation polling with annotation push, cache info display. --- diff --git a/plomrogue/commands.py b/plomrogue/commands.py index 2061fe7..07bfae0 100644 --- a/plomrogue/commands.py +++ b/plomrogue/commands.py @@ -202,18 +202,6 @@ def cmd_GOD_PORTAL(game, big_yx, little_yx, msg): game.changed = True cmd_GOD_PORTAL.argtypes = 'yx_tuple yx_tuple:nonneg string' -def cmd_GET_ANNOTATION(game, yx, connection_id): - player = game.get_player(connection_id) - big_yx, little_yx = player.fov_stencil.source_yxyx(yx) - annotation = '(unknown)' - if player.fov_test(big_yx, little_yx): - annotation = '(none)' - if big_yx in game.annotations: - if little_yx in game.annotations[big_yx]: - annotation = game.annotations[big_yx][little_yx] - game.io.send('ANNOTATION %s %s' % (yx, quote(annotation))) -cmd_GET_ANNOTATION.argtypes = 'yx_tuple:nonneg' - def cmd_MAP_LINE(game, big_yx, y, line): map_ = game.get_map(big_yx) map_.set_line(y, line) diff --git a/plomrogue/game.py b/plomrogue/game.py index ff76155..c495179 100755 --- a/plomrogue/game.py +++ b/plomrogue/game.py @@ -202,6 +202,7 @@ class Game(GameBase): def send_gamestate(self, connection_id=None): """Send out game state data relevant to clients.""" + # TODO: limit to connection_id if provided self.io.send('TURN ' + str(self.turn)) from plomrogue.mapping import FovMap import multiprocessing @@ -247,7 +248,9 @@ class Game(GameBase): for little_yx in [little_yx for little_yx in self.annotations[big_yx] if player.fov_test(big_yx, little_yx)]: target_yx = player.fov_stencil.target_yx(big_yx, little_yx) - self.io.send('ANNOTATION_HINT %s' % (target_yx,), c_id) + annotation = self.annotations[big_yx][little_yx] + self.io.send('ANNOTATION %s %s' % (target_yx, + quote(annotation)), c_id) self.io.send('GAME_STATE_COMPLETE') def run_tick(self): diff --git a/rogue_chat.html b/rogue_chat.html index 8efe2a2..dd037e2 100644 --- a/rogue_chat.html +++ b/rogue_chat.html @@ -120,8 +120,8 @@ keyboard input/control: <span id="keyboard_control"></span> </div> <script> "use strict"; -let websocket_location = "wss://plomlompom.com/rogue_chat/"; -//let websocket_location = "ws://localhost:8000/"; +//let websocket_location = "wss://plomlompom.com/rogue_chat/"; +let websocket_location = "ws://localhost:8001/"; let mode_helps = { 'play': { @@ -437,9 +437,10 @@ let server = { let tokens = parser.tokenize(event.data); if (tokens[0] === 'TURN') { game.turn_complete = false; - explorer.empty_info_db(); + explorer.empty_annotations(); game.things = {}; game.portals = {}; + game.fov = ''; game.turn = parseInt(tokens[1]); } else if (tokens[0] === 'THING') { let t = game.get_thing(tokens[4], true); @@ -477,9 +478,8 @@ let server = { game.turn_complete = true; if (tui.mode.name == 'post_login_wait') { tui.switch_mode('play'); - } else if (tui.mode.name == 'study') { - explorer.query_info(); } + explorer.info_cached = false; tui.full_refresh(); } else if (tokens[0] === 'CHAT') { tui.log_msg('# ' + tokens[1], 1); @@ -501,12 +501,9 @@ let server = { } else if (tokens[0] === 'PORTAL') { let position = parser.parse_yx(tokens[1]); game.portals[position] = tokens[2]; - } else if (tokens[0] === 'ANNOTATION_HINT') { - let position = parser.parse_yx(tokens[1]); - explorer.info_hints = explorer.info_hints.concat([position]); } else if (tokens[0] === 'ANNOTATION') { let position = parser.parse_yx(tokens[1]); - explorer.update_info_db(position, tokens[2]); + explorer.update_annotations(position, tokens[2]); tui.full_refresh(); } else if (tokens[0] === 'UNHANDLED_INPUT') { tui.log_msg('? unknown command'); @@ -742,9 +739,6 @@ let tui = { } if (game.player_id in game.things && (this.mode.shows_info || this.mode.name == 'control_tile_draw')) { explorer.position = game.things[game.player_id].position; - if (this.mode.shows_info) { - explorer.query_info(); - } } this.inputEl.value = ""; this.restore_input_values(); @@ -806,8 +800,8 @@ let tui = { } }, restore_input_values: function() { - if (this.mode.name == 'annotate' && explorer.position in explorer.info_db) { - let info = explorer.info_db[explorer.position]; + if (this.mode.name == 'annotate' && explorer.position in explorer.annotations) { + let info = explorer.annotations[explorer.position]; if (info != "(none)") { this.inputEl.value = info; } @@ -1034,8 +1028,8 @@ let tui = { this.offset_links(offset, log_links); }, draw_info: function() { - let [lines, link_data] = this.msg_into_lines_of_width(explorer.get_info(), - this.window_width); + const info = "MAP VIEW: " + tui.map_mode + "\n" + explorer.get_info(); + let [lines, link_data] = this.msg_into_lines_of_width(info, this.window_width); let offset = [this.height_header, this.window_width]; for (let y = offset[0], i = 0; y < terminal.rows && i < lines.length; y++, i++) { terminal.write(y, offset[1], lines[i]); @@ -1214,81 +1208,79 @@ server.init(websocket_location); let explorer = { position: [0,0], - info_db: {}, - info_hints: [], + annotations: {}, + info_cached: false, move: function(direction) { let target = game.move(this.position, direction); if (target) { this.position = target - if (tui.mode.shows_info) { - this.query_info(); - } else if (tui.tile_draw) { + this.info_cached = false; + if (tui.tile_draw) { this.send_tile_control_command(); } } else { terminal.blink_screen(); }; }, - update_info_db: function(yx, str) { - this.info_db[yx] = str; + update_annotations: function(yx, str) { + this.annotations[yx] = str; if (tui.mode.name == 'study') { tui.full_refresh(); } }, - empty_info_db: function() { - this.info_db = {}; - this.info_hints = []; + empty_annotations: function() { + this.annotations = {}; if (tui.mode.name == 'study') { tui.full_refresh(); } }, - query_info: function() { - server.send(["GET_ANNOTATION", unparser.to_yx(explorer.position)]); - }, get_info: function() { - let info = "MAP VIEW: " + tui.map_mode + "\n"; + if (this.info_cached) { + return this.info_cached; + } + let info_to_cache = ''; let position_i = this.position[0] * game.map_size[1] + this.position[1]; if (game.fov[position_i] != '.') { - return info + 'outside field of view'; - }; - let terrain_char = game.map[position_i] - let terrain_desc = '?' - if (game.terrains[terrain_char]) { - terrain_desc = game.terrains[terrain_char]; - }; - info += 'TERRAIN: "' + terrain_char + '" / ' + terrain_desc + "\n"; - let protection = game.map_control[position_i]; - if (protection == '.') { - protection = 'unprotected'; - }; - info += 'PROTECTION: ' + protection + '\n'; - for (let t_id in game.things) { - let t = game.things[t_id]; - if (t.position[0] == this.position[0] && t.position[1] == this.position[1]) { - let symbol = game.thing_types[t.type_]; - let protection = t.protection; - if (protection == '.') { - protection = 'none'; - } - info += "THING: " + t.type_ + " / " + symbol; - if (t.thing_char) { - info += t.thing_char; - }; - if (t.name_) { - info += " (" + t.name_ + ")"; - } - info += " / protection: " + protection + "\n"; - } - } - if (this.position in game.portals) { - info += "PORTAL: " + game.portals[this.position] + "\n"; - } - if (this.position in this.info_db) { - info += "ANNOTATIONS: " + this.info_db[this.position]; + info_to_cache += 'outside field of view'; } else { - info += 'waiting â¦'; + let terrain_char = game.map[position_i] + let terrain_desc = '?' + if (game.terrains[terrain_char]) { + terrain_desc = game.terrains[terrain_char]; + }; + info_to_cache += 'TERRAIN: "' + terrain_char + '" / ' + terrain_desc + "\n"; + let protection = game.map_control[position_i]; + if (protection == '.') { + protection = 'unprotected'; + }; + info_to_cache += 'PROTECTION: ' + protection + '\n'; + for (let t_id in game.things) { + let t = game.things[t_id]; + if (t.position[0] == this.position[0] && t.position[1] == this.position[1]) { + let symbol = game.thing_types[t.type_]; + let protection = t.protection; + if (protection == '.') { + protection = 'none'; + } + info_to_cache += "THING: " + t.type_ + " / " + symbol; + if (t.thing_char) { + info_to_cache += t.thing_char; + }; + if (t.name_) { + info_to_cache += " (" + t.name_ + ")"; + } + info_to_cache += " / protection: " + protection + "\n"; + } + } + if (this.position in game.portals) { + info_to_cache += "PORTAL: " + game.portals[this.position] + "\n"; + } + if (this.position in this.annotations) { + info_to_cache += "ANNOTATION: " + this.annotations[this.position]; + } } - return info; + this.info_cached = info_to_cache; + return this.info_cached; }, annotate: function(msg) { if (msg.length == 0) { diff --git a/rogue_chat.py b/rogue_chat.py index 4509d33..8dea176 100755 --- a/rogue_chat.py +++ b/rogue_chat.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 from plomrogue.game import Game from plomrogue.commands import (cmd_ALL, cmd_LOGIN, cmd_NICK, cmd_PING, cmd_THING, - cmd_MAP, cmd_TURN, cmd_MAP_LINE, cmd_GET_ANNOTATION, + cmd_MAP, cmd_TURN, cmd_MAP_LINE, cmd_ANNOTATE, cmd_PORTAL, cmd_GET_GAMESTATE, cmd_TASKS, cmd_MAP_CONTROL_LINE, cmd_MAP_CONTROL_PW, cmd_GOD_ANNOTATE, cmd_GOD_PORTAL, cmd_THING_TYPES, @@ -33,7 +33,6 @@ game.register_command(cmd_MAP) game.register_command(cmd_MAP_LINE) game.register_command(cmd_MAP_CONTROL_LINE) game.register_command(cmd_MAP_CONTROL_PW) -game.register_command(cmd_GET_ANNOTATION) game.register_command(cmd_ANNOTATE) game.register_command(cmd_PORTAL) game.register_command(cmd_GOD_ANNOTATE) diff --git a/rogue_chat_curses.py b/rogue_chat_curses.py index 420c858..70d60b2 100755 --- a/rogue_chat_curses.py +++ b/rogue_chat_curses.py @@ -134,12 +134,12 @@ class PlomSocketClient(PlomSocket): pass # we assume socket will be known as dead by now def cmd_TURN(game, n): - game.info_db = {} - game.info_hints = [] + game.annotations = {} game.turn = n game.things = [] game.portals = {} game.turn_complete = False + game.fov = '' cmd_TURN.argtypes = 'int:nonneg' def cmd_LOGIN_OK(game): @@ -224,10 +224,9 @@ cmd_MAP_CONTROL.argtypes = 'string' def cmd_GAME_STATE_COMPLETE(game): if game.tui.mode.name == 'post_login_wait': game.tui.switch_mode('play') - if game.tui.mode.shows_info: - game.tui.query_info() game.turn_complete = True game.tui.do_refresh = True + game.tui.info_cached = None cmd_GAME_STATE_COMPLETE.argtypes = '' def cmd_PORTAL(game, position, msg): @@ -250,12 +249,8 @@ def cmd_ARGUMENT_ERROR(game, msg): game.tui.do_refresh = True cmd_ARGUMENT_ERROR.argtypes = 'string' -def cmd_ANNOTATION_HINT(game, position): - game.info_hints += [position] -cmd_ANNOTATION_HINT.argtypes = 'yx_tuple:nonneg' - def cmd_ANNOTATION(game, position, msg): - game.info_db[position] = msg + game.annotations[position] = msg if game.tui.mode.shows_info: game.tui.do_refresh = True cmd_ANNOTATION.argtypes = 'yx_tuple:nonneg string' @@ -309,7 +304,6 @@ class Game(GameBase): self.register_command(cmd_MAP_CONTROL) self.register_command(cmd_PORTAL) self.register_command(cmd_ANNOTATION) - self.register_command(cmd_ANNOTATION_HINT) self.register_command(cmd_GAME_STATE_COMPLETE) self.register_command(cmd_ARGUMENT_ERROR) self.register_command(cmd_GAME_ERROR) @@ -320,8 +314,7 @@ class Game(GameBase): self.register_command(cmd_RANDOM_COLORS) self.map_content = '' self.player_id = -1 - self.info_db = {} - self.info_hints = [] + self.annotations = {} self.portals = {} self.terrains = {} @@ -536,14 +529,9 @@ class TUI: if len(self.log) > 100: self.log = self.log[-100:] - def query_info(self): - self.send('GET_ANNOTATION ' + str(self.explorer)) - def restore_input_values(self): - if self.mode.name == 'annotate' and self.explorer in self.game.info_db: - info = self.game.info_db[self.explorer] - if info != '(none)': - self.input_ = info + if self.mode.name == 'annotate' and self.explorer in self.game.annotations: + self.input_ = self.game.annotations[self.explorer] elif self.mode.name == 'portal' and self.explorer in self.game.portals: self.input_ = self.game.portals[self.explorer] elif self.mode.name == 'password': @@ -597,8 +585,6 @@ class TUI: if self.mode.shows_info or self.mode.name == 'control_tile_draw': player = self.game.get_thing(self.game.player_id) self.explorer = YX(player.position.y, player.position.x) - if self.mode.shows_info: - self.query_info() if self.mode.is_single_char_entry: self.show_help = True if self.mode.name == 'waiting_for_server': @@ -640,6 +626,47 @@ class TUI: curses.init_color(2, rand(0), rand(0), rand(0)) self.do_refresh = True + def get_info(self): + if self.info_cached: + return self.info_cached + pos_i = self.explorer.y * self.game.map_geometry.size.x + self.explorer.x + info_to_cache = '' + if len(self.game.fov) > pos_i and self.game.fov[pos_i] != '.': + info_to_cache += 'outside field of view' + else: + terrain_char = self.game.map_content[pos_i] + terrain_desc = '?' + if terrain_char in self.game.terrains: + terrain_desc = self.game.terrains[terrain_char] + info_to_cache += 'TERRAIN: "%s" / %s\n' % (terrain_char, + terrain_desc) + protection = self.game.map_control_content[pos_i] + if protection == '.': + protection = 'unprotected' + info_to_cache += 'PROTECTION: %s\n' % protection + for t in self.game.things: + if t.position == self.explorer: + protection = t.protection + if protection == '.': + protection = 'none' + info_to_cache += 'THING: %s / %s' %\ + (t.type_, self.game.thing_types[t.type_]) + if hasattr(t, 'thing_char'): + info_to_cache += t.thing_char + if hasattr(t, 'name'): + info_to_cache += ' (%s)' % t.name + info_to_cache += ' / protection: %s\n' % protection + if self.explorer in self.game.portals: + info_to_cache += 'PORTAL: ' +\ + self.game.portals[self.explorer] + '\n' + else: + info_to_cache += 'PORTAL: (none)\n' + if self.explorer in self.game.annotations: + info_to_cache += 'ANNOTATION: ' +\ + self.game.annotations[self.explorer] + self.info_cached = info_to_cache + return self.info_cached + def loop(self, stdscr): import datetime @@ -694,9 +721,8 @@ class TUI: def move_explorer(direction): target = self.game.map_geometry.move_yx(self.explorer, direction) if target: + self.info_cached = None self.explorer = target - if self.mode.shows_info: - self.query_info() if self.tile_draw: self.send_tile_control_command() else: @@ -715,42 +741,7 @@ class TUI: safe_addstr(max_y - i - 1, self.window_width, lines[i]) def draw_info(): - if not self.game.turn_complete: - return - pos_i = self.explorer.y * self.game.map_geometry.size.x + self.explorer.x - info = 'MAP VIEW: %s\n' % self.map_mode - if self.game.fov[pos_i] != '.': - info += 'outside field of view' - else: - terrain_char = self.game.map_content[pos_i] - terrain_desc = '?' - if terrain_char in self.game.terrains: - terrain_desc = self.game.terrains[terrain_char] - info += 'TERRAIN: "%s" / %s\n' % (terrain_char, terrain_desc) - protection = self.game.map_control_content[pos_i] - if protection == '.': - protection = 'unprotected' - info += 'PROTECTION: %s\n' % protection - for t in self.game.things: - if t.position == self.explorer: - protection = t.protection - if protection == '.': - protection = 'none' - info += 'THING: %s / %s' % (t.type_, - self.game.thing_types[t.type_]) - if hasattr(t, 'thing_char'): - info += t.thing_char - if hasattr(t, 'name'): - info += ' (%s)' % t.name - info += ' / protection: %s\n' % protection - 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 = 'MAP VIEW: %s\n%s' % (self.map_mode, self.get_info()) lines = msg_into_lines_of_width(info, self.window_width) height_header = 2 for i in range(len(lines)): @@ -792,7 +783,7 @@ class TUI: map_lines_split += [[c + ' ' for c in self.game.map_content[start:end]]] if self.map_mode == 'terrain + annotations': - for p in self.game.info_hints: + for p in self.game.annotations: map_lines_split[p.y][p.x] = 'A ' elif self.map_mode == 'terrain + things': for p in self.game.portals.keys():