IronForce is a decentralized network, Degeon is a messenger built on it
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

142 lines
5.4 KiB

from __future__ import annotations
from dataclasses import dataclass, field
import typing
import pygame
from button import Button
from chat_selector import ChatSelector
from active_chat import ActiveChat
from config import FPS, DARKER_BLUE, font, WHITE, WIDTH, CHAT_SELECTOR_WIDTH, HEIGHT
import degeon_core as dc
from input_field import TextField
@dataclass
class Degeon:
"""
The main class with everything connected to the app: the data, the
Attributes:
:param core (dc.Degeon): the rust worker
:param chat_selector (ChatSelector): chat list widget
:param active_chat (typing.Optional[ActiveChat]): current chat widget
:param fps (int): FPS rate
"""
core: typing.Optional[dc.Degeon]
chat_selector: ChatSelector
active_chat: typing.Optional[ActiveChat] = None
name_input_field: TextField = field(
default_factory=lambda: TextField(placeholder='Name', top_left_corner=(WIDTH // 5, HEIGHT // 3)))
name_input_button: Button = field(default_factory=lambda: Button(text='Done', width=200, height=100,
top_left=(round(2 * WIDTH / 5), 2 * HEIGHT // 3)))
has_profile_popup_opened: bool = False
has_no_peers_popup: bool = False
clock: pygame.time.Clock = field(default_factory=pygame.time.Clock)
fps: int = FPS
@classmethod
def new(cls) -> Degeon:
"""
Create a new default instance with settings from file
:return: a Degeon instance
"""
if dc.is_data_available():
core: dc.Degeon = dc.new_degeon()
else:
# core: dc.Degeon = dc.new_degeon_with_name(input('Enter name: '))
core = None
chat_selector = ChatSelector()
return cls(core=core, chat_selector=chat_selector)
def register(self, name: str):
"""
Create new rust-Degeon instance with name
:param name: user's name
"""
self.core = dc.new_degeon_with_name(name)
self.chat_selector.chats = self.core.chats
def render(self, screen: pygame.Surface):
"""
Render everything on the screen
:param screen: the main screen
"""
if self.core is None:
screen.fill(DARKER_BLUE)
button_surface: pygame.Surface = self.name_input_button.render()
screen.blit(button_surface, self.name_input_button.top_left)
name_field_surface: pygame.Surface = self.name_input_field.render()
screen.blit(name_field_surface, self.name_input_field.top_left_corner)
return
chats_surface = self.chat_selector.render()
screen.blit(chats_surface, (0, 0))
if self.active_chat is not None:
active_chat_surface = self.active_chat.render(self.core)
screen.blit(active_chat_surface, (self.active_chat.delta_x, 0))
else:
text_surface: pygame.Surface = font.render('<- Select chat in the menu', True, WHITE)
screen.blit(text_surface,
(round(WIDTH / 2 + CHAT_SELECTOR_WIDTH / 2 - text_surface.get_width() / 2), HEIGHT // 2))
def process_core_messages(self):
"""
Do all the necessary Rust work
"""
if self.core is None:
return
while self.core.message_queue_len():
self.core.handling_loop_iteration()
def tick(self):
"""
Handle incoming messages, update chats, create no_peers popup if necessary
"""
if self.core is None:
return
# process events in core
self.process_core_messages()
if self.core is not None:
self.chat_selector.chats = self.core.chats
if 0 <= self.chat_selector.active_chat < len(self.chat_selector.chats) and self.active_chat is None:
self.active_chat = ActiveChat.new(self.chat_selector.chats[self.chat_selector.active_chat])
if self.active_chat is not None and self.core is not None:
self.active_chat.chat = self.core.chats[self.chat_selector.active_chat]
def process_event(self, event: pygame.event.Event):
"""
Process an event
:param event: pygame event
"""
if self.core is None:
self.name_input_field.process_event(event)
if self.name_input_button.process_event(event):
self.register(self.name_input_field.value)
return
if self.chat_selector.process_event(event):
if 0 <= self.chat_selector.active_chat < len(self.chat_selector.chats):
self.active_chat = ActiveChat.new(self.chat_selector.chats[self.chat_selector.active_chat])
else:
self.active_chat = None
if self.active_chat is not None:
# If the result is a string, it's a message
result: typing.Optional[str] = self.active_chat.process_event(event)
if result:
self.core.send_text_message(result, self.chat_selector.active_chat)
def main_loop(self, screen: pygame.Surface):
"""
Drawing everything and handling events
"""
while True:
screen.fill(DARKER_BLUE)
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
self.process_event(event)
self.tick()
self.render(screen)
self.clock.tick(self.fps)
pygame.display.update()