From e6a3ab3471ae5a2be10bd64d694eef462d7f7cf6 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Fri, 27 Nov 2020 01:21:03 +0100 Subject: [PATCH] Add thing protection. --- config.json | 1 + plomrogue/commands.py | 27 +++++++++++++++++++++++++-- plomrogue/game.py | 10 +++++++++- plomrogue/things.py | 1 + rogue_chat.html | 39 ++++++++++++++++++++++++++++++++++----- rogue_chat.py | 3 +++ rogue_chat_curses.py | 40 ++++++++++++++++++++++++++++++++-------- 7 files changed, 105 insertions(+), 16 deletions(-) diff --git a/config.json b/config.json index 406f461..15022fe 100644 --- a/config.json +++ b/config.json @@ -11,6 +11,7 @@ "switch_to_admin": "A", "switch_to_control_pw_pw": "C", "switch_to_control_tile_type": "Q", + "switch_to_admin_thing_protect": "T", "flatten": "F", "take_thing": "z", "drop_thing": "u", diff --git a/plomrogue/commands.py b/plomrogue/commands.py index a2f98ed..3a10a4c 100644 --- a/plomrogue/commands.py +++ b/plomrogue/commands.py @@ -118,6 +118,19 @@ def cmd_SET_TILE_CONTROL(game, yx, control_char, connection_id): game.changed = True cmd_SET_TILE_CONTROL.argtypes = 'yx_tuple:nonneg char' +def cmd_THING_PROTECTION(game, thing_id, protection_char, connection_id): + player = game.get_player(connection_id) + if not player: + raise GameError('need to be logged in for this') + if not game.sessions[connection_id]['status'] == 'admin': + raise GameError('need to be admin for this') + t = game.get_thing(thing_id) + if not t: + raise GameError('thing of ID %s not found' % thing_id) + t.protection = protection_char + game.changed = True +cmd_THING_PROTECTION.argtypes = 'int:pos char' + def cmd_SET_MAP_CONTROL_PASSWORD(game, tile_class, password, connection_id): player = game.get_player(connection_id) if not player: @@ -269,13 +282,16 @@ def cmd_THING(game, big_yx, little_yx, thing_type, thing_id): game.changed = True cmd_THING.argtypes = 'yx_tuple yx_tuple:nonneg string:thing_type int:nonneg' -def cmd_THING_NAME(game, thing_id, name, connection_id): +def cmd_THING_NAME(game, thing_id, name, pw, connection_id): + # TODO check if thing in FOV t = game.get_thing(thing_id) if not t: raise GameError('thing of ID %s not found' % thing_id) + if not game.can_do_thing_with_pw(t, pw): + raise GameError('wrong password for tile') t.name = name game.changed = True -cmd_THING_NAME.argtypes = 'int:pos string' +cmd_THING_NAME.argtypes = 'int:pos string string' def cmd_GOD_THING_NAME(game, thing_id, name): t = game.get_thing(thing_id) @@ -283,3 +299,10 @@ def cmd_GOD_THING_NAME(game, thing_id, name): raise GameError('thing of ID %s not found' % thing_id) t.name = name cmd_GOD_THING_NAME.argtypes = 'int:pos string' + +def cmd_GOD_THING_PROTECTION(game, thing_id, protection_char): + t = game.get_thing(thing_id) + if not t: + raise GameError('thing of ID %s not found' % thing_id) + t.protection = protection_char +cmd_GOD_THING_PROTECTION.argtypes = 'int:pos char' diff --git a/plomrogue/game.py b/plomrogue/game.py index 49fdeeb..f504599 100755 --- a/plomrogue/game.py +++ b/plomrogue/game.py @@ -159,6 +159,12 @@ class Game(GameBase): print("FILE INPUT LINE %5s: %s" % (i, line), end='') self.io.handle_input(line, god_mode=True) + def can_do_thing_with_pw(self, thing, pw): + if thing.protection in self.map_control_passwords.keys(): + if pw != self.map_control_passwords[thing.protection]: + return False + return True + def can_do_tile_with_pw(self, big_yx, little_yx, pw): map_control = self.get_map(big_yx, 'control') tile_class = map_control[little_yx] @@ -204,7 +210,8 @@ class Game(GameBase): self.io.send('MAP_CONTROL %s' % quote(visible_control), c_id) for t in [t for t in self.things if player.fov_test(*t.position)]: target_yx = player.fov_stencil.target_yx(*t.position) - self.io.send('THING %s %s %s' % (target_yx, t.type_, t.id_), c_id) + self.io.send('THING %s %s %s %s' % (target_yx, t.type_, + quote(t.protection), t.id_), c_id) if hasattr(t, 'name'): self.io.send('THING_NAME %s %s' % (t.id_, quote(t.name)), c_id) if hasattr(t, 'player_char'): @@ -333,6 +340,7 @@ class Game(GameBase): for t in [t for t in self.things if not t.type_ == 'Player']: write(f, 'THING %s %s %s %s' % (t.position[0], t.position[1], t.type_, t.id_)) + write(f, 'GOD_THING_PROTECTION %s %s' % (t.id_, quote(t.protection))) if hasattr(t, 'name'): write(f, 'GOD_THING_NAME %s %s' % (t.id_, quote(t.name))) write(f, 'SPAWN_POINT %s %s' % (self.spawn_point[0], diff --git a/plomrogue/things.py b/plomrogue/things.py index 0edf8fb..1618ee6 100644 --- a/plomrogue/things.py +++ b/plomrogue/things.py @@ -18,6 +18,7 @@ class ThingBase: class Thing(ThingBase): blocking = False + protection = '.' def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/rogue_chat.html b/rogue_chat.html index d2136df..15b715a 100644 --- a/rogue_chat.html +++ b/rogue_chat.html @@ -72,6 +72,7 @@ keyboard input/control: + @@ -104,6 +105,7 @@ keyboard input/control:
  • +
  • toggle map view: @@ -131,6 +133,10 @@ let mode_helps = { 'short': 'name thing', 'long': 'Give name to/change name of thing here.' }, + 'admin_thing_protect': { + 'short': 'change thing protection', + 'long': 'Change protection character for thing here.' + }, 'write': { 'short': 'change terrain', 'long': 'This mode allows you to change the map tile you currently stand on (if your map editing password authorizes you so). Just enter any printable ASCII character to imprint it on the ground below you.' @@ -386,9 +392,10 @@ let server = { game.portals = {}; game.turn = parseInt(tokens[1]); } else if (tokens[0] === 'THING') { - let t = game.get_thing(tokens[3], true); + let t = game.get_thing(tokens[4], true); t.position = parser.parse_yx(tokens[1]); t.type_ = tokens[2]; + t.protection = tokens[3]; } else if (tokens[0] === 'THING_NAME') { let t = game.get_thing(tokens[1], false); if (t) { @@ -554,6 +561,7 @@ let tui = { mode_write: new Mode('write', false, false, false, true), mode_edit: new Mode('edit'), mode_control_pw_type: new Mode('control_pw_type', true), + mode_admin_thing_protect: new Mode('admin_thing_protect', true), mode_portal: new Mode('portal', true, true), mode_password: new Mode('password', true), mode_name_thing: new Mode('name_thing', true, true), @@ -565,7 +573,7 @@ let tui = { init: function() { this.mode_play.available_modes = ["chat", "study", "edit", "admin_enter"] this.mode_study.available_modes = ["chat", "play", "admin_enter", "edit"] - this.mode_admin.available_modes = ["control_pw_type", + this.mode_admin.available_modes = ["admin_thing_protect", "control_pw_type", "control_tile_type", "chat", "study", "play", "edit"] this.mode_control_tile_draw.available_modes = ["admin_enter"] @@ -622,7 +630,7 @@ let tui = { this.tile_draw = false; if (mode_name == 'admin_enter' && this.is_admin) { mode_name = 'admin'; - } else if (mode_name == 'name_thing') { + } else if (['name_thing', 'admin_thing_protect'].includes(mode_name)) { let player_position = game.things[game.player_id].position; let thing_id = null; for (let t_id in game.things) { @@ -713,6 +721,7 @@ let tui = { } else if (this.mode.name == 'admin') { document.getElementById("switch_to_control_pw_type").disabled = false; document.getElementById("switch_to_control_tile_type").disabled = false; + document.getElementById("switch_to_admin_thing_protect").disabled = false; } else if (this.mode.name == 'study') { document.getElementById("toggle_map_mode").disabled = false; } else if (this.mode.is_single_char_entry) { @@ -723,6 +732,8 @@ let tui = { this.log_msg('@ enter tile protection character for which you want to change the password:') } else if (this.mode.name == 'control_tile_type') { this.log_msg('@ enter tile protection character which you want to draw:') + } else if (this.mode.name == 'admin_thing_protect') { + this.log_msg('@ enter thing protection character:') } else if (this.mode.name == 'control_pw_pw') { this.log_msg('@ enter tile protection password for "' + this.tile_control_char + '":'); } else if (this.mode.name == 'control_tile_draw') { @@ -759,6 +770,11 @@ let tui = { if (t && t.name_) { this.inputEl.value = t.name_; } + } else if (this.mode.name == 'admin_thing_protect') { + let t = game.get_thing(this.selected_thing_id); + if (t && t.protection) { + this.inputEl.value = t.protection; + } } }, recalc_input_lines: function() { @@ -1206,7 +1222,11 @@ let explorer = { 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_]; - info += "THING: " + t.type_ + " / " + symbol; + let protection = t.protection; + if (protection == '.') { + protection = 'unprotected'; + } + info += "THING: " + t.type_ + " / protection: " + protection + " / " + symbol; if (t.player_char) { info += t.player_char; }; @@ -1290,7 +1310,8 @@ tui.inputEl.addEventListener('keydown', (event) => { if (tui.inputEl.value.length == 0) { tui.inputEl.value = " "; } - server.send(["THING_NAME", tui.selected_thing_id, tui.inputEl.value]); + server.send(["THING_NAME", tui.selected_thing_id, tui.inputEl.value, + tui.password]); tui.switch_mode('edit'); } else if (tui.mode.name == 'annotate' && event.key == 'Enter') { explorer.annotate(tui.inputEl.value); @@ -1320,6 +1341,14 @@ tui.inputEl.addEventListener('keydown', (event) => { tui.tile_control_char = tui.inputEl.value[0]; tui.switch_mode('control_tile_draw'); } + } else if (tui.mode.name == 'admin_thing_protect' && event.key == 'Enter') { + if (tui.inputEl.value.length != 1) { + tui.log_msg('@ entered non-single-char, therefore aborted'); + } else { + server.send(['THING_PROTECTION', tui.selected_thing_id, tui.inputEl.value]) + tui.log_msg('@ sent new protection character for thing'); + } + tui.switch_mode('admin'); } else if (tui.mode.name == 'chat' && event.key == 'Enter') { let tokens = parser.tokenize(tui.inputEl.value); if (tokens.length > 0 && tokens[0].length > 0) { diff --git a/rogue_chat.py b/rogue_chat.py index abdd027..5c5e657 100755 --- a/rogue_chat.py +++ b/rogue_chat.py @@ -8,6 +8,7 @@ from plomrogue.commands import (cmd_ALL, cmd_LOGIN, cmd_NICK, cmd_PING, cmd_THIN cmd_THING_NAME, cmd_TERRAINS, cmd_ADMIN_PASSWORD, cmd_BECOME_ADMIN, cmd_SET_TILE_CONTROL, cmd_GOD_THING_NAME, + cmd_GOD_THING_PROTECTION, cmd_THING_PROTECTION, cmd_SET_MAP_CONTROL_PASSWORD, cmd_SPAWN_POINT) from plomrogue.tasks import (Task_WAIT, Task_MOVE, Task_WRITE, Task_PICK_UP, Task_DROP, Task_FLATTEN_SURROUNDINGS) @@ -34,6 +35,8 @@ game.register_command(cmd_TASKS) game.register_command(cmd_THING_TYPES) game.register_command(cmd_TERRAINS) game.register_command(cmd_THING) +game.register_command(cmd_THING_PROTECTION) +game.register_command(cmd_GOD_THING_PROTECTION) game.register_command(cmd_THING_NAME) game.register_command(cmd_GOD_THING_NAME) game.register_command(cmd_ADMIN_PASSWORD) diff --git a/rogue_chat_curses.py b/rogue_chat_curses.py index 7ffee57..5ad366a 100755 --- a/rogue_chat_curses.py +++ b/rogue_chat_curses.py @@ -27,6 +27,10 @@ mode_helps = { 'short': 'name thing', 'long': 'Give name to/change name of thing here.' }, + 'admin_thing_protect': { + 'short': 'change thing protection', + 'long': 'Change protection character for thing here.' + }, 'write': { 'short': 'change terrain', 'long': 'This mode allows you to change the map tile you currently stand on (if your map editing password authorizes you so). Just enter any printable ASCII character to imprint it on the ground below you.' @@ -156,14 +160,15 @@ def cmd_PLAYER_ID(game, player_id): game.player_id = player_id cmd_PLAYER_ID.argtypes = 'int:nonneg' -def cmd_THING(game, yx, thing_type, thing_id): +def cmd_THING(game, yx, thing_type, protection, thing_id): t = game.get_thing(thing_id) if not t: t = ThingBase(game, thing_id) game.things += [t] t.position = yx t.type_ = thing_type -cmd_THING.argtypes = 'yx_tuple:nonneg string:thing_type int:nonneg' + t.protection = protection +cmd_THING.argtypes = 'yx_tuple:nonneg string:thing_type char int:nonneg' def cmd_THING_NAME(game, thing_id, name): t = game.get_thing(thing_id) @@ -360,6 +365,7 @@ class TUI: mode_control_pw_pw = Mode('control_pw_pw', has_input_prompt=True) mode_control_tile_type = Mode('control_tile_type', has_input_prompt=True) mode_control_tile_draw = Mode('control_tile_draw') + mode_admin_thing_protect = Mode('admin_thing_protect', has_input_prompt=True) mode_annotate = Mode('annotate', has_input_prompt=True, shows_info=True) mode_portal = Mode('portal', has_input_prompt=True, shows_info=True) mode_chat = Mode('chat', has_input_prompt=True) @@ -376,7 +382,7 @@ class TUI: import json self.mode_play.available_modes = ["chat", "study", "edit", "admin_enter"] self.mode_study.available_modes = ["chat", "play", "admin_enter", "edit"] - self.mode_admin.available_modes = ["control_pw_type", + self.mode_admin.available_modes = ["admin_thing_protect", "control_pw_type", "control_tile_type", "chat", "study", "play", "edit"] self.mode_control_tile_draw.available_modes = ["admin_enter"] @@ -408,6 +414,7 @@ class TUI: 'switch_to_admin_enter': 'A', 'switch_to_control_pw_type': 'C', 'switch_to_control_tile_type': 'Q', + 'switch_to_admin_thing_protect': 'T', 'flatten': 'F', 'take_thing': 'z', 'drop_thing': 'u', @@ -508,6 +515,9 @@ class TUI: elif self.mode.name == 'name_thing': if hasattr(self.thing_selected, 'name'): self.input_ = self.thing_selected.name + elif self.mode.name == 'admin_thing_protect': + if hasattr(self.thing_selected, 'protection'): + self.input_ = self.thing_selected.protection def send_tile_control_command(self): self.send('SET_TILE_CONTROL %s %s' % @@ -527,7 +537,7 @@ class TUI: self.tile_draw = False if mode_name == 'admin_enter' and self.is_admin: mode_name = 'admin' - elif mode_name == 'name_thing': + elif mode_name in {'name_thing', 'admin_thing_protect'}: player = self.game.get_thing(self.game.player_id) thing = None for t in [t for t in self.game.things if t.position == player.position @@ -568,6 +578,8 @@ class TUI: self.log_msg('@ enter tile protection character for which you want to change the password:') elif self.mode.name == 'control_tile_type': self.log_msg('@ enter tile protection character which you want to draw:') + elif self.mode.name == 'admin_thing_protect': + self.log_msg('@ enter thing protection character:') elif self.mode.name == 'control_pw_pw': self.log_msg('@ enter tile protection password for "%s":' % self.tile_control_char) elif self.mode.name == 'control_tile_draw': @@ -665,8 +677,11 @@ class TUI: info += 'PROTECTION: %s\n' % protection for t in self.game.things: if t.position == self.explorer: - info += 'THING: %s / %s' % (t.type_, - self.game.thing_types[t.type_]) + protection = t.protection + if protection == '.': + protection = 'unprotected' + info += 'THING: %s / protection: %s / %s' %\ + (t.type_, protection, self.game.thing_types[t.type_]) if hasattr(t, 'player_char'): info += t.player_char if hasattr(t, 'name'): @@ -915,6 +930,14 @@ class TUI: else: self.tile_control_char = self.input_ self.switch_mode('control_pw_pw') + elif self.mode.name == 'admin_thing_protect' and key == '\n': + if len(self.input_) != 1: + self.log_msg('@ entered non-single-char, therefore aborted') + else: + self.send('THING_PROTECTION %s %s' % (self.thing_selected.id_, + quote(self.input_))) + self.log_msg('@ sent new protection character for thing') + self.switch_mode('admin') elif self.mode.name == 'control_tile_type' and key == '\n': if len(self.input_) != 1: self.log_msg('@ entered non-single-char, therefore aborted') @@ -948,8 +971,9 @@ class TUI: elif self.mode.name == 'name_thing' and key == '\n': if self.input_ == '': self.input_ = ' ' - self.send('THING_NAME %s %s' % (self.thing_selected.id_, - quote(self.input_))) + self.send('THING_NAME %s %s %s' % (self.thing_selected.id_, + quote(self.input_), + quote(self.password))) self.switch_mode('edit') elif self.mode.name == 'annotate' and key == '\n': if self.input_ == '': -- 2.30.2