WIP: Current state before PVP combat investigation
This commit is contained in:
125
api/database.py
125
api/database.py
@@ -2190,3 +2190,128 @@ async def remove_expired_dropped_items(timestamp_limit: float) -> int:
|
||||
result = await session.execute(stmt)
|
||||
await session.commit()
|
||||
return result.rowcount
|
||||
|
||||
# ============================================================================
|
||||
# PVP COMBAT FUNCTIONS
|
||||
# ============================================================================
|
||||
|
||||
async def get_pvp_combat_by_id(combat_id: int) -> Optional[Dict[str, Any]]:
|
||||
"""Get PVP combat by ID."""
|
||||
async with DatabaseSession() as session:
|
||||
stmt = select(pvp_combats).where(pvp_combats.c.id == combat_id)
|
||||
result = await session.execute(stmt)
|
||||
row = result.first()
|
||||
return dict(row._mapping) if row else None
|
||||
|
||||
|
||||
async def get_pvp_combat_by_player(character_id: int) -> Optional[Dict[str, Any]]:
|
||||
"""Get active PVP combat for a player (either as attacker or defender)."""
|
||||
async with DatabaseSession() as session:
|
||||
stmt = select(pvp_combats).where(
|
||||
and_(
|
||||
or_(
|
||||
pvp_combats.c.attacker_character_id == character_id,
|
||||
pvp_combats.c.defender_character_id == character_id
|
||||
),
|
||||
# If acknowledged by both, it's effectively over for query purposes
|
||||
# But here we want the active one.
|
||||
# Logic: If I am attacker, and I haven't acknowledged => active
|
||||
# If I am defender, and I haven't acknowledged => active
|
||||
# Simplified: Just return the record, caller handles logic.
|
||||
)
|
||||
)
|
||||
result = await session.execute(stmt)
|
||||
# There should only be one active combat at a time per player
|
||||
row = result.first()
|
||||
return dict(row._mapping) if row else None
|
||||
|
||||
|
||||
async def create_pvp_combat(
|
||||
attacker_id: int,
|
||||
defender_id: int,
|
||||
location_id: str,
|
||||
turn_timeout: int = 300
|
||||
) -> Dict[str, Any]:
|
||||
"""Create a new PVP combat encounter."""
|
||||
import time
|
||||
async with DatabaseSession() as session:
|
||||
current_time = time.time()
|
||||
|
||||
# Get names for denormalization
|
||||
attacker_res = await session.execute(select(characters.c.name).where(characters.c.id == attacker_id))
|
||||
defender_res = await session.execute(select(characters.c.name).where(characters.c.id == defender_id))
|
||||
|
||||
attacker_name = attacker_res.scalar() or "Unknown"
|
||||
defender_name = defender_res.scalar() or "Unknown"
|
||||
|
||||
stmt = insert(pvp_combats).values(
|
||||
attacker_character_id=attacker_id,
|
||||
defender_character_id=defender_id,
|
||||
attacker_name=attacker_name,
|
||||
defender_name=defender_name,
|
||||
location_id=location_id,
|
||||
started_at=current_time,
|
||||
updated_at=current_time,
|
||||
turn='defender', # Defender goes first usually, or random? 'initiator pays price?'
|
||||
# Requirement says: "You have initiated combat... They get the first turn."
|
||||
turn_started_at=current_time,
|
||||
turn_timeout_seconds=turn_timeout,
|
||||
attacker_acknowledged=False,
|
||||
defender_acknowledged=False
|
||||
).returning(pvp_combats)
|
||||
|
||||
result = await session.execute(stmt)
|
||||
await session.commit()
|
||||
return dict(result.fetchone()._mapping)
|
||||
|
||||
|
||||
async def update_pvp_combat(combat_id: int, updates: Dict[str, Any]) -> bool:
|
||||
"""Update PVP combat state."""
|
||||
import time
|
||||
updates['updated_at'] = time.time()
|
||||
|
||||
async with DatabaseSession() as session:
|
||||
stmt = update(pvp_combats).where(
|
||||
pvp_combats.c.id == combat_id
|
||||
).values(**updates)
|
||||
await session.execute(stmt)
|
||||
await session.commit()
|
||||
return True
|
||||
|
||||
|
||||
async def acknowledge_pvp_combat(combat_id: int, player_id: int) -> bool:
|
||||
"""Player acknowledges combat end."""
|
||||
async with DatabaseSession() as session:
|
||||
# First check who this player is
|
||||
stmt = select(pvp_combats).where(pvp_combats.c.id == combat_id)
|
||||
result = await session.execute(stmt)
|
||||
combat = result.first()
|
||||
|
||||
if not combat:
|
||||
return False
|
||||
|
||||
updates = {}
|
||||
if combat.attacker_character_id == player_id:
|
||||
updates['attacker_acknowledged'] = True
|
||||
elif combat.defender_character_id == player_id:
|
||||
updates['defender_acknowledged'] = True
|
||||
else:
|
||||
return False
|
||||
|
||||
stmt = update(pvp_combats).where(
|
||||
pvp_combats.c.id == combat_id
|
||||
).values(**updates)
|
||||
|
||||
await session.execute(stmt)
|
||||
|
||||
# Check if both acknowledged, then delete?
|
||||
# Or just keep it. We have acknowledge flags.
|
||||
# If both acknowledged, maybe delete to clean up?
|
||||
# Let's check updated flags
|
||||
if (updates.get('attacker_acknowledged') or combat.attacker_acknowledged) and \
|
||||
(updates.get('defender_acknowledged') or combat.defender_acknowledged):
|
||||
delete_stmt = delete(pvp_combats).where(pvp_combats.c.id == combat_id)
|
||||
await session.execute(delete_stmt)
|
||||
|
||||
await session.commit()
|
||||
return True
|
||||
|
||||
Reference in New Issue
Block a user