Compare commits

...

4 commits

3 changed files with 39 additions and 12 deletions

View file

@ -3,6 +3,7 @@
from typing import Any from typing import Any
from mudlib.commands import CommandDefinition, register from mudlib.commands import CommandDefinition, register
from mudlib.entity import Entity
from mudlib.player import Player, players from mudlib.player import Player, players
# World instance will be injected by the server # World instance will be injected by the server
@ -69,8 +70,7 @@ async def move_player(player: Player, dx: int, dy: int, direction_name: str) ->
# Check if the target is passable # Check if the target is passable
if not world.is_passable(target_x, target_y): if not world.is_passable(target_x, target_y):
player.writer.write("You can't go that way.\r\n") await player.send("You can't go that way.\r\n")
await player.writer.drain()
return return
# Send departure message to players in the old area # Send departure message to players in the old area
@ -94,11 +94,11 @@ async def move_player(player: Player, dx: int, dy: int, direction_name: str) ->
await cmd_look(player, "") await cmd_look(player, "")
async def send_nearby_message(player: Player, x: int, y: int, message: str) -> None: async def send_nearby_message(entity: Entity, x: int, y: int, message: str) -> None:
"""Send a message to all players near a location, excluding the player. """Send a message to all players near a location, excluding the entity.
Args: Args:
player: The player who triggered the message (excluded from receiving it) entity: The entity who triggered the message (excluded from receiving it)
x: X coordinate of the location x: X coordinate of the location
y: Y coordinate of the location y: Y coordinate of the location
message: The message to send message: The message to send
@ -107,7 +107,7 @@ async def send_nearby_message(player: Player, x: int, y: int, message: str) -> N
viewport_range = 10 viewport_range = 10
for other in players.values(): for other in players.values():
if other.name == player.name: if other.name == entity.name:
continue continue
# Check if other player is within viewport range (wrapping) # Check if other player is within viewport range (wrapping)
@ -116,8 +116,7 @@ async def send_nearby_message(player: Player, x: int, y: int, message: str) -> N
dx_dist = min(dx_dist, world.width - dx_dist) dx_dist = min(dx_dist, world.width - dx_dist)
dy_dist = min(dy_dist, world.height - dy_dist) dy_dist = min(dy_dist, world.height - dy_dist)
if dx_dist <= viewport_range and dy_dist <= viewport_range: if dx_dist <= viewport_range and dy_dist <= viewport_range:
other.writer.write(message) await other.send(message)
await other.writer.drain()
# Define individual movement command handlers # Define individual movement command handlers

24
src/mudlib/entity.py Normal file
View file

@ -0,0 +1,24 @@
"""Base entity class for characters in the world."""
from dataclasses import dataclass
@dataclass
class Entity:
"""Base class for anything with position and identity in the world."""
name: str
x: int
y: int
async def send(self, message: str) -> None:
"""Send a message to this entity. Base implementation is a no-op."""
pass
@dataclass
class Mob(Entity):
"""Represents a non-player character (NPC) in the world."""
description: str = ""
alive: bool = True

View file

@ -3,14 +3,13 @@
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Any from typing import Any
from mudlib.entity import Entity
@dataclass @dataclass
class Player: class Player(Entity):
"""Represents a connected player.""" """Represents a connected player."""
name: str
x: int # position in world
y: int
writer: Any # telnetlib3 TelnetWriter for sending output writer: Any # telnetlib3 TelnetWriter for sending output
reader: Any # telnetlib3 TelnetReader for reading input reader: Any # telnetlib3 TelnetReader for reading input
flying: bool = False flying: bool = False
@ -21,6 +20,11 @@ class Player:
"""Current mode is the top of the stack.""" """Current mode is the top of the stack."""
return self.mode_stack[-1] return self.mode_stack[-1]
async def send(self, message: str) -> None:
"""Send a message to the player via their telnet writer."""
self.writer.write(message)
await self.writer.drain()
# Global registry of connected players # Global registry of connected players
players: dict[str, Player] = {} players: dict[str, Player] = {}