From 1f65215b70d2a8a255aa9327497b88b94c4b1f17 Mon Sep 17 00:00:00 2001 From: Christian Heller <c.heller@plomlompom.de> Date: Wed, 25 Nov 2020 01:04:18 +0100 Subject: [PATCH] Put admin stuff into dedicated admin mode. --- plomrogue/commands.py | 1 + rogue_chat.html | 77 ++++++++++++++++++++++++++++++------------- rogue_chat_curses.py | 45 ++++++++++++++++++------- 3 files changed, 90 insertions(+), 33 deletions(-) diff --git a/plomrogue/commands.py b/plomrogue/commands.py index 41509df..c0470ba 100644 --- a/plomrogue/commands.py +++ b/plomrogue/commands.py @@ -98,6 +98,7 @@ def cmd_BECOME_ADMIN(game, password, connection_id): raise GameError('need to be logged in for this') if password in game.admin_passwords: game.sessions[connection_id]['status'] = 'admin' + game.io.send('ADMIN_OK', connection_id) else: raise GameError('wrong password') cmd_BECOME_ADMIN.argtypes = 'string' diff --git a/rogue_chat.html b/rogue_chat.html index 59d03a9..cf82cf9 100644 --- a/rogue_chat.html +++ b/rogue_chat.html @@ -42,33 +42,41 @@ terminal columns: <input id="n_cols" type="number" step=4 min=80 value=80 /> <tr> <td><button id="switch_to_chat">chat mode</button><br /></td> </tr> + <tr> <td><button id="switch_to_study">study mode</button></td> <td><button id="toggle_map_mode">toggle terrain/annotations/control view</button> + </tr> <tr> <td><button id="switch_to_play">play mode</button></td> <td> <table> <tr> <td><button id="take_thing">take thing</button></td> + <td><button id="switch_to_annotate">annotate tile</button></td> <td><button id="switch_to_edit">change tile</button></td> - <td><button id="switch_to_admin">become admin</button></td> + <td><button id="teleport">teleport</button></td> </tr> <tr> <td><button id="drop_thing">drop thing</button></td> + <td><button id="flatten">flatten surroundings</button></td> <td><button id="switch_to_password">change tile editing password</button></td> - <td><button id="switch_to_control_pw_type">change tile control password</button></td> + <td><button id="switch_to_portal">edit portal link</button></td> </tr> + </table> + </td> + </tr> + <td><button id="switch_to_admin_enter">admin mode</button></td> + <td> + <table> <tr> - <td><button id="flatten">flatten surroundings</button></td> - <td><button id="switch_to_annotate">annotate tile</button></td> - <td><button id="switch_to_control_tile_type">change tiles control</button></td> + <td><button id="switch_to_control_pw_type">change tile control password</button></td> </tr> <tr> - <td><button id="teleport">teleport</button></td> - <td><button id="switch_to_portal">edit portal link</button></td> + <td><button id="switch_to_control_tile_type">change tiles control</button></td> </tr> </table> </td> + <tr> </tr> </table> <h3>edit keybindings</h3> (see <a href="https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values">here</a> for non-obvious available values):<br /> @@ -93,7 +101,7 @@ terminal columns: <input id="n_cols" type="number" step=4 min=80 value=80 /> <li><input id="key_switch_to_study" type="text" value="?" /> <li><input id="key_switch_to_edit" type="text" value="m" /> <li><input id="key_switch_to_password" type="text" value="P" /> -<li><input id="key_switch_to_admin" type="text" value="A" /> +<li><input id="key_switch_to_admin_enter" type="text" value="A" /> <li><input id="key_switch_to_control_pw_type" type="text" value="C" /> <li><input id="key_switch_to_control_tile_type" type="text" value="Q" /> <li><input id="key_switch_to_annotate" type="text" value="M" /> @@ -103,8 +111,8 @@ terminal columns: <input id="n_cols" type="number" step=4 min=80 value=80 /> </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:8000/"; let mode_helps = { 'play': { @@ -162,9 +170,13 @@ let mode_helps = { 'short': 'map edit password', 'long': 'This mode allows you to change the password that you send to authorize yourself for editing password-protected map tiles. Hit return to confirm and leave.' }, - 'admin': { + 'admin_enter': { 'short': 'become admin', 'long': 'This mode allows you to become admin if you know an admin password.' + }, + 'admin': { + 'short': 'admin', + 'long': 'This mode allows you access to actions limited to administrators.' } } @@ -409,6 +421,10 @@ let server = { } else if (tokens[0] === 'LOGIN_OK') { this.send(['GET_GAMESTATE']); tui.switch_mode('post_login_wait'); + } else if (tokens[0] === 'ADMIN_OK') { + tui.is_admin = true; + tui.log_msg('@ you now have admin rights'); + tui.switch_mode('admin'); } else if (tokens[0] === 'PORTAL') { let position = parser.parse_yx(tokens[1]); game.portals[position] = tokens[2]; @@ -517,6 +533,7 @@ let tui = { height_input: 1, password: 'foo', show_help: false, + is_admin: false, mode_waiting_for_server: new Mode('waiting_for_server', false, false, true), mode_login: new Mode('login', true, false, true), @@ -530,7 +547,8 @@ let tui = { false, false, false, true), mode_portal: new Mode('portal', true, true), mode_password: new Mode('password', true), - mode_admin: new Mode('admin', true), + mode_admin_enter: new Mode('admin_enter', true), + mode_admin: new Mode('admin'), mode_control_pw_pw: new Mode('control_pw_pw', true), mode_control_tile_type: new Mode('control_tile_type', false, false, false, true), @@ -538,11 +556,12 @@ let tui = { init: function() { this.mode_play.available_modes = ["chat", "study", "edit", "annotate", "portal", - "password", "admin", - "control_pw_type", - "control_tile_type"] - this.mode_study.available_modes = ["chat", "play"] - this.mode_control_tile_draw.available_modes = ["play"] + "password", "admin_enter"]; + this.mode_study.available_modes = ["chat", "play", "admin_enter"]; + this.mode_admin.available_modes = ["chat", "play", "study", + "control_pw_type", + "control_tile_type"]; + this.mode_control_tile_draw.available_modes = ["admin_enter"]; this.mode = this.mode_waiting_for_server; this.inputEl = document.getElementById("input"); this.inputEl.focus(); @@ -589,6 +608,9 @@ let tui = { switch_mode: function(mode_name) { this.inputEl.focus(); this.map_mode = 'terrain'; + if (mode_name == 'admin_enter' && this.is_admin) { + mode_name = 'admin'; + }; this.mode = this['mode_' + mode_name]; 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; @@ -619,6 +641,9 @@ let tui = { if (!this.mode.is_intro && this.mode.name != 'chat') { document.getElementById("switch_to_chat").disabled = false; } + if (!this.mode.is_intro && this.mode.name != 'admin' && this.mode.name != 'admin_enter') { + document.getElementById("switch_to_admin_enter").disabled = false; + } if (this.mode.name == 'login') { if (this.login_name) { server.send(['LOGIN', this.login_name]); @@ -642,14 +667,15 @@ let tui = { document.getElementById("switch_to_edit").disabled = false; document.getElementById("switch_to_portal").disabled = false; document.getElementById("switch_to_password").disabled = false; - document.getElementById("switch_to_admin").disabled = false; + document.getElementById("switch_to_admin_enter").disabled = false; + } else if (this.mode.name == 'admin') { document.getElementById("switch_to_control_pw_type").disabled = false; document.getElementById("switch_to_control_tile_type").disabled = false; } else if (this.mode.name == 'study') { document.getElementById("toggle_map_mode").disabled = false; } else if (this.mode.is_single_char_entry) { this.show_help = true; - } else if (this.mode.name == 'admin') { + } else if (this.mode.name == 'admin_enter') { this.log_msg('@ enter admin password:') } else if (this.mode.name == 'control_pw_pw') { this.log_msg('@ enter tile control password for "' + this.tile_control_char + '":'); @@ -927,6 +953,7 @@ let tui = { content += '/nick NAME â re-name yourself to NAME\n'; content += '/' + this.keys.switch_to_play + ' or /play â switch to play mode\n'; content += '/' + this.keys.switch_to_study + ' or /study â switch to study mode\n'; + content += '/' + this.keys.switch_to_admin_enter + ' or /admin â switch to admin mode\n'; } content += this.mode.list_available_modes(); let start_x = 0; @@ -1176,7 +1203,7 @@ tui.inputEl.addEventListener('keydown', (event) => { server.send(['SET_MAP_CONTROL_PASSWORD', tui.tile_control_char, tui.inputEl.value]); } - tui.switch_mode('play'); + tui.switch_mode('admin'); } else if (tui.mode.name == 'portal' && event.key == 'Enter') { explorer.set_portal(tui.inputEl.value); tui.switch_mode('play'); @@ -1189,7 +1216,7 @@ tui.inputEl.addEventListener('keydown', (event) => { } tui.password = tui.inputEl.value tui.switch_mode('play'); - } else if (tui.mode.name == 'admin' && event.key == 'Enter') { + } else if (tui.mode.name == 'admin_enter' && event.key == 'Enter') { server.send(['BECOME_ADMIN', tui.inputEl.value]); tui.switch_mode('play'); } else if (tui.mode.name == 'chat' && event.key == 'Enter') { @@ -1200,6 +1227,8 @@ tui.inputEl.addEventListener('keydown', (event) => { tui.switch_mode('play'); } else if (tokens[0].slice(1) == 'study' || tokens[0][1] == tui.keys.switch_to_study) { tui.switch_mode('study'); + } else if (tokens[0].slice(1) == 'admin' || tokens[0][1] == tui.keys.switch_to_admin_enter) { + tui.switch_mode('admin_enter'); } else if (tokens[0].slice(1) == 'nick') { if (tokens.length > 1) { server.send(['NICK', tokens[1]]); @@ -1260,6 +1289,10 @@ tui.inputEl.addEventListener('keydown', (event) => { } else if (event.key in tui.movement_keys) { explorer.move(tui.movement_keys[event.key]); }; + } else if (tui.mode.name == 'admin') { + if (tui.mode.mode_switch_on_key(event)) { + null; + }; } tui.full_refresh(); }, false); @@ -1330,7 +1363,7 @@ document.getElementById("switch_to_portal").onclick = function() { tui.switch_mode('portal'); tui.full_refresh(); }; -document.getElementById("switch_to_admin").onclick = function() { +document.getElementById("switch_to_admin_enter").onclick = function() { tui.switch_mode('admin'); tui.full_refresh(); }; diff --git a/rogue_chat_curses.py b/rogue_chat_curses.py index 2362d99..3cd5914 100755 --- a/rogue_chat_curses.py +++ b/rogue_chat_curses.py @@ -67,9 +67,13 @@ mode_helps = { 'short': 'map edit password', 'long': 'This mode allows you to change the password that you send to authorize yourself for editing password-protected map tiles. Hit return to confirm and leave.' }, - 'admin': { + 'admin_enter': { 'short': 'become admin', 'long': 'This mode allows you to become admin if you know an admin password.' + }, + 'admin': { + 'short': 'admin', + 'long': 'This mode allows you access to actions limited to administrators.' } } @@ -128,6 +132,13 @@ def cmd_LOGIN_OK(game): game.tui.log_msg('@ welcome') cmd_LOGIN_OK.argtypes = '' +def cmd_ADMIN_OK(game): + game.tui.is_admin = True + game.tui.log_msg('@ you now have admin rights') + game.tui.switch_mode('admin') + game.tui.do_refresh = True +cmd_ADMIN_OK.argtypes = '' + def cmd_CHAT(game, msg): game.tui.log_msg('# ' + msg) game.tui.do_refresh = True @@ -253,6 +264,7 @@ class Game(GameBase): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.register_command(cmd_LOGIN_OK) + self.register_command(cmd_ADMIN_OK) self.register_command(cmd_PONG) self.register_command(cmd_CHAT) self.register_command(cmd_PLAYER_ID) @@ -331,7 +343,8 @@ class Mode: return False class TUI: - mode_admin = Mode('admin', has_input_prompt=True) + mode_admin_enter = Mode('admin_enter', has_input_prompt=True) + mode_admin = Mode('admin') mode_play = Mode('play') mode_study = Mode('study', shows_info=True) mode_edit = Mode('edit', is_single_char_entry=True) @@ -346,17 +359,19 @@ class TUI: mode_login = Mode('login', has_input_prompt=True, is_intro=True) mode_post_login_wait = Mode('post_login_wait', is_intro=True) mode_password = Mode('password', has_input_prompt=True) + is_admin = False def __init__(self, host): import os import json self.mode_play.available_modes = ["chat", "study", "edit", "annotate", "portal", - "password", "admin", - "control_pw_type", - "control_tile_type"] - self.mode_study.available_modes = ["chat", "play"] - self.mode_control_tile_draw.available_modes = ["play"] + "password", "admin_enter"] + self.mode_study.available_modes = ["chat", "play", "admin_enter"] + self.mode_admin.available_modes = ["chat", "play", "study", + "control_pw_type", + "control_tile_type"] + self.mode_control_tile_draw.available_modes = ["admin"] self.host = host self.game = Game() self.game.tui = self @@ -376,7 +391,7 @@ class TUI: 'switch_to_portal': 'T', 'switch_to_study': '?', 'switch_to_edit': 'm', - 'switch_to_admin': 'A', + 'switch_to_admin_enter': 'A', 'switch_to_control_pw_type': 'C', 'switch_to_control_tile_type': 'Q', 'flatten': 'F', @@ -481,6 +496,8 @@ class TUI: def switch_mode(self, mode_name): self.map_mode = 'terrain' + if mode_name == 'admin_enter' and self.is_admin: + mode_name = 'admin' self.mode = getattr(self, 'mode_' + mode_name) if self.mode.shows_info or self.mode.name == 'control_tile_draw': player = self.game.get_thing(self.game.player_id) @@ -499,7 +516,7 @@ class TUI: self.send('LOGIN ' + quote(self.login_name)) else: self.log_msg('@ enter username') - elif self.mode.name == 'admin': + elif self.mode.name == 'admin_enter': self.log_msg('@ enter admin password:') elif self.mode.name == 'control_pw_pw': self.log_msg('@ enter tile control password for "%s":' % self.tile_control_char) @@ -716,6 +733,7 @@ class TUI: content += '/nick NAME â re-name yourself to NAME\n' content += '/%s or /play â switch to play mode\n' % self.keys['switch_to_play'] content += '/%s or /study â switch to study mode\n' % self.keys['switch_to_study'] + content += '/%s or /admin â switch to admin mode\n' % self.keys['switch_to_admin_enter'] content += self.mode.list_available_modes(self) for i in range(self.size.y): safe_addstr(i, @@ -810,14 +828,14 @@ class TUI: else: self.send('SET_MAP_CONTROL_PASSWORD ' + quote(self.tile_control_char) + ' ' + quote(self.input_)) self.input_ = "" - self.switch_mode('play') + self.switch_mode('admin') elif self.mode.name == 'password' and key == '\n': if self.input_ == '': self.input_ = ' ' self.password = self.input_ self.input_ = "" self.switch_mode('play') - elif self.mode.name == 'admin' and key == '\n': + elif self.mode.name == 'admin_enter' and key == '\n': self.send('BECOME_ADMIN ' + quote(self.input_)) self.input_ = "" self.switch_mode('play') @@ -829,6 +847,8 @@ class TUI: self.switch_mode('play') elif self.input_ in {'/' + self.keys['switch_to_study'], '/study'}: self.switch_mode('study') + elif self.input_ in {'/' + self.keys['switch_to_admin_enter'], '/admin'}: + self.switch_mode('admin_enter') elif self.input_.startswith('/nick'): tokens = self.input_.split(maxsplit=1) if len(tokens) == 2: @@ -900,6 +920,9 @@ class TUI: continue elif key in self.movement_keys: move_explorer(self.movement_keys[key]) + elif self.mode.name == 'admin': + if self.mode.mode_switch_on_key(self, key): + continue if len(sys.argv) != 2: raise ArgError('wrong number of arguments, need game host') -- 2.30.2