home · contact · privacy
Add editable player faces.
authorChristian Heller <c.heller@plomlompom.de>
Mon, 7 Dec 2020 04:26:35 +0000 (05:26 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Mon, 7 Dec 2020 04:26:35 +0000 (05:26 +0100)
config.json
plomrogue/commands.py
plomrogue/game.py
rogue_chat.html
rogue_chat.py
rogue_chat_curses.py

index a7a51ad30668a0b71d039ce193319cde88844d08..7b26b539bfced13b535065a4b42751fee9dc75f1 100644 (file)
@@ -14,6 +14,7 @@
     "switch_to_control_tile_type": "Q",
     "switch_to_admin_thing_protect": "T",
     "flatten": "F",
+    "switch_to_enter_face": "f",
     "switch_to_take_thing": "z",
     "drop_thing": "u",
     "teleport": "p",
index daa43576cd7181ed4e285e3a389abf7dce0b5bbd..0ccbdc1cb50ef3b646474e1d165fe0a4444ea701 100644 (file)
@@ -313,3 +313,17 @@ def cmd_THING_INSTALLED(game, thing_id):
         raise GameError('thing of ID %s not installable' % thing_id)
     t.install()
 cmd_THING_INSTALLED.argtypes = 'int:pos'
+
+def cmd_PLAYER_FACE(game, face, connection_id):
+    t = game.get_player(connection_id)
+    if not t:
+        raise GameError('can only draw face when already logged in')
+    if len(face) != 9:
+        raise GameError('wrong face string length')
+    game.faces[t.name] = face
+    game.changed = True
+cmd_PLAYER_FACE.argtypes = 'string'
+
+def cmd_GOD_PLAYER_FACE(game, name, face):
+    game.faces[name] = face
+cmd_GOD_PLAYER_FACE.argtypes = 'string string'
index 68d4858da793b07d9385a0ebcc25a579dc353263..017580f24e4cb28ef98062f4d11026b2a02894ca 100755 (executable)
@@ -121,6 +121,7 @@ class Game(GameBase):
         self.tasks = {}
         self.thing_types = {}
         self.sessions = {}
+        self.faces = {}
         self.maps = {}
         self.map_controls = {}
         self.map_control_passwords = {}
@@ -199,6 +200,14 @@ class Game(GameBase):
         player = self.get_thing(self.sessions[connection_id]['thing_id'])
         return player
 
+    def get_face(self, t):
+        if t.type_ == 'Player':
+            if t.name in self.faces:
+                return self.faces[t.name]
+            else:
+                return 'O O' + ' v ' + '>-<'
+        return None
+
     def send_gamestate(self, connection_id=None):
         """Send out game state data relevant to clients."""
 
@@ -237,6 +246,9 @@ class Game(GameBase):
                              c_id)
                 if hasattr(t, 'name'):
                     self.io.send('THING_NAME %s %s' % (t.id_, quote(t.name)), c_id)
+                face = self.get_face(t)
+                if face:
+                    self.io.send('THING_FACE %s %s' % (t.id_, quote(face)), c_id)
                 if hasattr(t, 'thing_char'):
                     self.io.send('THING_CHAR %s %s' % (t.id_,
                                                        quote(t.thing_char)), c_id)
@@ -371,6 +383,9 @@ class Game(GameBase):
                                                    self.map_control_passwords[tile_class]))
             for pw in self.admin_passwords:
                 write(f, 'ADMIN_PASSWORD %s' % pw)
+            for name in self.faces:
+                write(f, 'GOD_PLAYER_FACE %s %s' % (quote(name),
+                                                    quote(self.faces[name])))
             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_))
index f7a97ec11325cebb6faf66a769209fceea5aae0e..dfeeecdba69e2570d88c4ea1f08fafa512b2c14e 100644 (file)
@@ -69,6 +69,7 @@ keyboard input/control: <span id="keyboard_control"></span>
       <button id="switch_to_portal"></button>
       <button id="switch_to_name_thing"></button>
       <button id="switch_to_password"></button>
+      <button id="switch_to_enter_face"></button>
     </td>
   </tr>
   <tr>
@@ -101,6 +102,7 @@ keyboard input/control: <span id="keyboard_control"></span>
 <li>open/close: <input id="key_door" type="text" value="D" />
 <li>consume: <input id="key_consume" type="text" value="C" />
 <li>install: <input id="key_install" type="text" value="I" />
+<li><input id="key_switch_to_enter_face" type="text" value="f" />
 <li><input id="key_switch_to_take_thing" type="text" value="z" />
 <li><input id="key_switch_to_chat" type="text" value="t" />
 <li><input id="key_switch_to_play" type="text" value="p" />
@@ -160,6 +162,11 @@ let mode_helps = {
         'intro': '@ enter thing protection character:',
         'long': 'Change protection character for thing here.'
     },
+    'enter_face': {
+        'short': 'enter your face',
+        'intro': '@ enter face line (enter nothing to abort):',
+        'long': 'Draw your face as ASCII art.  The string you enter must be 9 characters long, and will be divided on display into three lines of three characters each, from top to bottom..'
+    },
     'write': {
         'short': 'change terrain',
         'intro': '',
@@ -477,14 +484,13 @@ let server = {
             t.portable = parseInt(tokens[5]);
         } else if (tokens[0] === 'THING_NAME') {
             let t = game.get_thing(tokens[1], false);
-            if (t) {
-                t.name_ = tokens[2];
-            };
+            t.name_ = tokens[2];
+        } else if (tokens[0] === 'THING_FACE') {
+            let t = game.get_thing(tokens[1], false);
+            t.face = tokens[2];
         } else if (tokens[0] === 'THING_CHAR') {
             let t = game.get_thing(tokens[1], false);
-            if (t) {
-                t.thing_char = tokens[2];
-            };
+            t.thing_char = tokens[2];
         } else if (tokens[0] === 'TASKS') {
             game.tasks = tokens[1].split(',');
             tui.mode_write.legal = game.tasks.includes('WRITE');
@@ -494,14 +500,10 @@ let server = {
             game.thing_types[tokens[1]] = tokens[2]
         } else if (tokens[0] === 'THING_CARRYING') {
             let t = game.get_thing(tokens[1], false);
-            if (t) {
-                t.carrying = true;
-            };
+            t.carrying = true;
         } else if (tokens[0] === 'THING_INSTALLED') {
             let t = game.get_thing(tokens[1], false);
-            if (t) {
-                t.installed = true;
-            };
+            t.installed = true;
         } else if (tokens[0] === 'TERRAIN') {
             game.terrains[tokens[1]] = tokens[2]
         } else if (tokens[0] === 'MAP') {
@@ -662,6 +664,7 @@ let tui = {
   mode_name_thing: new Mode('name_thing', true, true),
   mode_command_thing: new Mode('command_thing', true),
   mode_take_thing: new Mode('take_thing', true),
+  mode_enter_face: new Mode('enter_face', true),
   mode_admin_enter: new Mode('admin_enter', true),
   mode_admin: new Mode('admin'),
   mode_control_pw_pw: new Mode('control_pw_pw', true),
@@ -695,7 +698,7 @@ let tui = {
       this.mode_control_tile_draw.available_actions = ["toggle_tile_draw"];
       this.mode_edit.available_modes = ["write", "annotate", "portal", "name_thing",
                                         "password", "chat", "study", "play",
-                                        "admin_enter"]
+                                        "admin_enter", "enter_face"]
       this.mode_edit.available_actions = ["move", "flatten", "toggle_map_mode"]
       this.inputEl = document.getElementById("input");
       this.inputEl.focus();
@@ -1325,17 +1328,6 @@ let explorer = {
         if (game.fov[position_i] != '.') {
             info_to_cache += 'outside field of view';
         } else {
-            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]) {
@@ -1345,8 +1337,24 @@ let explorer = {
                          protection = 'none';
                      }
                      info_to_cache += " / protection: " + protection + "\n";
+                     if (t.face) {
+                         info_to_cache += t.face.slice(0, 3) + '\n';
+                         info_to_cache += t.face.slice(3, 6) + '\n';
+                         info_to_cache += t.face.slice(6, 9) + '\n';
+                     }
                  }
             }
+            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';
             if (this.position in game.portals) {
                 info_to_cache += "PORTAL: " + game.portals[this.position] + "\n";
             }
@@ -1427,6 +1435,14 @@ tui.inputEl.addEventListener('keydown', (event) => {
         tui.login_name = tui.inputEl.value;
         server.send(['LOGIN', tui.inputEl.value]);
         tui.inputEl.value = "";
+    } else if (tui.mode.name == 'enter_face' && event.key == 'Enter') {
+        if (tui.inputEl.value.length != 9) {
+            tui.log_msg('? wrong input length, aborting');
+        } else {
+            server.send(['PLAYER_FACE', tui.inputEl.value]);
+        }
+        tui.inputEl.value = "";
+        tui.switch_mode('edit');
     } else if (tui.mode.name == 'command_thing' && event.key == 'Enter') {
         if (tui.task_action_on('command')) {
             server.send(['TASK:COMMAND', tui.inputEl.value]);
index 8aeaf811b762ba4faac35ac049a0f842670ef2bc..14e23dc91fb13520b3454a82476faefcdca582c0 100755 (executable)
@@ -12,7 +12,8 @@ from plomrogue.commands import (cmd_ALL, cmd_LOGIN, cmd_NICK, cmd_PING, cmd_THIN
                                 cmd_SET_MAP_CONTROL_PASSWORD, cmd_SPAWN_POINT,
                                 cmd_THING_MUSICPLAYER_SETTINGS,
                                 cmd_THING_MUSICPLAYER_PLAYLIST_ITEM,
-                                cmd_THING_BOTTLE_EMPTY)
+                                cmd_THING_BOTTLE_EMPTY, cmd_PLAYER_FACE,
+                                cmd_GOD_PLAYER_FACE)
 from plomrogue.tasks import (Task_WAIT, Task_MOVE, Task_WRITE, Task_PICK_UP,
                              Task_DROP, Task_FLATTEN_SURROUNDINGS, Task_DOOR,
                              Task_INTOXICATE, Task_COMMAND, Task_INSTALL)
@@ -56,6 +57,8 @@ game.register_command(cmd_SPAWN_POINT)
 game.register_command(cmd_THING_MUSICPLAYER_SETTINGS)
 game.register_command(cmd_THING_MUSICPLAYER_PLAYLIST_ITEM)
 game.register_command(cmd_THING_BOTTLE_EMPTY)
+game.register_command(cmd_PLAYER_FACE)
+game.register_command(cmd_GOD_PLAYER_FACE)
 game.register_task(Task_WAIT)
 game.register_task(Task_MOVE)
 game.register_task(Task_WRITE)
index 70060275893245d4e63ba5e2838f53dbd1e53fd6..89c841140edc871c4108d91c6bb3b5f389599e0a 100755 (executable)
@@ -46,6 +46,11 @@ mode_helps = {
         'intro': '@ enter thing protection character:',
         'long': 'Change protection character for thing here.'
     },
+    'enter_face': {
+        'short': 'enter your face',
+        'intro': '@ enter face line (enter nothing to abort):',
+        'long': 'Draw your face as ASCII art.  The string you enter must be 9 characters long, and will be divided on display into three lines of three characters each, from top to bottom..'
+    },
     'write': {
         'short': 'change terrain',
         'intro': '',
@@ -207,15 +212,18 @@ cmd_THING.argtypes = 'yx_tuple:nonneg string:thing_type char int:nonneg bool'
 
 def cmd_THING_NAME(game, thing_id, name):
     t = game.get_thing(thing_id)
-    if t:
-        t.name = name
-cmd_THING_NAME.argtypes = 'int:nonneg string'
+    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.face = face
+cmd_THING_FACE.argtypes = 'int:pos string'
 
 def cmd_THING_CHAR(game, thing_id, c):
     t = game.get_thing(thing_id)
-    if t:
-        t.thing_char = c
-cmd_THING_CHAR.argtypes = 'int:nonneg char'
+    t.thing_char = c
+cmd_THING_CHAR.argtypes = 'int:pos char'
 
 def cmd_MAP(game, geometry, size, content):
     map_geometry_class = globals()['MapGeometry' + geometry]
@@ -334,6 +342,7 @@ class Game(GameBase):
         self.register_command(cmd_THING_TYPE)
         self.register_command(cmd_THING_NAME)
         self.register_command(cmd_THING_CHAR)
+        self.register_command(cmd_THING_FACE)
         self.register_command(cmd_THING_CARRYING)
         self.register_command(cmd_THING_INSTALLED)
         self.register_command(cmd_TERRAIN)
@@ -429,6 +438,7 @@ class TUI:
     mode_name_thing = Mode('name_thing', has_input_prompt=True, shows_info=True)
     mode_command_thing = Mode('command_thing', has_input_prompt=True)
     mode_take_thing = Mode('take_thing', has_input_prompt=True)
+    mode_enter_face = Mode('enter_face', has_input_prompt=True)
     is_admin = False
     tile_draw = False
 
@@ -451,7 +461,7 @@ class TUI:
                                                          "toggle_tile_draw"]
         self.mode_edit.available_modes = ["write", "annotate", "portal", "name_thing",
                                           "password", "chat", "study", "play",
-                                          "admin_enter"]
+                                          "admin_enter", "enter_face"]
         self.mode_edit.available_actions = ["move", "flatten", "toggle_map_mode"]
         self.mode = None
         self.host = host
@@ -481,6 +491,7 @@ class TUI:
             'switch_to_control_tile_type': 'Q',
             'switch_to_admin_thing_protect': 'T',
             'flatten': 'F',
+            'switch_to_enter_face': 'f',
             'switch_to_take_thing': 'z',
             'drop_thing': 'u',
             'teleport': 'p',
@@ -690,6 +701,17 @@ class TUI:
         if len(self.game.fov) > pos_i and self.game.fov[pos_i] != '.':
             info_to_cache += 'outside field of view'
         else:
+            for t in self.game.things:
+                if t.position == self.explorer:
+                    info_to_cache += 'THING: %s' % self.get_thing_info(t)
+                    protection = t.protection
+                    if protection == '.':
+                        protection = 'none'
+                    info_to_cache += ' / protection: %s\n' % protection
+                    if hasattr(t, 'face'):
+                        info_to_cache += t.face[0:3] + '\n'
+                        info_to_cache += t.face[3:6] + '\n'
+                        info_to_cache += t.face[6:9] + '\n'
             terrain_char = self.game.map_content[pos_i]
             terrain_desc = '?'
             if terrain_char in self.game.terrains:
@@ -700,13 +722,6 @@ class TUI:
             if protection == '.':
                 protection = 'unprotected'
             info_to_cache += 'PROTECTION: %s\n' % protection
-            for t in self.game.things:
-                if t.position == self.explorer:
-                    info_to_cache += 'THING: %s' % self.get_thing_info(t)
-                    protection = t.protection
-                    if protection == '.':
-                        protection = 'none'
-                    info_to_cache += ' / protection: %s\n' % protection
             if self.explorer in self.game.portals:
                 info_to_cache += 'PORTAL: ' +\
                     self.game.portals[self.explorer] + '\n'
@@ -1040,6 +1055,13 @@ class TUI:
                 self.login_name = self.input_
                 self.send('LOGIN ' + quote(self.input_))
                 self.input_ = ""
+            elif self.mode.name == 'enter_face' and key == '\n':
+                if len(self.input_) != 9:
+                    self.log_msg('? wrong input length, aborting')
+                else:
+                    self.send('PLAYER_FACE %s' % quote(self.input_))
+                self.input_ = ""
+                self.switch_mode('edit')
             elif self.mode.name == 'take_thing' and key == '\n':
                 try:
                     i = int(self.input_)