mirror of
https://github.com/evgen-app/chess_rpg_backend.git
synced 2024-11-22 17:47:11 +03:00
added game state base logic, minor changes
This commit is contained in:
parent
df3685b8fe
commit
73db40a4f7
|
@ -24,6 +24,11 @@ INSTALLED_APPS = [
|
||||||
"room",
|
"room",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if DEBUG:
|
||||||
|
INSTALLED_APPS.append("django.contrib.staticfiles")
|
||||||
|
INSTALLED_APPS.append("drf_yasg")
|
||||||
|
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
"django.middleware.security.SecurityMiddleware",
|
"django.middleware.security.SecurityMiddleware",
|
||||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||||
|
|
|
@ -1,9 +1,46 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls.static import static
|
from django.conf.urls.static import static
|
||||||
from django.urls import path, include
|
from django.template.defaulttags import url
|
||||||
|
from django.urls import path, include, re_path
|
||||||
|
|
||||||
urlpatterns = (
|
# openapi schema
|
||||||
[path("api/", include("game.urls"))]
|
from rest_framework import permissions
|
||||||
+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
from drf_yasg.views import get_schema_view
|
||||||
+ static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
from drf_yasg import openapi
|
||||||
|
|
||||||
|
|
||||||
|
schema_view = get_schema_view(
|
||||||
|
openapi.Info(
|
||||||
|
title="Snippets API",
|
||||||
|
default_version="v1",
|
||||||
|
description="Test description",
|
||||||
|
terms_of_service="https://www.google.com/policies/terms/",
|
||||||
|
contact=openapi.Contact(email="contact@snippets.local"),
|
||||||
|
license=openapi.License(name="BSD License"),
|
||||||
|
),
|
||||||
|
public=True,
|
||||||
|
permission_classes=(permissions.AllowAny,),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
urlpatterns = [path("api/", include("game.urls"))] + static(
|
||||||
|
settings.MEDIA_URL, document_root=settings.MEDIA_ROOT
|
||||||
|
)
|
||||||
|
|
||||||
|
if settings.DEBUG:
|
||||||
|
urlpatterns += [
|
||||||
|
re_path(
|
||||||
|
r"^swagger(?P<format>\.json|\.yaml)$",
|
||||||
|
schema_view.without_ui(cache_timeout=0),
|
||||||
|
name="schema-json",
|
||||||
|
),
|
||||||
|
re_path(
|
||||||
|
r"^swagger/$",
|
||||||
|
schema_view.with_ui("swagger", cache_timeout=0),
|
||||||
|
name="schema-swagger-ui",
|
||||||
|
),
|
||||||
|
re_path(
|
||||||
|
r"^redoc/$",
|
||||||
|
schema_view.with_ui("redoc", cache_timeout=0),
|
||||||
|
name="schema-redoc",
|
||||||
|
),
|
||||||
|
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||||
|
|
|
@ -11,4 +11,4 @@ def generate_charset(length: int):
|
||||||
|
|
||||||
|
|
||||||
def gen_ton():
|
def gen_ton():
|
||||||
return "".join([str(randint(0, 9)) for _ in range(48)])
|
return int("".join([str(randint(0, 9)) for _ in range(48)]))
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import random
|
import random
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from django.core.files import File
|
|
||||||
from django.core.validators import (
|
from django.core.validators import (
|
||||||
MinValueValidator,
|
MinValueValidator,
|
||||||
MaxValueValidator,
|
MaxValueValidator,
|
||||||
|
@ -9,18 +8,16 @@ from django.core.validators import (
|
||||||
MaxLengthValidator,
|
MaxLengthValidator,
|
||||||
)
|
)
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
from common.generators import generate_charset
|
from common.generators import generate_charset
|
||||||
from game.services.jwt import sign_jwt
|
from game.services.jwt import sign_jwt
|
||||||
|
|
||||||
HER0_TYPES = [
|
|
||||||
("WIZARD", "wizard"),
|
class HeroTypes(models.TextChoices):
|
||||||
("ARCHER", "archer"),
|
wizard = "WIZARD", "wizard"
|
||||||
("WARRIOR", "warrior"),
|
archer = "ARCHER", "archer"
|
||||||
("KING", "king"),
|
warrior = "WARRIOR", "warrior"
|
||||||
]
|
king = "KING", "king"
|
||||||
HER0_IMAGE_TYPES = [("DIE", "die"), ("IDLE", "idle"), ("ATTACK", "attack")]
|
|
||||||
|
|
||||||
|
|
||||||
class Player(models.Model):
|
class Player(models.Model):
|
||||||
|
@ -47,7 +44,7 @@ class Player(models.Model):
|
||||||
+ ["ARCHER" for _ in range(4)]
|
+ ["ARCHER" for _ in range(4)]
|
||||||
+ ["WARRIOR" for _ in range(6)]
|
+ ["WARRIOR" for _ in range(6)]
|
||||||
+ ["WIZARD" for _ in range(2)]
|
+ ["WIZARD" for _ in range(2)]
|
||||||
+ [random.choice(HER0_TYPES[:3])[0] for _ in range(3)]
|
+ [random.choice(HeroTypes.choices[:3])[0] for _ in range(3)]
|
||||||
)
|
)
|
||||||
for t in types:
|
for t in types:
|
||||||
hero = Hero()
|
hero = Hero()
|
||||||
|
@ -99,16 +96,8 @@ class Hero(models.Model):
|
||||||
)
|
)
|
||||||
added = models.DateTimeField(auto_now_add=True)
|
added = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
type = models.CharField(blank=False, choices=HER0_TYPES, max_length=7)
|
type = models.CharField(blank=False, choices=HeroTypes.choices, max_length=7)
|
||||||
idle_img_f = models.ForeignKey(
|
model = models.ForeignKey("HeroModelSet", on_delete=models.CASCADE)
|
||||||
"HeroImageSet", on_delete=models.CASCADE, related_name="idle_image_fkey"
|
|
||||||
)
|
|
||||||
attack_img_f = models.ForeignKey(
|
|
||||||
"HeroImageSet", on_delete=models.CASCADE, related_name="attack_image_fkey"
|
|
||||||
)
|
|
||||||
die_img_f = models.ForeignKey(
|
|
||||||
"HeroImageSet", on_delete=models.CASCADE, related_name="die_image_fkey"
|
|
||||||
)
|
|
||||||
health = models.IntegerField(
|
health = models.IntegerField(
|
||||||
validators=[MinValueValidator(1), MaxValueValidator(10)], blank=False
|
validators=[MinValueValidator(1), MaxValueValidator(10)], blank=False
|
||||||
)
|
)
|
||||||
|
@ -135,13 +124,13 @@ class Hero(models.Model):
|
||||||
self, force_insert=False, force_update=False, using=None, update_fields=None
|
self, force_insert=False, force_update=False, using=None, update_fields=None
|
||||||
):
|
):
|
||||||
self.idle_img_f = random.choice(
|
self.idle_img_f = random.choice(
|
||||||
[x for x in HeroImageSet.objects.filter(hero_type=self.type, type="IDLE")]
|
[x for x in HeroModelSet.objects.filter(hero_type=self.type)]
|
||||||
)
|
)
|
||||||
self.attack_img_f = random.choice(
|
self.attack_img_f = random.choice(
|
||||||
[x for x in HeroImageSet.objects.filter(hero_type=self.type, type="ATTACK")]
|
[x for x in HeroModelSet.objects.filter(hero_type=self.type)]
|
||||||
)
|
)
|
||||||
self.die_img_f = random.choice(
|
self.die_img_f = random.choice(
|
||||||
[x for x in HeroImageSet.objects.filter(hero_type=self.type, type="DIE")]
|
[x for x in HeroModelSet.objects.filter(hero_type=self.type)]
|
||||||
)
|
)
|
||||||
super(Hero, self).save()
|
super(Hero, self).save()
|
||||||
|
|
||||||
|
@ -154,13 +143,12 @@ class Hero(models.Model):
|
||||||
verbose_name_plural = "heroes"
|
verbose_name_plural = "heroes"
|
||||||
|
|
||||||
|
|
||||||
class HeroImageSet(models.Model):
|
class HeroModelSet(models.Model):
|
||||||
type = models.CharField(max_length=10, choices=HER0_IMAGE_TYPES)
|
hero_type = models.CharField(blank=False, choices=HeroTypes.choices, max_length=7)
|
||||||
hero_type = models.CharField(blank=False, choices=HER0_TYPES, max_length=7)
|
model = models.ImageField(upload_to="uploads/")
|
||||||
image = models.ImageField(upload_to="uploads/")
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.hero_type} {self.type} image"
|
return f"{self.hero_type} model file"
|
||||||
|
|
||||||
|
|
||||||
class Deck(models.Model):
|
class Deck(models.Model):
|
||||||
|
|
|
@ -5,7 +5,7 @@ from channels.generic.websocket import AsyncWebsocketConsumer
|
||||||
from channels.layers import get_channel_layer
|
from channels.layers import get_channel_layer
|
||||||
|
|
||||||
from game.models import Deck
|
from game.models import Deck
|
||||||
from room.models import PlayerInQueue, Room, PlayerInRoom
|
from room.models import PlayerInQueue, Room, PlayerInRoom, GameState
|
||||||
from room.services.room_create import create_room
|
from room.services.room_create import create_room
|
||||||
|
|
||||||
channel_layer = get_channel_layer()
|
channel_layer = get_channel_layer()
|
||||||
|
@ -208,15 +208,18 @@ class RoomConsumer(AsyncWebsocketConsumer):
|
||||||
if not await self.connect_to_room():
|
if not await self.connect_to_room():
|
||||||
await self.close()
|
await self.close()
|
||||||
else:
|
else:
|
||||||
|
message, round = await self.get_state()
|
||||||
|
|
||||||
await self.send(
|
await self.send(
|
||||||
json.dumps(
|
json.dumps(
|
||||||
{
|
{
|
||||||
"type": "INFO",
|
"type": "INFO",
|
||||||
"message": f"welcome to room {self.room_name}",
|
|
||||||
"opponent_score": self.scope["opponent_score"],
|
"opponent_score": self.scope["opponent_score"],
|
||||||
"opponent_deck": self.scope["opponent_deck"],
|
"opponent_deck": self.scope["opponent_deck"],
|
||||||
"opponent_online": self.scope["opponent_online"],
|
"opponent_online": self.scope["opponent_online"],
|
||||||
"first": self.scope["first"],
|
"first": self.scope["first"],
|
||||||
|
"state": message,
|
||||||
|
"round": round,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -236,6 +239,11 @@ class RoomConsumer(AsyncWebsocketConsumer):
|
||||||
# Join room group
|
# Join room group
|
||||||
await self.channel_layer.group_add(self.room_group_name, self.channel_name)
|
await self.channel_layer.group_add(self.room_group_name, self.channel_name)
|
||||||
|
|
||||||
|
@sync_to_async
|
||||||
|
def get_state(self):
|
||||||
|
state = self.scope["player_in_room"].get_state()
|
||||||
|
return state.message, state.round
|
||||||
|
|
||||||
@sync_to_async
|
@sync_to_async
|
||||||
def connect_to_room(self):
|
def connect_to_room(self):
|
||||||
slug = self.scope["url_route"]["kwargs"]["room_name"]
|
slug = self.scope["url_route"]["kwargs"]["room_name"]
|
||||||
|
@ -346,6 +354,12 @@ class RoomConsumer(AsyncWebsocketConsumer):
|
||||||
if "first" in event:
|
if "first" in event:
|
||||||
msg["first"] = event["first"]
|
msg["first"] = event["first"]
|
||||||
|
|
||||||
|
if "state" in event:
|
||||||
|
msg["state"] = event["state"]
|
||||||
|
|
||||||
|
if "round" in event:
|
||||||
|
msg["round"] = event["round"]
|
||||||
|
|
||||||
await self.send(text_data=json.dumps(msg))
|
await self.send(text_data=json.dumps(msg))
|
||||||
|
|
||||||
# Receive message from room group
|
# Receive message from room group
|
||||||
|
|
|
@ -9,38 +9,7 @@ class Migration(migrations.Migration):
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('game', '0002_deck_heroimageset_heroindeck_playerauthsession_and_more'),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.CreateModel(
|
|
||||||
name='Room',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('slug', models.SlugField(max_length=16, unique=True)),
|
|
||||||
('created', models.DateTimeField(auto_now_add=True)),
|
|
||||||
('ended', models.BooleanField(default=False)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='PlayerInRoom',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('first', models.BooleanField()),
|
|
||||||
('score', models.IntegerField()),
|
|
||||||
('deck', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='decks', to='game.deck')),
|
|
||||||
('player', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='game.player')),
|
|
||||||
('room', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='players', to='room.room')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='PlayerInQueue',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('channel_name', models.CharField(max_length=50)),
|
|
||||||
('score', models.IntegerField()),
|
|
||||||
('deck', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='game.deck')),
|
|
||||||
('player', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='game.player')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -33,5 +33,18 @@ class PlayerInRoom(models.Model):
|
||||||
online = models.BooleanField(default=False)
|
online = models.BooleanField(default=False)
|
||||||
channel_name = models.CharField(max_length=50, blank=True, null=True)
|
channel_name = models.CharField(max_length=50, blank=True, null=True)
|
||||||
|
|
||||||
|
def get_state(self):
|
||||||
|
return GameState.objects.filter(player=self.player, room=self.room).last()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.player.name} in room {self.room.slug}"
|
return f"{self.player.name} in room {self.room.slug}"
|
||||||
|
|
||||||
|
|
||||||
|
class GameState(models.Model):
|
||||||
|
room = models.ForeignKey(Room, on_delete=models.CASCADE)
|
||||||
|
player = models.ForeignKey(Player, on_delete=models.CASCADE)
|
||||||
|
round = models.IntegerField(blank=False)
|
||||||
|
message = models.CharField(max_length=100, blank=False)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
unique_together = ["room", "player", "round"]
|
||||||
|
|
|
@ -3,7 +3,7 @@ from random import randint
|
||||||
|
|
||||||
from common.generators import generate_charset
|
from common.generators import generate_charset
|
||||||
from game.models import Player
|
from game.models import Player
|
||||||
from room.models import Room, PlayerInRoom
|
from room.models import Room, PlayerInRoom, GameState
|
||||||
|
|
||||||
|
|
||||||
@sync_to_async
|
@sync_to_async
|
||||||
|
@ -36,4 +36,10 @@ def create_room(
|
||||||
deck_id=deck_id_2,
|
deck_id=deck_id_2,
|
||||||
first=first_player == 2,
|
first=first_player == 2,
|
||||||
)
|
)
|
||||||
|
GameState.objects.create(
|
||||||
|
room=room, player=player_1, round=0, message="Game started"
|
||||||
|
)
|
||||||
|
GameState.objects.create(
|
||||||
|
room=room, player=player_2, round=0, message="Game started"
|
||||||
|
)
|
||||||
return room.slug
|
return room.slug
|
||||||
|
|
Loading…
Reference in New Issue
Block a user