From 7c03e8e8e4ed15f01e29dd331596719058af9f07 Mon Sep 17 00:00:00 2001
From: Christian Heller <c.heller@plomlompom.de>
Date: Sat, 19 Dec 2020 00:41:54 +0100
Subject: [PATCH] Use temporary SpawnPoints to store logged-out players'
 positions for up to ten minutes.

---
 plomrogue/commands.py | 14 ++++++++++++++
 plomrogue/game.py     | 21 ++++++++++++++++++++-
 plomrogue/things.py   | 11 +++++++++++
 rogue_chat.py         |  4 +++-
 4 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/plomrogue/commands.py b/plomrogue/commands.py
index 921d6e0..9cdab97 100644
--- a/plomrogue/commands.py
+++ b/plomrogue/commands.py
@@ -414,3 +414,17 @@ cmd_THING_CRATE_ITEM.argtypes = 'int:pos int:pos'
 def cmd_MAP_CONTROL_PRESETS(game, draw_control_presets):
     game.draw_control_presets = draw_control_presets
 cmd_MAP_CONTROL_PRESETS.argtypes = 'bool'
+
+def cmd_THING_SPAWNPOINT_CREATED(game, spawnpoint_id, timestamp):
+    import datetime
+    spawnpoint = game.get_thing(spawnpoint_id)
+    if not spawnpoint:
+        raise GameError('thing of ID %s not found' % spawnpoint_id)
+    if spawnpoint.type_ != 'SpawnPoint':
+        raise GameError('thing of ID %s not a SpawnPoint' % spawnpoint_id)
+    if timestamp == 0:
+        spawnpoint.temporary = False
+    else:
+        spawnpoint.temporary = True
+        spawnpoint.created_at = datetime.datetime.fromtimestamp(timestamp)
+cmd_THING_SPAWNPOINT_CREATED.argtypes = 'int:pos int:nonneg'
diff --git a/plomrogue/game.py b/plomrogue/game.py
index 4b5c337..088db9d 100755
--- a/plomrogue/game.py
+++ b/plomrogue/game.py
@@ -351,7 +351,9 @@ class Game(GameBase):
         for s in [s for s in self.things
                   if s.type_ == 'SpawnPoint' and s.name == t.name]:
             t.position = s.position
-            break
+            if s.temporary:
+                self.remove_thing(s)
+                break
 
     def run_tick(self):
 
@@ -367,6 +369,9 @@ class Game(GameBase):
                 t = self.get_player(connection_id)
                 if hasattr(t, 'name'):
                     self.io.send('CHAT ' + quote(t.name + ' left the map.'))
+                spawn_point = self.add_thing('SpawnPoint', t.position)
+                spawn_point.temporary = True
+                spawn_point.name = t.name
                 self.remove_thing(t)
                 to_delete += [connection_id]
         for connection_id in to_delete:
@@ -568,6 +573,20 @@ class Game(GameBase):
                 elif t.type_ == 'Crate':
                     for item in t.content:
                         write(f, 'THING_CRATE_ITEM %s %s' % (t.id_, item.id_))
+                elif t.type_ == 'SpawnPoint':
+                    timestamp = 0
+                    if t.temporary:
+                        timestamp = int(t.created_at.timestamp())
+                    write(f, 'THING_SPAWNPOINT_CREATED %s %s' % (t.id_,
+                                                                 timestamp))
+            next_thing_id = self.new_thing_id()
+            for t in [t for t in self.things if t.type_ == 'Player']:
+                write(f, 'THING %s %s SpawnPoint %s'
+                      % (t.position[0], t.position[1], next_thing_id))
+                write(f, 'GOD_THING_NAME %s %s' % (next_thing_id, t.name))
+                write(f, 'THING_SPAWNPOINT_CREATED %s %s'
+                      % (next_thing_id, int(datetime.datetime.now().timestamp())))
+                next_thing_id += 1
             write(f, 'SPAWN_POINT %s %s' % (self.spawn_point[0],
                                             self.spawn_point[1]))
 
diff --git a/plomrogue/things.py b/plomrogue/things.py
index da995d3..2c3f540 100644
--- a/plomrogue/things.py
+++ b/plomrogue/things.py
@@ -148,6 +148,17 @@ class Thing_SpawnPoint(Thing):
     symbol_hint = 's'
     portable = True
     name = 'username'
+    temporary = False
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self.created_at = datetime.datetime.now()
+
+    def proceed(self):
+        super().proceed()
+        if self.temporary and datetime.datetime.now() >\
+           self.created_at + datetime.timedelta(minutes=10):
+            self.game.remove_thing(self)
 
 
 
diff --git a/rogue_chat.py b/rogue_chat.py
index 2461289..5c07276 100755
--- a/rogue_chat.py
+++ b/rogue_chat.py
@@ -16,7 +16,8 @@ from plomrogue.commands import (cmd_ALL, cmd_LOGIN, cmd_NICK, cmd_PING, cmd_THIN
                                 cmd_GOD_PLAYER_FACE, cmd_GOD_PLAYER_HAT,
                                 cmd_GOD_PLAYERS_HAT_CHARS, cmd_PLAYER_HAT,
                                 cmd_TERRAIN_TAG, cmd_THING_DOOR_KEY,
-                                cmd_THING_CRATE_ITEM, cmd_MAP_CONTROL_PRESETS)
+                                cmd_THING_CRATE_ITEM, cmd_MAP_CONTROL_PRESETS,
+                                cmd_THING_SPAWNPOINT_CREATED)
 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,
@@ -76,6 +77,7 @@ game.register_command(cmd_THING_HAT_DESIGN)
 game.register_command(cmd_THING_DOOR_KEY)
 game.register_command(cmd_THING_CRATE_ITEM)
 game.register_command(cmd_MAP_CONTROL_PRESETS)
+game.register_command(cmd_THING_SPAWNPOINT_CREATED)
 game.register_task(Task_WAIT)
 game.register_task(Task_MOVE)
 game.register_task(Task_WRITE)
-- 
2.30.2