Files

291 lines
13 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from fastapi import HTTPException
from datetime import datetime
import json
from app.services.coins import CoinsService
from app.models.server.event import PlayerEvent, OnlinePlayersUpdate
import uuid
class EventService:
def __init__(self):
self.coins_service = CoinsService()
async def process_event(self, event_data):
"""Обработка событий от сервера Minecraft"""
try:
# Проверяем формат ваших событий (event_type вместо type)
event_type = event_data.get("event_type")
if not event_type:
# Для совместимости со старым форматом
event_type = event_data.get("type")
if not event_type:
raise HTTPException(status_code=400, detail="Missing event type")
server_ip = event_data.get("server_ip")
if not server_ip:
raise HTTPException(status_code=400, detail="Missing server IP")
# Преобразуем ваши типы событий в нужные форматы
if event_type == "online_players_update":
# Регистрируем сервер, если его нет
await self._register_server(server_ip, event_data)
# Обновляем данные об онлайн игроках
players = event_data.get("players", [])
await self._update_online_players(server_ip, players)
return {"status": "success"}
elif event_type == "player_join":
player_id = event_data.get("player_id")
player_name = event_data.get("player_name")
if not player_id or not player_name:
raise HTTPException(status_code=400, detail="Missing player data")
# Регистрируем вход игрока
await self._register_player_login(server_ip, player_id, player_name)
return {"status": "success"}
elif event_type == "player_quit":
player_id = event_data.get("player_id")
player_name = event_data.get("player_name")
if not player_id or not player_name:
raise HTTPException(status_code=400, detail="Missing player data")
# Регистрируем выход игрока
await self._register_player_logout(server_ip, player_id, player_name)
return {"status": "success"}
elif event_type == "player_session":
player_id = event_data.get("player_id")
player_name = event_data.get("player_name")
duration = event_data.get("duration", 0)
if not player_id or not player_name:
raise HTTPException(status_code=400, detail="Missing player data")
# Обрабатываем информацию о сессии
await self._process_player_session(server_ip, player_id, player_name, duration)
return {"status": "success"}
# Если тип события не распознан
print(f"[{datetime.now()}] Неизвестное событие: {event_data}")
raise HTTPException(status_code=400, detail="Invalid event type")
except HTTPException as e:
print(f"[{datetime.now()}] Ошибка обработки события: {e.status_code}: {e.detail}")
print(f"Полученные данные: {event_data}")
raise
except Exception as e:
print(f"[{datetime.now()}] Необработанная ошибка: {str(e)}")
print(f"Полученные данные: {event_data}")
raise HTTPException(status_code=500, detail=f"Server error: {str(e)}")
async def _register_server(self, server_ip, event_data):
"""Регистрирует сервер, если его нет в базе"""
from app.db.database import db
import uuid
game_servers_collection = db.game_servers
# Проверяем, есть ли уже такой сервер
existing_server = await game_servers_collection.find_one({"ip": server_ip})
if not existing_server:
# Создаем новую запись сервера
server_data = {
"id": str(uuid.uuid4()),
"name": f"Server {server_ip}", # Можно улучшить название
"ip": server_ip,
"port": 25565, # Стандартный порт Minecraft
"description": f"Minecraft server {server_ip}",
"max_players": 100,
"registered_at": datetime.utcnow(),
"last_activity": datetime.utcnow() # Добавляем поле last_activity
}
await game_servers_collection.insert_one(server_data)
print(f"[{datetime.utcnow()}] Зарегистрирован новый сервер: {server_ip}")
else:
# Обновляем активность существующего сервера
await game_servers_collection.update_one(
{"ip": server_ip},
{"$set": {"last_activity": datetime.utcnow()}}
)
return existing_server or await game_servers_collection.find_one({"ip": server_ip})
async def _update_online_players(self, server_ip, players_data):
"""Обновляет информацию об онлайн игроках"""
from app.db.database import db
online_players_collection = db.online_players
game_servers_collection = db.game_servers
# Получаем ID сервера
server = await self._register_server(server_ip, {})
server_id = server["id"]
# Обновляем время активности сервера
await game_servers_collection.update_one(
{"id": server_id},
{"$set": {"last_activity": datetime.utcnow()}}
)
# Помечаем всех игроков как оффлайн на этом сервере
await online_players_collection.update_many(
{"server_id": server_id},
{"$set": {"is_online": False}}
)
# Обновляем данные для каждого онлайн игрока
now = datetime.utcnow()
for player in players_data:
player_id = player.get("player_id")
player_name = player.get("player_name")
online_time = player.get("online_time", 0)
if not player_id or not player_name:
continue
# Проверяем, существует ли уже запись
existing_player = await online_players_collection.find_one({
"uuid": player_id,
"server_id": server_id
})
if existing_player:
# Обновляем существующую запись
await online_players_collection.update_one(
{"_id": existing_player["_id"]},
{"$set": {
"username": player_name,
"is_online": True,
"last_seen": now,
"online_duration": online_time
}}
)
else:
# Создаем новую запись
await online_players_collection.insert_one({
"uuid": player_id,
"username": player_name,
"server_id": server_id,
"is_online": True,
"login_time": now,
"last_seen": now,
"online_duration": online_time
})
online_count = len(players_data)
print(f"[{now}] Обновлена информация о {online_count} игроках на сервере {server_ip}")
# Также обновляем информацию о коинах для каждого игрока
if players_data:
from app.services.coins import CoinsService
coins_service = CoinsService()
for player in players_data:
player_id = player.get("player_id")
player_name = player.get("player_name")
online_time = player.get("online_time", 0)
if player_id and player_name:
await coins_service.update_player_coins(player_id, player_name, online_time, server_ip)
async def _register_player_login(self, server_ip, player_id, player_name):
"""Регистрирует вход игрока на сервер"""
from app.db.database import db
online_players_collection = db.online_players
server = await self._register_server(server_ip, {})
server_id = server["id"]
now = datetime.utcnow()
# Проверяем, есть ли уже запись для этого игрока
existing_player = await online_players_collection.find_one({
"uuid": player_id,
"server_id": server_id
})
if existing_player:
# Обновляем запись
await online_players_collection.update_one(
{"_id": existing_player["_id"]},
{"$set": {
"username": player_name,
"is_online": True,
"login_time": now,
"last_seen": now
}}
)
else:
# Создаем новую запись
await online_players_collection.insert_one({
"uuid": player_id,
"username": player_name,
"server_id": server_id,
"is_online": True,
"login_time": now,
"last_seen": now,
"online_duration": 0
})
print(f"[{now}] Игрок {player_name} зашел на сервер {server_ip}")
async def _register_player_logout(self, server_ip, player_id, player_name):
"""Регистрирует выход игрока с сервера"""
from app.db.database import db
online_players_collection = db.online_players
server = await self._register_server(server_ip, {})
server_id = server["id"]
now = datetime.utcnow()
# Ищем запись игрока
player = await online_players_collection.find_one({
"uuid": player_id,
"server_id": server_id
})
if player:
# Обновляем запись
await online_players_collection.update_one(
{"_id": player["_id"]},
{"$set": {
"is_online": False,
"last_seen": now
}}
)
print(f"[{now}] Игрок {player_name} вышел с сервера {server_ip}")
async def _process_player_session(self, server_ip, player_id, player_name, duration):
"""Обрабатывает информацию о завершенной сессии игрока"""
from app.db.database import db
from app.services.coins import CoinsService
server = await self._register_server(server_ip, {})
server_id = server["id"]
# Обновляем статистику времени игры
await db.player_sessions.insert_one({
"uuid": player_id,
"username": player_name,
"server_id": server_id,
"server_ip": server_ip,
"duration": duration,
"session_end": datetime.utcnow()
})
# Начисляем коины за время игры
coins_service = CoinsService()
await coins_service.update_player_coins(player_id, player_name, duration, server_ip)
print(f"[{datetime.now()}] Сессия игрока {player_name} завершена, длительность: {duration} сек.")