rom24-quickmud-python 2.1.0__py3-none-any.whl → 2.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
mud/net/connection.py CHANGED
@@ -1448,6 +1448,214 @@ async def _select_character(
1448
1448
  await _send_line(conn, "Failed to load that character. Please try again.")
1449
1449
 
1450
1450
 
1451
+ async def handle_connection_with_stream(
1452
+ conn: TelnetStream,
1453
+ host_for_ban: str | None = None,
1454
+ connection_type: str = "Telnet",
1455
+ ) -> None:
1456
+ """
1457
+ Handle a connection using a pre-created stream object (TelnetStream or SSHStream).
1458
+
1459
+ This function is used by SSH and other connection types that create their own
1460
+ stream wrapper before calling the connection handler.
1461
+
1462
+ Args:
1463
+ conn: Pre-created TelnetStream or SSHStream object
1464
+ host_for_ban: IP address for ban checking (optional)
1465
+ connection_type: Type of connection for logging (default: "Telnet")
1466
+ """
1467
+ session = None
1468
+ char = None
1469
+ account: PlayerAccount | None = None
1470
+ username = ""
1471
+
1472
+ # Set peer host if not already set
1473
+ if host_for_ban and not conn.peer_host:
1474
+ conn.peer_host = host_for_ban
1475
+
1476
+ permit_banned = bool(host_for_ban and bans.is_host_banned(host_for_ban, BanFlag.PERMIT))
1477
+ newbie_banned = bool(host_for_ban and bans.is_host_banned(host_for_ban, BanFlag.NEWBIES))
1478
+ qmconfig = get_qmconfig()
1479
+
1480
+ try:
1481
+ if host_for_ban and bans.is_host_banned(host_for_ban, BanFlag.ALL):
1482
+ await conn.send_line("Your site has been banned from this mud.")
1483
+ return
1484
+
1485
+ await conn.negotiate()
1486
+ if qmconfig.ansiprompt:
1487
+ ansi_result = await _prompt_ansi_preference(conn)
1488
+ if ansi_result is None:
1489
+ return
1490
+ ansi_preference, ansi_explicit = ansi_result
1491
+ else:
1492
+ ansi_preference = qmconfig.ansicolor
1493
+ ansi_explicit = False
1494
+ conn.set_ansi(ansi_preference)
1495
+ await _send_help_greeting(conn)
1496
+
1497
+ login_result = await _run_account_login(conn, host_for_ban)
1498
+ if not login_result:
1499
+ return
1500
+ account, username, was_reconnect = login_result
1501
+
1502
+ selection = await _select_character(
1503
+ conn,
1504
+ account,
1505
+ username,
1506
+ permit_banned=permit_banned,
1507
+ newbie_banned=newbie_banned,
1508
+ )
1509
+ if selection is None:
1510
+ return
1511
+
1512
+ char, is_creation = selection
1513
+ if char is None:
1514
+ return
1515
+
1516
+ if is_creation and not was_reconnect:
1517
+ if account.id:
1518
+ char.account_id = account.id
1519
+ char.account_name = username
1520
+ try:
1521
+ save_character(char)
1522
+ except Exception as exc:
1523
+ print(f"[ERROR] Failed to save newly created character: {exc}")
1524
+
1525
+ char.connection = conn
1526
+ char.desc = conn
1527
+
1528
+ # Create a mock StreamReader for SSH connections (Session requires it but SSH doesn't use it)
1529
+ mock_reader = asyncio.StreamReader()
1530
+
1531
+ session = Session(
1532
+ name=char.name or "",
1533
+ character=char,
1534
+ reader=mock_reader,
1535
+ connection=conn,
1536
+ account_name=username,
1537
+ ansi_enabled=conn.ansi_enabled,
1538
+ )
1539
+ SESSIONS[char.name] = session
1540
+
1541
+ print(f"[{connection_type}] {char.name} entered the game")
1542
+
1543
+ # Send welcome messages
1544
+ try:
1545
+ if is_creation:
1546
+ # New character - send MOTD and newbie help
1547
+ await send_to_char(char, "Character created successfully!")
1548
+ if _should_send_newbie_help(char):
1549
+ await _send_newbie_help(char)
1550
+ elif was_reconnect:
1551
+ await send_to_char(char, RECONNECT_MESSAGE)
1552
+
1553
+ # Announce login
1554
+ note_reminder = _announce_login_or_reconnect(char, host_for_ban, was_reconnect)
1555
+ if was_reconnect and note_reminder:
1556
+ await send_to_char(
1557
+ char,
1558
+ "You have a note in progress. Type NWRITE to continue it.",
1559
+ )
1560
+ except Exception as exc:
1561
+ print(f"[ERROR] Failed to send welcome messages for {session.name}: {exc}")
1562
+
1563
+ # Send initial room look
1564
+ try:
1565
+ if char.room:
1566
+ response = process_command(char, "look")
1567
+ await send_to_char(char, response)
1568
+ else:
1569
+ await send_to_char(char, "You are floating in a void...")
1570
+ except Exception as exc:
1571
+ print(f"[ERROR] Failed to send initial look: {exc}")
1572
+ await send_to_char(char, "Welcome to the world!")
1573
+
1574
+ # Main game loop
1575
+ while True:
1576
+ try:
1577
+ await asyncio.sleep(0.1)
1578
+ if not char or not char.room:
1579
+ break
1580
+
1581
+ if session.command_queue:
1582
+ try:
1583
+ cmd = session.command_queue.pop(0)
1584
+ result = await interpret_command(char, cmd)
1585
+ if result and len(result) < 6000:
1586
+ await send_to_char(char, result)
1587
+ elif result:
1588
+ await send_to_char(
1589
+ char,
1590
+ "Sorry, there was an error processing that command.",
1591
+ )
1592
+ except Exception as exc:
1593
+ print(f"[ERROR] Command execution error: {exc}")
1594
+ await send_to_char(
1595
+ char,
1596
+ "Sorry, there was an error processing that command.",
1597
+ )
1598
+
1599
+ while char and char.messages:
1600
+ try:
1601
+ msg = char.messages.pop(0)
1602
+ await send_to_char(char, msg)
1603
+ except Exception as exc:
1604
+ print(f"[ERROR] Failed to send message: {exc}")
1605
+ break
1606
+
1607
+ except asyncio.CancelledError:
1608
+ break
1609
+ except Exception as exc:
1610
+ print(f"[ERROR] Connection loop error for {session.name if session else 'unknown'}: {exc}")
1611
+ break
1612
+
1613
+ except Exception as exc:
1614
+ print(f"[ERROR] {connection_type} connection handler error: {exc}")
1615
+ finally:
1616
+ forced_disconnect = bool(session and getattr(session, "_forced_disconnect", False))
1617
+ try:
1618
+ if char and not forced_disconnect:
1619
+ announce_wiznet_logout(char)
1620
+ except Exception as exc:
1621
+ print(f"[ERROR] Failed to announce wiznet logout for {session.name if session else 'unknown'}: {exc}")
1622
+
1623
+ try:
1624
+ if char and not forced_disconnect:
1625
+ save_character(char)
1626
+ except Exception as exc:
1627
+ print(f"[ERROR] Failed to save character: {exc}")
1628
+
1629
+ try:
1630
+ if char and char.room and not forced_disconnect:
1631
+ char.room.remove_character(char)
1632
+ except Exception as exc:
1633
+ print(f"[ERROR] Failed to remove character from room: {exc}")
1634
+
1635
+ if session and not forced_disconnect and session.name in SESSIONS:
1636
+ SESSIONS.pop(session.name, None)
1637
+
1638
+ if char:
1639
+ if not forced_disconnect:
1640
+ char.desc = None
1641
+ try:
1642
+ char.account_name = ""
1643
+ except Exception:
1644
+ pass
1645
+ if getattr(char, "connection", None) is conn:
1646
+ char.connection = None
1647
+
1648
+ if username and not forced_disconnect:
1649
+ release_account(username)
1650
+
1651
+ try:
1652
+ await conn.close()
1653
+ except Exception as exc:
1654
+ print(f"[ERROR] Failed to close connection: {exc}")
1655
+
1656
+ print(f"[{connection_type} DISCONNECT] {session.name if session else 'unknown'}")
1657
+
1658
+
1451
1659
  async def handle_connection(reader: asyncio.StreamReader, writer: asyncio.StreamWriter) -> None:
1452
1660
  addr = writer.get_extra_info("peername")
1453
1661
  host_for_ban: str | None = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rom24-quickmud-python
3
- Version: 2.1.0
3
+ Version: 2.1.1
4
4
  Summary: A modern Python port of the ROM 2.4b6 MUD engine with full telnet server and JSON world loading
5
5
  Author-email: Mark Jedrzejczyk <mark.jedrzejczyk@gmail.com>
6
6
  Maintainer-email: Mark Jedrzejczyk <mark.jedrzejczyk@gmail.com>
@@ -158,7 +158,7 @@ python -m mud # Start development server
158
158
 
159
159
  ## 🎯 Project Status
160
160
 
161
- - **Version**: 2.1.0 (Production Ready)
161
+ - **Version**: 2.1.1 (Production Ready)
162
162
  - **ROM 2.4b Parity**: 100% (227/227 behavioral tests passing)
163
163
  - **ROM C Function Coverage**: 96.1% (716/745 functions mapped)
164
164
  - **Test Coverage**: 1435/1436 tests passing (99.93% success rate)
@@ -159,7 +159,7 @@ mud/models/social_json.py,sha256=_dir6JDEMN3m4qERdbX4xveoga-YdRic7tLhpiHCfK4,447
159
159
  mud/music/__init__.py,sha256=QKXSuF6XcqoR22e9qAKjK8cYL2H0MveikdlF1cwA0_A,4435
160
160
  mud/net/__init__.py,sha256=LHCpGaVl9a5SqH396-1yngVEyNZSxWmaT62d-Ry5sms,178
161
161
  mud/net/ansi.py,sha256=ron4xslwKoAM2Y1tkfYHTL8tXiXkHyVv5cDEfyyrFaw,1128
162
- mud/net/connection.py,sha256=TH7fT1rW5A47W164J_IuWfxdf1Au55FTqiKtZ0M-rVQ,58602
162
+ mud/net/connection.py,sha256=NOjOxTeNZ48L9o-6wmnRRF4FEfj3wEnKJePRdG7uMHI,66203
163
163
  mud/net/protocol.py,sha256=ImgMHwTcxYD2xgQ5SNOsGhiu7FwtB-pfms1KE4hCeXY,2760
164
164
  mud/net/session.py,sha256=U09R5agaguFqJNn6IoUbVNYvW2BhumHA1Q5xhgTaIr0,4779
165
165
  mud/net/ssh_server.py,sha256=sg5G3npy5lG96SgyHzE6Yl1I-Xgya05-LDAKmut0lmo,10629
@@ -200,9 +200,9 @@ mud/world/movement.py,sha256=Y7it7pXrPORgKyy2tRB8br_kb4-s9UK-gj0N-E2U9oM,18695
200
200
  mud/world/obj_find.py,sha256=7QjVAhA-XEqAEm0CoanNtBuYj6rKijNSu8Vu1JcueMY,4304
201
201
  mud/world/vision.py,sha256=q8VjzSzm0cbNrHX6-o0j1UG-jlcM3Z9bzUxK6T-Bsi8,9862
202
202
  mud/world/world_state.py,sha256=W9ABMADlY5H-ZmywACsryFKZp34OufjzMRD6WT331qg,7917
203
- rom24_quickmud_python-2.1.0.dist-info/licenses/LICENSE,sha256=anQ2j9As6sIC8tZgQCXbo0-09JDH9vPiqhA9djnOvkY,1078
204
- rom24_quickmud_python-2.1.0.dist-info/METADATA,sha256=Vyf_RX2VhMNrNaGACOcc0QkCYAAbd0SiMjojtL9wPW8,13934
205
- rom24_quickmud_python-2.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
206
- rom24_quickmud_python-2.1.0.dist-info/entry_points.txt,sha256=VFru08UQTXZA_CkK-NBjJmWHyEX5a3864fQHjhaojbw,41
207
- rom24_quickmud_python-2.1.0.dist-info/top_level.txt,sha256=Fk1WPmabIIjp7_iZXLYpbAVqiq7lG7TeAHt30AsOKtQ,4
208
- rom24_quickmud_python-2.1.0.dist-info/RECORD,,
203
+ rom24_quickmud_python-2.1.1.dist-info/licenses/LICENSE,sha256=anQ2j9As6sIC8tZgQCXbo0-09JDH9vPiqhA9djnOvkY,1078
204
+ rom24_quickmud_python-2.1.1.dist-info/METADATA,sha256=TdN0k96Tz-z5rx3ZmAvbYpsOKBXeiH5ttdRI0j4XYwA,13934
205
+ rom24_quickmud_python-2.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
206
+ rom24_quickmud_python-2.1.1.dist-info/entry_points.txt,sha256=VFru08UQTXZA_CkK-NBjJmWHyEX5a3864fQHjhaojbw,41
207
+ rom24_quickmud_python-2.1.1.dist-info/top_level.txt,sha256=Fk1WPmabIIjp7_iZXLYpbAVqiq7lG7TeAHt30AsOKtQ,4
208
+ rom24_quickmud_python-2.1.1.dist-info/RECORD,,