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:
parent
34aa91ad9e
commit
7d0c8f3431
|
@ -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),
|
||||||
|
),
|
||||||
|
]
|
|
@ -66,7 +66,7 @@ class CharacterManager(models.Manager):
|
||||||
"""
|
"""
|
||||||
hashed_pass = make_password(password)
|
hashed_pass = make_password(password)
|
||||||
character = self.create(name=name, game=game, password=hashed_pass, hostmask=hostmask,
|
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())
|
last_login=timezone.now())
|
||||||
logger.info("%s::%s: created and logged in, next level @ %s",
|
logger.info("%s::%s: created and logged in, next level @ %s",
|
||||||
character.game.name, character.name, character.next_level)
|
character.game.name, character.name, character.next_level)
|
||||||
|
@ -77,12 +77,14 @@ class Character(models.Model):
|
||||||
"""A character in a game."""
|
"""A character in a game."""
|
||||||
|
|
||||||
CHARACTER_STATUS_DISABLED = 'DISABLED'
|
CHARACTER_STATUS_DISABLED = 'DISABLED'
|
||||||
|
CHARACTER_STATUS_LOGGED_IN = 'LOGGEDIN'
|
||||||
CHARACTER_STATUS_OFFLINE = 'OFFLINE'
|
CHARACTER_STATUS_OFFLINE = 'OFFLINE'
|
||||||
CHARACTER_STATUS_ONLINE = 'ONLINE'
|
CHARACTER_STATUS_ONLINE = 'ONLINE'
|
||||||
CHARACTER_STATUSES = {
|
CHARACTER_STATUSES = {
|
||||||
|
CHARACTER_STATUS_DISABLED: "Disabled",
|
||||||
|
CHARACTER_STATUS_LOGGED_IN: "Logged in",
|
||||||
CHARACTER_STATUS_OFFLINE: "Offline",
|
CHARACTER_STATUS_OFFLINE: "Offline",
|
||||||
CHARACTER_STATUS_ONLINE: "Online",
|
CHARACTER_STATUS_ONLINE: "Online",
|
||||||
CHARACTER_STATUS_DISABLED: "Disabled",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NICK_CHANGE_P = 30
|
NICK_CHANGE_P = 30
|
||||||
|
@ -153,7 +155,7 @@ class Character(models.Model):
|
||||||
# error if this is being called before it should be
|
# error if this is being called before it should be
|
||||||
if self.next_level > timezone.now():
|
if self.next_level > timezone.now():
|
||||||
raise ValueError(f"character '{self.name}' can't level, it isn't yet {self.next_level}!")
|
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!")
|
raise ValueError(f"character '{self.name}' can't level, it isn't logged in!")
|
||||||
|
|
||||||
logger.debug("leveling up %s...", str(self))
|
logger.debug("leveling up %s...", str(self))
|
||||||
|
@ -169,15 +171,15 @@ class Character(models.Model):
|
||||||
Raises:
|
Raises:
|
||||||
ValueError: if the provided password was incorrect, or the character isn't logged out
|
ValueError: if the provided password was incorrect, or the character isn't logged out
|
||||||
"""
|
"""
|
||||||
if self.status != self.CHARACTER_STATUS_OFFLINE:
|
if self.status != self.CHARACTER_STATUS_ONLINE:
|
||||||
raise ValueError(f"character '{self.name}' can't be logged in, isn't logged out!")
|
raise ValueError(f"character '{self.name}' can't be logged in, isn't online!")
|
||||||
if not check_password(password, self.password):
|
if not check_password(password, self.password):
|
||||||
raise ValueError(f"incorrect password for character '{self.name}'!")
|
raise ValueError(f"incorrect password for character '{self.name}'!")
|
||||||
|
|
||||||
logger.debug("logging %s in...", str(self))
|
logger.debug("logging %s in...", str(self))
|
||||||
# we need to apply the time lost to the next level time
|
# we need to apply the time lost to the next level time
|
||||||
self.next_level += timezone.now() - self.last_login
|
self.next_level += timezone.now() - self.last_login
|
||||||
self.status = self.CHARACTER_STATUS_ONLINE
|
self.status = self.CHARACTER_STATUS_LOGGED_IN
|
||||||
self.hostmask = hostmask
|
self.hostmask = hostmask
|
||||||
logger.info("%s::%s: logged in, next level @ %s", self.game.name, self.name, self.next_level)
|
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:
|
Raises:
|
||||||
ValueError: the character isn't logged in
|
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!")
|
raise ValueError(f"character '{self.name}' can't be logged out, isn't logged in!")
|
||||||
|
|
||||||
self.status = self.CHARACTER_STATUS_OFFLINE
|
self.status = self.CHARACTER_STATUS_OFFLINE
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
"name": "bss",
|
"name": "bss",
|
||||||
"password": "pbkdf2_sha256$720000$A941t4dL96zzqeldCFucrr$Pof137/IjT3p//ZR+iYNoBnGmYPG6jLbNqenwMA3hHY=",
|
"password": "pbkdf2_sha256$720000$A941t4dL96zzqeldCFucrr$Pof137/IjT3p//ZR+iYNoBnGmYPG6jLbNqenwMA3hHY=",
|
||||||
"hostmask": "bss!bss@bss",
|
"hostmask": "bss!bss@bss",
|
||||||
"status": "ONLINE",
|
"status": "LOGGEDIN",
|
||||||
"character_class": "tester",
|
"character_class": "tester",
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"next_level": "2024-05-05T05:20:45.437Z",
|
"next_level": "2024-05-05T05:20:45.437Z",
|
||||||
|
|
|
@ -56,11 +56,12 @@ class CharacterTest(TestCase):
|
||||||
char.log_out()
|
char.log_out()
|
||||||
# logout has a penalty of its own, so this post-logout value is what will be altered
|
# logout has a penalty of its own, so this post-logout value is what will be altered
|
||||||
old_next_level = char.next_level
|
old_next_level = char.next_level
|
||||||
|
char.status = Character.CHARACTER_STATUS_ONLINE
|
||||||
with patch('django.utils.timezone.now', return_value=login_time):
|
with patch('django.utils.timezone.now', return_value=login_time):
|
||||||
char.log_in('bss', 'bss!bss@test_log_in')
|
char.log_in('bss', 'bss!bss@test_log_in')
|
||||||
|
|
||||||
assert char.next_level == old_next_level + timedelta(seconds=300)
|
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'
|
assert char.hostmask == 'bss!bss@test_log_in'
|
||||||
|
|
||||||
def test_cant_log_in_when_already_online(self):
|
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."""
|
"""Test that we can't log in the character if we don't have the right password."""
|
||||||
char = Character.objects.get(pk=1)
|
char = Character.objects.get(pk=1)
|
||||||
char.log_out()
|
char.log_out()
|
||||||
|
char.status = Character.CHARACTER_STATUS_ONLINE
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
char.log_in('bad pass', 'bss!bss@test_bad_password')
|
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):
|
with patch('django.utils.timezone.now', return_value=register_time):
|
||||||
new_char = Character.objects.register('new', game, 'pass', 'bss!bss@test_register', 'unit tester')
|
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.next_level == register_time + timedelta(seconds=600)
|
||||||
assert new_char.last_login == register_time
|
assert new_char.last_login == register_time
|
||||||
assert new_char.password[0:13] == 'pbkdf2_sha256'
|
assert new_char.password[0:13] == 'pbkdf2_sha256'
|
||||||
|
|
Loading…
Reference in New Issue