separate the logged in state from the online state for a character

I think we will need to distinguish in the database characters whose
players are online but not yet logged in, so start building for that now

Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
This commit is contained in:
Brian S. Stephan 2024-05-10 14:39:41 -05:00
parent 34aa91ad9e
commit 7d0c8f3431
Signed by: bss
GPG Key ID: 3DE06D3180895FCB
4 changed files with 32 additions and 10 deletions

View File

@ -0,0 +1,18 @@
# Generated by Django 5.0.5 on 2024-05-10 21:03
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('idlerpg', '0002_character_player_must_have_unique_character_names'),
]
operations = [
migrations.AlterField(
model_name='character',
name='status',
field=models.CharField(choices=[('DISABLED', 'Disabled'), ('LOGGEDIN', 'Logged in'), ('OFFLINE', 'Offline'), ('ONLINE', 'Online')], default='OFFLINE', max_length=8),
),
]

View File

@ -66,7 +66,7 @@ class CharacterManager(models.Manager):
"""
hashed_pass = make_password(password)
character = self.create(name=name, game=game, password=hashed_pass, hostmask=hostmask,
character_class=character_class, status=Character.CHARACTER_STATUS_ONLINE,
character_class=character_class, status=Character.CHARACTER_STATUS_LOGGED_IN,
last_login=timezone.now())
logger.info("%s::%s: created and logged in, next level @ %s",
character.game.name, character.name, character.next_level)
@ -77,12 +77,14 @@ class Character(models.Model):
"""A character in a game."""
CHARACTER_STATUS_DISABLED = 'DISABLED'
CHARACTER_STATUS_LOGGED_IN = 'LOGGEDIN'
CHARACTER_STATUS_OFFLINE = 'OFFLINE'
CHARACTER_STATUS_ONLINE = 'ONLINE'
CHARACTER_STATUSES = {
CHARACTER_STATUS_DISABLED: "Disabled",
CHARACTER_STATUS_LOGGED_IN: "Logged in",
CHARACTER_STATUS_OFFLINE: "Offline",
CHARACTER_STATUS_ONLINE: "Online",
CHARACTER_STATUS_DISABLED: "Disabled",
}
NICK_CHANGE_P = 30
@ -153,7 +155,7 @@ class Character(models.Model):
# error if this is being called before it should be
if self.next_level > timezone.now():
raise ValueError(f"character '{self.name}' can't level, it isn't yet {self.next_level}!")
if self.status != self.CHARACTER_STATUS_ONLINE:
if self.status != self.CHARACTER_STATUS_LOGGED_IN:
raise ValueError(f"character '{self.name}' can't level, it isn't logged in!")
logger.debug("leveling up %s...", str(self))
@ -169,15 +171,15 @@ class Character(models.Model):
Raises:
ValueError: if the provided password was incorrect, or the character isn't logged out
"""
if self.status != self.CHARACTER_STATUS_OFFLINE:
raise ValueError(f"character '{self.name}' can't be logged in, isn't logged out!")
if self.status != self.CHARACTER_STATUS_ONLINE:
raise ValueError(f"character '{self.name}' can't be logged in, isn't online!")
if not check_password(password, self.password):
raise ValueError(f"incorrect password for character '{self.name}'!")
logger.debug("logging %s in...", str(self))
# we need to apply the time lost to the next level time
self.next_level += timezone.now() - self.last_login
self.status = self.CHARACTER_STATUS_ONLINE
self.status = self.CHARACTER_STATUS_LOGGED_IN
self.hostmask = hostmask
logger.info("%s::%s: logged in, next level @ %s", self.game.name, self.name, self.next_level)
@ -187,7 +189,7 @@ class Character(models.Model):
Raises:
ValueError: the character isn't logged in
"""
if self.status != self.CHARACTER_STATUS_ONLINE:
if self.status != self.CHARACTER_STATUS_LOGGED_IN:
raise ValueError(f"character '{self.name}' can't be logged out, isn't logged in!")
self.status = self.CHARACTER_STATUS_OFFLINE

View File

@ -49,7 +49,7 @@
"name": "bss",
"password": "pbkdf2_sha256$720000$A941t4dL96zzqeldCFucrr$Pof137/IjT3p//ZR+iYNoBnGmYPG6jLbNqenwMA3hHY=",
"hostmask": "bss!bss@bss",
"status": "ONLINE",
"status": "LOGGEDIN",
"character_class": "tester",
"level": 0,
"next_level": "2024-05-05T05:20:45.437Z",

View File

@ -56,11 +56,12 @@ class CharacterTest(TestCase):
char.log_out()
# logout has a penalty of its own, so this post-logout value is what will be altered
old_next_level = char.next_level
char.status = Character.CHARACTER_STATUS_ONLINE
with patch('django.utils.timezone.now', return_value=login_time):
char.log_in('bss', 'bss!bss@test_log_in')
assert char.next_level == old_next_level + timedelta(seconds=300)
assert char.status == Character.CHARACTER_STATUS_ONLINE
assert char.status == Character.CHARACTER_STATUS_LOGGED_IN
assert char.hostmask == 'bss!bss@test_log_in'
def test_cant_log_in_when_already_online(self):
@ -73,6 +74,7 @@ class CharacterTest(TestCase):
"""Test that we can't log in the character if we don't have the right password."""
char = Character.objects.get(pk=1)
char.log_out()
char.status = Character.CHARACTER_STATUS_ONLINE
with self.assertRaises(ValueError):
char.log_in('bad pass', 'bss!bss@test_bad_password')
@ -147,7 +149,7 @@ class CharacterTest(TestCase):
with patch('django.utils.timezone.now', return_value=register_time):
new_char = Character.objects.register('new', game, 'pass', 'bss!bss@test_register', 'unit tester')
assert new_char.status == Character.CHARACTER_STATUS_ONLINE
assert new_char.status == Character.CHARACTER_STATUS_LOGGED_IN
assert new_char.next_level == register_time + timedelta(seconds=600)
assert new_char.last_login == register_time
assert new_char.password[0:13] == 'pbkdf2_sha256'