From a1e6857395d1003538a635f2cfba102459314f2b Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Sat, 12 Dec 2020 22:16:59 +0100 Subject: [PATCH] In clients, cache all world status until GAME_STATE_COMPLETE. --- rogue_chat.html | 84 ++++++++++++++++++++++++-------------------- rogue_chat_curses.py | 53 ++++++++++++++++++---------- 2 files changed, 79 insertions(+), 58 deletions(-) diff --git a/rogue_chat.html b/rogue_chat.html index 0bb8c43..f47cf12 100644 --- a/rogue_chat.html +++ b/rogue_chat.html @@ -479,29 +479,25 @@ let server = { let tokens = parser.tokenize(event.data); if (tokens[0] === 'TURN') { game.turn_complete = false; - 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); + let t = game.get_thing_temp(tokens[4], true); t.position = parser.parse_yx(tokens[1]); t.type_ = tokens[2]; t.protection = tokens[3]; t.portable = parseInt(tokens[5]); t.commandable = parseInt(tokens[6]); } else if (tokens[0] === 'THING_NAME') { - let t = game.get_thing(tokens[1], false); + let t = game.get_thing_temp(tokens[1]); t.name_ = tokens[2]; } else if (tokens[0] === 'THING_FACE') { - let t = game.get_thing(tokens[1], false); + let t = game.get_thing_temp(tokens[1]); t.face = tokens[2]; } else if (tokens[0] === 'THING_HAT') { - let t = game.get_thing(tokens[1], false); + let t = game.get_thing_temp(tokens[1]); t.hat = tokens[2]; } else if (tokens[0] === 'THING_CHAR') { - let t = game.get_thing(tokens[1], false); + let t = game.get_thing_temp(tokens[1]); t.thing_char = tokens[2]; } else if (tokens[0] === 'TASKS') { game.tasks = tokens[1].split(','); @@ -512,26 +508,36 @@ let server = { } else if (tokens[0] === 'THING_TYPE') { game.thing_types[tokens[1]] = tokens[2] } else if (tokens[0] === 'THING_CARRYING') { - let t = game.get_thing(tokens[1], false); + let t = game.get_thing_temp(tokens[1]); t.carrying = game.get_thing(tokens[2], false); } else if (tokens[0] === 'THING_INSTALLED') { - let t = game.get_thing(tokens[1], false); + let t = game.get_thing_temp(tokens[1]); t.installed = true; } else if (tokens[0] === 'TERRAIN') { game.terrains[tokens[1]] = tokens[2] } else if (tokens[0] === 'MAP') { - game.map_geometry = tokens[1]; + game.map_geometry_new = tokens[1]; tui.init_keys(); - game.map_size = parser.parse_yx(tokens[2]); - game.map = tokens[3] + game.map_size_new = parser.parse_yx(tokens[2]); + game.map_new = tokens[3] } else if (tokens[0] === 'FOV') { - game.fov = tokens[1] + game.fov_new = tokens[1] } else if (tokens[0] === 'MAP_CONTROL') { - game.map_control = tokens[1] + game.map_control_new = tokens[1] } else if (tokens[0] === 'GAME_STATE_COMPLETE') { game.turn_complete = true; - game.player = game.things[game.player_id]; + game.portals = game.portals_new; + game.portals_new = {}; + game.map_geometry = game.map_geometry_new; + game.map_size = game.map_size_new; + game.map = game.map_new; + game.map_control = game.map_control_new; + explorer.annotations = explorer.annotations_new; + explorer.annotations_new = {}; explorer.info_cached = false; + game.things = game.things_new; + game.things_new = []; + game.player = game.things[game.player_id]; if (tui.mode.name == 'post_login_wait') { tui.switch_mode('play'); } else { @@ -559,11 +565,10 @@ let server = { tui.switch_mode('admin'); } else if (tokens[0] === 'PORTAL') { let position = parser.parse_yx(tokens[1]); - game.portals[position] = tokens[2]; + game.portals_new[position] = tokens[2]; } else if (tokens[0] === 'ANNOTATION') { let position = parser.parse_yx(tokens[1]); - explorer.update_annotations(position, tokens[2]); - tui.full_refresh(); + explorer.annotations_new[position] = tokens[2]; } else if (tokens[0] === 'UNHANDLED_INPUT') { tui.log_msg('? unknown command'); } else if (tokens[0] === 'PLAY_ERROR') { @@ -1307,24 +1312,36 @@ let tui = { let game = { init: function() { - this.things = {}; this.turn = -1; + this.player_id = -1; + this.tasks = {}; + this.things = {}; + this.things_new = {}; + this.fov = ""; + this.fov_new = ""; this.map = ""; + this.map_new = ""; this.map_control = ""; + this.map_control_new = ""; this.map_size = [0,0]; - this.player_id = -1; + this.map_size_new = [0,0]; this.portals = {}; - this.tasks = {}; + this.portals_new = {}; }, - get_thing: function(id_, create_if_not_found=false) { - if (id_ in game.things) { - return game.things[id_]; + get_thing_temp: function(id_, create_if_not_found=false) { + if (id_ in game.things_new) { + return game.things_new[id_]; } else if (create_if_not_found) { let t = new Thing([0,0]); - game.things[id_] = t; + game.things_new[id_] = t; return t; }; }, + get_thing: function(id_, create_if_not_found=false) { + if (id_ in game.things) { + return game.things[id_]; + }; + }, move: function(start_position, direction) { let target = [start_position[0], start_position[1]]; if (direction == 'LEFT') { @@ -1385,6 +1402,7 @@ server.init(websocket_location); let explorer = { position: [0,0], annotations: {}, + annotations_new: {}, info_cached: false, move: function(direction) { let target = game.move(this.position, direction); @@ -1398,18 +1416,6 @@ let explorer = { terminal.blink_screen(); }; }, - update_annotations: function(yx, str) { - this.annotations[yx] = str; - if (tui.mode.name == 'study') { - tui.full_refresh(); - } - }, - empty_annotations: function() { - this.annotations = {}; - if (tui.mode.name == 'study') { - tui.full_refresh(); - } - }, get_info: function() { if (this.info_cached) { return this.info_cached; diff --git a/rogue_chat_curses.py b/rogue_chat_curses.py index 6bd662b..7145101 100755 --- a/rogue_chat_curses.py +++ b/rogue_chat_curses.py @@ -169,12 +169,8 @@ class PlomSocketClient(PlomSocket): pass # we assume socket will be known as dead by now def cmd_TURN(game, n): - 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): @@ -210,10 +206,10 @@ def cmd_PLAYER_ID(game, player_id): cmd_PLAYER_ID.argtypes = 'int:nonneg' def cmd_THING(game, yx, thing_type, protection, thing_id, portable, commandable): - t = game.get_thing(thing_id) + t = game.get_thing_temp(thing_id) if not t: t = ThingBase(game, thing_id) - game.things += [t] + game.things_new += [t] t.position = yx t.type_ = thing_type t.protection = protection @@ -222,29 +218,29 @@ def cmd_THING(game, yx, thing_type, protection, thing_id, portable, commandable) cmd_THING.argtypes = 'yx_tuple:nonneg string:thing_type char int:nonneg bool bool' def cmd_THING_NAME(game, thing_id, name): - t = game.get_thing(thing_id) + t = game.get_thing_temp(thing_id) t.name = name cmd_THING_NAME.argtypes = 'int:pos string' def cmd_THING_FACE(game, thing_id, face): - t = game.get_thing(thing_id) + t = game.get_thing_temp(thing_id) t.face = face cmd_THING_FACE.argtypes = 'int:pos string' def cmd_THING_HAT(game, thing_id, hat): - t = game.get_thing(thing_id) + t = game.get_thing_temp(thing_id) t.hat = hat cmd_THING_HAT.argtypes = 'int:pos string' def cmd_THING_CHAR(game, thing_id, c): - t = game.get_thing(thing_id) + t = game.get_thing_temp(thing_id) t.thing_char = c cmd_THING_CHAR.argtypes = 'int:pos char' def cmd_MAP(game, geometry, size, content): map_geometry_class = globals()['MapGeometry' + geometry] - game.map_geometry = map_geometry_class(size) - game.map_content = content + game.map_geometry_new = map_geometry_class(size) + game.map_content_new = content if type(game.map_geometry) == MapGeometrySquare: game.tui.movement_keys = { game.tui.keys['square_move_up']: 'UP', @@ -264,24 +260,34 @@ def cmd_MAP(game, geometry, size, content): cmd_MAP.argtypes = 'string:map_geometry yx_tuple:pos string' def cmd_FOV(game, content): - game.fov = content + game.fov_new = content cmd_FOV.argtypes = 'string' def cmd_MAP_CONTROL(game, content): - game.map_control_content = content + game.map_control_content_new = content cmd_MAP_CONTROL.argtypes = 'string' def cmd_GAME_STATE_COMPLETE(game): game.turn_complete = True game.tui.do_refresh = True game.tui.info_cached = None + game.things = game.things_new + game.things_new = [] + game.portals = game.portals_new + game.portals_new = {} + game.annotations = game.annotations_new + game.annotations_new = {} + game.fov = game.fov_new + game.map_geometry = game.map_geometry_new + game.map_content = game.map_content_new + game.map_control_content = game.map_control_content_new game.player = game.get_thing(game.player_id) if game.tui.mode.name == 'post_login_wait': game.tui.switch_mode('play') cmd_GAME_STATE_COMPLETE.argtypes = '' def cmd_PORTAL(game, position, msg): - game.portals[position] = msg + game.portals_new[position] = msg cmd_PORTAL.argtypes = 'yx_tuple:nonneg string' def cmd_PLAY_ERROR(game, msg): @@ -301,7 +307,7 @@ def cmd_ARGUMENT_ERROR(game, msg): cmd_ARGUMENT_ERROR.argtypes = 'string' def cmd_ANNOTATION(game, position, msg): - game.annotations[position] = msg + game.annotations_new[position] = msg if game.tui.mode.shows_info: game.tui.do_refresh = True cmd_ANNOTATION.argtypes = 'yx_tuple:nonneg string' @@ -319,11 +325,11 @@ def cmd_THING_TYPE(game, thing_type, symbol_hint): cmd_THING_TYPE.argtypes = 'string char' def cmd_THING_INSTALLED(game, thing_id): - game.get_thing(thing_id).installed = True + game.get_thing_temp(thing_id).installed = True cmd_THING_INSTALLED.argtypes = 'int:pos' def cmd_THING_CARRYING(game, thing_id, carried_id): - game.get_thing(thing_id).carrying = game.get_thing(carried_id) + game.get_thing_temp(thing_id).carrying = game.get_thing(carried_id) cmd_THING_CARRYING.argtypes = 'int:pos int:pos' def cmd_TERRAIN(game, terrain_char, terrain_desc): @@ -346,6 +352,7 @@ class Game(GameBase): turn_complete = False tasks = {} thing_types = {} + things_new = [] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -381,7 +388,9 @@ class Game(GameBase): self.map_content = '' self.player_id = -1 self.annotations = {} + self.annotations_new = {} self.portals = {} + self.portals_new = {} self.terrains = {} self.player = None @@ -398,6 +407,12 @@ class Game(GameBase): f.argtypes = self.commands[command_name].argtypes return f + def get_thing_temp(self, id_): + for thing in self.things_new: + if id_ == thing.id_: + return thing + return None + class Mode: def __init__(self, name, has_input_prompt=False, shows_info=False, @@ -893,7 +908,7 @@ class TUI: 'MODE: %s – %s' % (self.mode.short_desc, help)) def draw_map(): - if not self.game.turn_complete and len(self.map_lines) == 0: + if (not self.game.turn_complete) and len(self.map_lines) == 0: return if self.game.turn_complete: map_lines_split = [] -- 2.30.2