tweaks for server using serialization

This commit is contained in:
2026-01-26 10:11:44 +01:00
parent 6e14cb65c3
commit 0504e90754
8 changed files with 90 additions and 43 deletions

102
server.py
View File

@@ -7,7 +7,9 @@ from player import Player
from item import Item
from game import Game
from npc import NPC
from serializable import Serializable
import json
import os
mcp = FastMCP("wyvern-castle")
game = Game()
@@ -19,6 +21,32 @@ logging.basicConfig(
]
)
# History file path
HISTORY_FILE = "game_history.json"
def append_to_history(event: Dict[str, Any]):
"""Append a game event to the history file."""
history = []
if os.path.exists(HISTORY_FILE):
with open(HISTORY_FILE, "r", encoding="utf-8") as f:
try:
history = json.load(f)
except json.JSONDecodeError:
history = []
history.append(event)
with open(HISTORY_FILE, "w", encoding="utf-8") as f:
json.dump(history, f, ensure_ascii=False, indent=2)
def read_history() -> list:
"""Read the game history from the file."""
if os.path.exists(HISTORY_FILE):
with open(HISTORY_FILE, "r", encoding="utf-8") as f:
try:
return json.load(f)
except json.JSONDecodeError:
return []
return []
@mcp.tool()
async def throw_a_dice(n_faces: int) -> Any:
"""Throw a dice with n faces. If n==2 its a coin toss.
@@ -27,7 +55,7 @@ async def throw_a_dice(n_faces: int) -> Any:
n_faces: Number of faces of the dice
"""
logging.info(f"Throwing a dice with {n_faces} faces")
dice = Dice()
dice = Dice(n_faces)
if n_faces < 1:
raise ValueError("Number of faces must be at least 1")
@@ -36,36 +64,12 @@ async def throw_a_dice(n_faces: int) -> Any:
elif n_faces == 2:
return dice.head_or_tails()
else:
return dice.roll(n_faces)
return dice.roll()
@mcp.tool()
async def mult(a: int, b: int) -> int:
"""Multiply two numbers.
Args:
a: First number
b: Second number
"""
logging.info(f"Calling mult with a={a}, b={b}")
result = a * b
logging.info(f"mult result: {result}")
return result
@mcp.tool()
async def add(a: int, b: int) -> int:
"""Add two numbers.
Args:
a: First number
b: Second number
"""
logging.info(f"Calling add with a={a}, b={b}")
result = a + b
logging.info(f"add result: {result}")
return result
@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 = None) -> Dict[str, Any]:
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]:
"""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.
@@ -84,10 +88,11 @@ async def create_player(name: str, strength: int, dexterity: int, intelligence:
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.players.append(player)
return player.serialize_dict()
@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 = None) -> 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: str = "") -> Dict[str, Any]:
"""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.
@@ -106,6 +111,7 @@ async def create_npc(name: str, strength: int, dexterity: int, intelligence: int
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.npcs.append(npc)
return npc.serialize_dict()
@mcp.tool()
@@ -120,6 +126,7 @@ async def create_item(name: str, description: str, bonus: str) -> Dict[str, Any]
logging.info(f"Creating item with name={name}")
item = Item(name, description, bonus)
logging.info(f"Created item: {item}")
game.items.append(item)
return item.serialize_dict()
@mcp.tool()
@@ -133,6 +140,39 @@ async def add_item_to_player(player_name: str, item_name: str) -> Dict[str, Any]
logging.info(f"Adding item {item_name} to player {player_name}")
return {"status": "Item added"}
@mcp.tool()
async def save_game_state() -> str:
"""Save the current game state to a persistent storage each time
the game state is modified."""
logging.info("Saving game state")
with open("game_state.json", "w", encoding="utf-8") as f:
f.write(game.serialize())
return "Game state saved to game_state.json"
# Example MCP tool to add an event to history
@mcp.tool()
async def add_event_to_history(event: Dict[str, Any]) -> str:
"""Add a game event to the history resource."""
append_to_history(event)
return "Event added to history."
# Example MCP tool to read history
@mcp.tool()
async def get_game_history() -> list:
"""Get the full game history."""
return read_history()
@mcp.tool()
async def purge_game_history_and_state() -> str:
"""Purge the game history and state files when the player is starting a new game."""
if os.path.exists(HISTORY_FILE):
os.remove(HISTORY_FILE)
if os.path.exists("game_state.json"):
os.remove("game_state.json")
return "Game history and state purged."
def main():
# Initialize and run the server
mcp.run(transport="stdio")