Merging from api

This commit is contained in:
KuMiShi
2026-01-30 17:08:55 +01:00
12 changed files with 461 additions and 163 deletions

130
server.py
View File

@@ -1,18 +1,26 @@
# Game imports
from utils.dice import Dice
from utils.game import Game
from utils.serializable import Serializable
from events.event import Event
# Native imports
from typing import Any, Dict
import logging
import httpx
from mcp.server.fastmcp import FastMCP
from utils.dice import Dice
from entities.player import Player
from items.item import Item
from game import Game
from entities.npc import NPC
from serializable import Serializable
import json
import os
# Constants
HISTORY_FILE = "game_history.json"
SAVE_PATH = "save_"
# Global Parameters
mcp = FastMCP("wyvern-castle")
game: Game = None
# Logging config
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
@@ -21,10 +29,7 @@ logging.basicConfig(
]
)
# Constants
HISTORY_FILE = "game_history.json"
SAVE_PATH = "save_"
# SAVING & LOADING GAME STATE
@mcp.tool()
async def load_game(slot:int):
"""Loads an already existing game.
@@ -69,6 +74,7 @@ async def save_game(slot:int):
"error": str(e)
}
@DeprecationWarning
def append_to_history(event: Dict[str, Any]):
"""Append a game event to the history file."""
history = []
@@ -82,6 +88,7 @@ def append_to_history(event: Dict[str, Any]):
with open(HISTORY_FILE, "w", encoding="utf-8") as f:
json.dump(history, f, ensure_ascii=False, indent=2)
@DeprecationWarning
def read_history() -> list:
"""Read the game history from the file."""
if os.path.exists(HISTORY_FILE):
@@ -92,6 +99,26 @@ def read_history() -> list:
return []
return []
# EVENTS TOOLS
@mcp.tool()
async def start_event(location:str, initial_description:str, entity_list:list[str]):
new_event = Event(location=location, initial_description=initial_description, entities=entity_list)
game.add_event(new_event)
@mcp.tool()
async def perform_action():
pass
# ITEM TOOLS
@mcp.tool()
async def create_item():
pass
@mcp.tool()
async def add_item_to_entity():
pass
# OTHER UTILS
@mcp.tool()
async def throw_a_dice(n_faces: int) -> Any:
"""Throw a dice with n faces. If n==2 its a coin toss.
@@ -102,18 +129,27 @@ async def throw_a_dice(n_faces: int) -> Any:
logging.info(f"Throwing a dice with {n_faces} faces")
if n_faces < 1:
raise ValueError("Number of faces must be at least 1")
elif n_faces == 1:
return 1
return {
"success": False,
"error": "Number of faces must be at least 1"
}
elif n_faces == 2:
return Dice.head_or_tails()
return {
"success": True,
"toss_result": Dice.head_or_tails()
}
else:
return Dice.roll(n_faces)
return {
"success": True,
"roll_result": Dice.roll(n_faces)
}
@mcp.tool()
async def create_player(name: str, strength: int, dexterity: int, intelligence: int, wisdom: int, charisma: int, hp: int, armor: int, speed: int, item: str = "") -> Dict[str, Any]:
async def get_entity_status():
pass
@mcp.tool()
async def create_player(name: str, strength: int, dexterity: int, intelligence: int, wisdom: int, charisma: int, hp: int, armor: int, speed: int, item_id:str):
"""Create a new player. Need all the stats to function properly. Throw a d20 for every stats you don't have,
and a d6 for hp, armor and speed.
@@ -129,14 +165,25 @@ async def create_player(name: str, strength: int, dexterity: int, intelligence:
speed: Speed of the player
item: Item carried by the player
"""
logging.info(f"Creating player with name={name}")
player = Player(name, strength, dexterity, intelligence, wisdom, charisma, hp, armor, speed)
logging.info(f"Created player: {player}")
game.active_players.append(player)
return player.serialize_dict()
logging.info(f"Creating NPC named {name}")
try:
player_id = game.create_player(name=name, strength=strength, dexterity=dexterity, intelligence=intelligence, wisdom=wisdom, charisma=charisma, hp=hp, armor=armor, speed=speed)
game.add_item_to_entity(item_id=item_id, entity_id=player_id)
player_dict = game.get_player(player_id=player_id).serialize()
logging.info(f"Creation of NPC successful")
return {
"success": True,
"npc_properties": player_dict
}
except ReferenceError as e:
logging.info(f"ReferenceError: " + str(e))
return {
"success": False,
"error": str(e)
}
@mcp.tool()
async def create_npc(name: str, strength: int, dexterity: int, intelligence: int, wisdom: int, charisma: int, hp: int, armor: int, speed: int, item: str = "") -> Dict[str, Any]:
async def create_npc(name: str, strength: int, dexterity: int, intelligence: int, wisdom: int, charisma: int, hp: int, armor: int, speed: int, item_id:str):
"""Create a new NPC. Need all the stats to function properly. Throw a d20 for every stats you don't have,
and a d6 for hp, armor and speed.
@@ -152,14 +199,25 @@ async def create_npc(name: str, strength: int, dexterity: int, intelligence: int
speed: Speed of the NPC
item: Item carried by the NPC
"""
logging.info(f"Creating NPC with name={name}")
npc = NPC(name, strength, dexterity, intelligence, wisdom, charisma, hp, armor, speed)
logging.info(f"Created NPC: {npc}")
game.active_npcs.append(npc)
return npc.serialize_dict()
logging.info(f"Creating NPC named {name}")
try:
npc_id = game.create_npc(name=name, strength=strength, dexterity=dexterity, intelligence=intelligence, wisdom=wisdom, charisma=charisma, hp=hp, armor=armor, speed=speed)
game.add_item_to_entity(item_id=item_id, entity_id=npc_id)
npc_dict = game.get_npc(npc_id=npc_id).serialize()
logging.info(f"Creation of NPC successful")
return {
"success": True,
"npc_properties": npc_dict
}
except ReferenceError as e:
logging.info(f"ReferenceError: " + str(e))
return {
"success": False,
"error": str(e)
}
@mcp.tool()
async def create_item(name: str, description: str, bonus: str) -> Dict[str, Any]:
async def create_item(name: str, description: str, stat_modifier: dict[str,int]):
"""Create a new item.
Args:
@@ -167,11 +225,13 @@ async def create_item(name: str, description: str, bonus: str) -> Dict[str, Any]
description: Description of the item
bonus: Bonus of the item ex: strength+1,hp+5
"""
logging.info(f"Creating item with name={name}")
item = Item(name, description, bonus)
logging.info(f"Created item: {item}")
game.active_items.append(item)
return item.serialize_dict()
logging.info(f"Creating item, name={name} ; description={description}")
item_id = game.create_item(name, description, stat_modifier)
item_dict = game.get_item(item_id).serialize()
return {
"success": True,
"item_properties": item_dict
}
@mcp.tool()
async def add_item_to_player(player_name: str, item_name: str) -> Dict[str, Any]: