Commit Graph

35 Commits

Author SHA1 Message Date
031428add6 Implement process-forwarding WebSocket architecture
New simplified approach: WebSocket server spawns bin/game process and forwards I/O

Backend Changes:
- New GameProcessServer class (src/Core/GameProcessServer.php)
  - Implements MessageComponentInterface (Ratchet)
  - For each WebSocket connection, spawns independent php bin/game process
  - Uses proc_open() to manage process I/O pipes
  - Reads process STDOUT/STDERR in non-blocking mode
  - Writes client input to process STDIN
  - Automatic process cleanup on disconnect
  - No game code modifications required

- New websocket-process-server.php startup script
  - Listens on port 9002
  - Simple process forwarder without game-specific logic
  - Suitable for any interactive CLI application

Frontend Changes:
- New web/process.html
  - Ultra-simple WebSocket frontend for process I/O
  - Direct STDIN/STDOUT forwarding
  - ANSI color support via xterm.js
  - Minimal dependencies, minimal code
  - Suitable for any CLI game/application

Architecture Benefits:
✓ Zero game code changes needed
✓ Each user gets independent process (isolation)
✓ Real process STDIO, not emulation
✓ ANSI colors work perfectly
✓ Can run ANY CLI application (not just this game)
✓ Simpler than GameSession-based approach
✓ Easier to deploy and manage

Usage:
1. Start WebSocket server:
   php websocket-process-server.php

2. Start HTTP file server (for static files):
   php -S 0.0.0.0:8080 web/server.php

3. Open browser:
   http://localhost:8080/process.html

Message Protocol:
Client → Server:
  { "type": "input", "input": "command" } - Send stdin to process
  { "type": "ping" } - Heartbeat

Server → Client:
  { "type": "output", "text": "..." } - Process stdout/stderr
  { "type": "system", "message": "..." } - Server messages
  { "type": "error", "message": "..." } - Error messages
  { "type": "pong" } - Heartbeat response

Features:
- Non-blocking I/O reading
- Stream buffering management
- Automatic reconnection support
- 30-second heartbeat for keep-alive
- Process termination on disconnect
- Proper error handling

This is the simplest and most elegant approach for running CLI games on web!

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 13:21:23 +08:00
7308af1c1b Fix web state management: handleInput now returns structured data
Issues fixed:
- GameSession.handleInput() was returning plain text, causing WebSocket frontend
  to lose state information after each input
- GameWebSocketServer.handleGameInput() was calling unnecessary getStateInfo()
- Duplicate state saves in runCurrentState() and handleInput()

Changes:
1. GameSession.php:
   - handleInput() now returns structured array with output + state info
   - runCurrentState() no longer saves state (already done in handleInput)
   - Consistent return format: { output, state, stateName, playerInfo }

2. GameWebSocketServer.php:
   - handleGameInput() simplified to use handleInput() return value
   - Direct merge of result into WebSocket message

3. web/server.php:
   - handleGameInput() simplified to just return handleInput() result
   - No duplicate getStateInfo() call

Results:
- Web frontend now receives complete state info after each input
- State transitions in submenus now work correctly
- No more state desynchronization between client and server

Testing:
- Input in level 3+ menus now executes correctly
- State name updates properly in header
- Player info (HP, etc) stays synchronized

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 13:14:48 +08:00
cf84c53020 Implement WebSocket real-time communication for game
Replace HTTP API with WebSocket for true real-time bidirectional communication:

Backend Changes:
- Add Ratchet WebSocket library (cboden/ratchet) to composer.json
- New GameWebSocketServer class implementing MessageComponentInterface
  - Handles client connections and session management
  - Message types: login, game-input, sync-state, ping/pong
  - Maintains client connections map and user sessions
- New websocket-server.php startup script
  - Listens on port 9001
  - Uses Ratchet with HttpServer wrapper

Frontend Changes:
- New game-ws.html with WebSocket implementation
  - Replace HTTP requests with WebSocket messages
  - Keep HTTP for authentication (login/register/status)
  - WebSocket handles all game interactions
  - Real-time status display with connection indicator
  - Implements reconnection on disconnect
  - 30-second heartbeat (ping/pong) to maintain connection

Message Protocol:
Client → Server:
  login: { userId, username } - Authenticate and load game
  game-input: { input } - Send game command
  sync-state: {} - Request full state sync
  ping - Heart beat

Server → Client:
  welcome - Initial greeting
  login-success - Auth successful, game loaded
  game-output - Normal command output
  battle-start/end - Battle state changes
  state-sync - Full state snapshot
  error - Error message
  pong - Heartbeat response

Port Configuration:
- HTTP API: port 80 (web server)
- WebSocket: port 9001 (Ratchet server)
- Both services run independently

Usage:
1. Start web server: php -S 0.0.0.0:8080 web/server.php
2. Start WebSocket server: php websocket-server.php
3. Open browser: http://localhost:8080/game-ws.html

Benefits:
✓ True bidirectional real-time communication
✓ Can handle battle interactions in-game
✓ Better for multiplayer scenarios
✓ Persistent connections reduce latency
✓ Future support for spectating, PvP

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 12:21:30 +08:00
10e64d4766 Fix web state management: add state metadata to API responses
Issues fixed:
- Remove redundant parameter in handleGameInput (line 195)
- Add getStateInfo() method to GameSession to return current game state
- Return state metadata in both handleGameRender() and handleGameInput()
- Add playerInfo (hp, mana, exp) to responses for UI sync
- Add state name mapping for debugging

Changes:
1. GameSession.php:
   - Rename getPlayerInfo() to include full stats (mana, exp)
   - Add getStateInfo() returning state, stateName, playerInfo
   - Add getStateName() helper to convert state constant to string

2. server.php:
   - Fix handleGameInput() parameter error
   - handleGameRender() now returns state metadata
   - handleGameInput() now returns state metadata

3. index.html (web):
   - Add console.log for debugging state sync
   - Add stateName logging to track state transitions
   - Prepare for renderGame() refresh (commented)

These changes allow:
- Frontend to verify correct game state after each action
- Debugging state sync issues via browser console
- Foundation for state validation in UI

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 11:19:28 +08:00
ac5f57c3ca Fix Screen.php: replace Laravel class_basename with native PHP 2025-12-07 11:11:25 +08:00
cb4b955bca Implement Server-Sent Events (SSE) for real-time battle streaming
Redesign web battle system from buffered to streaming architecture:

Backend Changes:
- New SSEOutput class for real-time event streaming to clients
- GameSession::streamBattle() for SSE-based battle execution
- Enhanced Screen::delay() to support SSE timing and buffering modes
- New /api/game/battle-stream endpoint handling SSE connections

Frontend Changes:
- Enhanced sendInput() to detect battle command (input "1")
- New streamBattle() function using EventSource for SSE connections
- Real-time log display matching terminal experience
- Event handlers for start, message, complete, error events

Benefits:
✓ Real-time streaming instead of waiting for complete battle
✓ Web frontend experience identical to terminal
✓ Lightweight implementation without WebSocket
✓ Automatic browser reconnection support
✓ ANSI colors fully preserved
✓ Backward compatible for non-battle screens

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 10:50:30 +08:00
0658960b70 优化 2025-12-06 22:59:52 +08:00
dabc1f1cd4 修复装备配置并实现自动防护状态功能
- 修复装备配置中硬编码属性值的问题
  * 5处直接指定patk/matk/pdef/mdef的装备改为使用模板
  * 现在装备会正确生成词条和动态属性
  * 装备品质与属性值完全匹配

- 实现战斗中的自动防护状态切换
  * 当自身血量健康(>50%)且队友血量低(<30%)时
  * 自动进入防护状态为队友抗伤
  * 仅在有需要时自动切换,提高战斗智能性
  * 显示战斗信息提示玩家防护状态的激活

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 22:50:06 +08:00
6aedb96342 优化 2025-12-06 20:52:40 +08:00
cd020e1240 Implement base damage calculation system for spells
- Add base and growth values to all 36 spells across heal_single, damage_single, damage_aoe, and heal_aoe categories in spells.php
- Map base values: heal [8, 18, 38, 65], fire [5, 12, 25, 45], ice [4, 10, 22, 42], thunder [6, 14, 28, 48], aoe damage [4-6, 10-14, 22-28, 42-48]
- Map growth rates: heal [0.8, 1.0, 1.2, 1.5], fire [0.6, 0.8, 1.0, 1.2], ice [0.5, 0.7, 0.95, 1.15], thunder [0.7, 0.9, 1.1, 1.3]
- Modify createSpell() in Item.php to calculate final base damage using formula: finalValue = base + (level * growth) + randomBonus(15%)
- All spells now generate with calculated base values that scale with level and quality tier
- This enables proper damage/healing scaling mechanics in combat system

Formula implementation:
- baseValue = spellInfo['base'][$qualityIndex]
- growth = spellInfo['growth'][$qualityIndex]
- randomBonus = rand(0, max(1, (int)($baseValue * 0.15)))
- finalBaseValue = (int)($baseValue + ($level * $growth) + $randomBonus)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 23:01:35 +08:00
82b6b27563 Implement comprehensive spell system with base damage and growth mechanics
- Add 5 spell templates (fire, ice, thunder, heal, defense) with base damage values and growth rates for 4 quality levels (common, rare, epic, legendary)
- Add base values and growth rates to 100+ spell configurations across all 13 maps and 39+ monsters
- Implement dynamic damage calculation: baseValue + (level * growth) + randomBonus
- Ensure all spells reference appropriate templates for proper scaling mechanics
- Follow cultivation stage progression (Qi Refinement → Foundation Establishment → Core Formation → Nascent Soul → Ascension)

This enables spells to scale dynamically with character level and quality tier, providing the foundation for implementing the damage calculation system in game code.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 22:39:40 +08:00
46bf1e0195 为法术系统添加基础数值和属性机制
- 新增火系、冰系、雷系、治疗、防御五大法术模板
- 每个法术模板包含四个品质等级(common/rare/epic/legendary)的基础伤害值
- 添加成长值和随机属性(暴击率、暴击伤害)
- 为所有怪物的法术配置添加品质等级和对应模板
- 法术伤害将随着等级成长,且包含15%的随机属性波动
- 符合《凡人修仙传》的剧情设定,不同品质法术强度差异明显

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 22:05:54 +08:00
hantao
ecee1606f4 技能优化 2025-12-05 18:15:06 +08:00
hantao
c77620127d 技能优化 2025-12-05 17:38:10 +08:00
hantao
1e336cffcd Merge remote-tracking branch 'origin/main'
# Conflicts:
#	.idea/php.xml
2025-12-05 09:39:28 +08:00
hantao
2a4d3c08a5 first 2025-12-05 09:38:15 +08:00
f703c6800c 优化 2025-12-05 00:11:55 +08:00
0e6351d328 抽象:统一法术显示逻辑到 SpellDisplay.php
- ItemDisplay.php:移除 formatSpellCompact() 方法(已在 SpellDisplay 中实现)
- ItemDisplay.php:简化 renderSlot() 方法,移除法术特定逻辑
- ItemDisplay.php:更新 renderListItem() 注释,说明法术由 SpellDisplay 处理
- InventoryPanel.php:增强列表显示,对法术使用 SpellDisplay::formatSpellCompact()
- StatsPanel.php:技能槽位显示改用 SpellDisplay::renderSlot()

结果:
✓ 所有法术显示逻辑已集中到 SpellDisplay.php
✓ ItemDisplay.php 专注于装备显示逻辑
✓ 调用者正确路由:法术→SpellDisplay, 装备→ItemDisplay
✓ 保持向后兼容性,同时提高代码组织性

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 00:02:15 +08:00
c2a2e93ff3 优化 2025-12-04 23:52:50 +08:00
ba273b2cdf 技能掉落系统:为地图中的技能添加掉落概率配置
新增功能:
- maps.php:为所有怪物技能添加 rate 字段
  - 单技能怪物:25-30% 概率
  - 多技能怪物:按位置递减 (30% → 25% → 20% → 15% → 10%)
- Monster.generateSpells():支持技能的 rate 字段
  - 存储掉落概率到法术对象的 dropRate 字段
  - 格式1和格式2都支持
- Monster.getRandomSpellDrops():使用法术配置的掉落概率
  - 优先使用法术的 dropRate 字段
  - 如果未指定则使用默认值(50%)

改进内容:
- 技能掉落概率与装备掉落概率管理方式统一
- 支持Boss技能更高的掉落概率
- 普通怪物技能掉落概率略低于装备
- 13个地图、100+个怪物配置已更新

掉落概率配置示例:
- 野狼帮帮众(1个技能):柔拳 rate=25
- 野狼帮精锐(2个技能):刀气切割 rate=30, 寒冰爆裂 rate=25
- Boss怪物技能:rate=40-50

🧙 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 23:32:56 +08:00
911f814581 角色面板增强:技能槽位显示法术的计算方式和基础数值
新增功能:
- ItemDisplay.renderSlot: 增强支持法术物品显示
  - 法术显示计算方式描述
  - 法术显示品质相关的基础数值
  - 法术显示消耗(含强化后的实际消耗)
  - 装备仍显示属性和词条(无改动)
- StatsPanel 导入 SpellDisplay 以支持未来扩展

改进内容:
- 角色面板技能栏显示法术的详细信息
- 显示14种计算方式的完整描述
- 显示伤害倍数或治疗系数(根据品质)
- 显示强化前后的魔法消耗变化
- 保持与战斗系统显示的一致性

显示格式示例:
[技能1] 火球术 Lv.5 +2
  计算: 基于魔攻
  倍数: 2.0x
  消耗: 20 → 16

[技能2] 恢复术 Lv.3
  计算: 基于魔攻
  治疗: 0.8x + 40
  消耗: 15

🧙 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 23:11:49 +08:00
ab90eb8435 背包和物品列表增强:支持显示法术的计算方式和基础数值
新增功能:
- ItemDisplay.formatSpellCompact: 格式化法术的简洁信息
  - 显示计算方式(缩写形式)
  - 显示品质相关的基础数值(伤害/治疗倍数)
- ItemDisplay.renderListItem: 增强支持法术物品显示
  - 法术物品显示计算方式和基础数值
  - 装备物品仍显示属性和词条

改进内容:
- 背包列表中显示法术的详细计算方式(如 [魔攻] 1.6x)
- 法术物品不显示词条(仅装备显示词条)
- InventoryPanel 导入 SpellDisplay 以支持未来扩展
- 保持与战斗系统中法术显示的一致性

格式示例:
装备: 名称 Lv.5 +3 (武器) (物攻+50 暴伤+30) 3词条
法术: 名称 Lv.5 (法术) [魔攻] 1.6x

🧙 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 23:03:49 +08:00
c065e19113 优化技能显示系统:增强战斗中的法术信息显示
新增功能:
- 创建 SpellDisplay 工具类,统一管理法术显示逻辑
- 支持 14 种计算方式的中文说明显示
- 显示品质特定的基础伤害/治疗倍数
- 增强 Battle.php 中所有法术施放方法的信息显示

改进内容:
- castDamageSingleSpell: 显示计算方式、消耗、伤害倍数
- castDamageAoeSpell: 显示计算方式、消耗
- castHealSingleSpell: 显示计算方式、消耗
- castHealAoeSpell: 显示计算方式、消耗
- castSupportSpell: 显示品质颜色和消耗

技术细节:
- ItemDisplay.php 添加 getQualityIndex() 辅助方法
- SpellDisplay.php 修复 match 表达式语法(改用 if-elseif)
- 使用质量索引访问品质相关数组
- 显示强化后的实际消耗

🧙 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 22:52:48 +08:00
hantao
9d9af5f96c 逻辑优化 2025-12-04 18:11:28 +08:00
595295ebf2 优化 2025-12-03 23:48:23 +08:00
9a5eb6433f 优化 2025-12-03 23:41:55 +08:00
d2e1625c43 重构:Partner 采用和 Player 相同的属性计算方式
- 删除 Partner 的自定义 getStats() 方法,改用 Actor 的统一实现
- 删除 parseAffix() 方法(Actor 中已有)
- baseStats 只在构造函数初始化时使用一次,用于设置基础属性
- 基础属性(patk, matk, pdef, mdef, crit, critdmg)现在直接存储在 Actor 属性中
- 删除 growth 系数,不再基于等级动态放大属性
- 属性计算方式统一:基础值 → 天赋加成 → 装备加成 → 附魔加成

现在 Partner 与 Player 使用完全相同的属性计算系统,只是天赋加成值不同

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 22:53:47 +08:00
0ffd44eccf 修复:恢复 Partner 的 getStats() 和 parseAffix() 方法
Partner 继承 Actor 后,不小心删除了 getStats() 和 parseAffix() 方法。
这导致 Partner 无法正确计算属性,招募后显示属性全是0。

恢复的内容:
- getStats():基于 baseStats 和 growth 系数的属性计算
- parseAffix():装备附魔属性解析
- baseStats 属性:用于存储伙伴的基础属性配置
- talentBonus 覆盖:Partner 特有的天赋加成值

现在 Partner 能够正确继承 Actor 的同时保留自己特有的属性计算逻辑

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 22:46:34 +08:00
1cff247906 重构:Partner 继承 Actor 类
- Partner 现在继承 Actor,获得统一的天赋、法术和属性系统
- Partner 覆盖 talentBonus 为自己的特殊值(hp 20, critdmg 10)
- Partner 覆盖 getStats() 以支持自定义的 baseStats 和 growth 系数
- Partner 保留特有的 autoAllocateTalent() 方法(私有,确保 HP 至少加1点)
- Partner 覆盖 gainExp() 以调用自己的 autoAllocateTalent()
- 删除重复的方法:heal(), recoverMana(), spendMana(), learnSpell()
- 保留特有方法:getTotalTalentPoints(), hasSpell(), getSpellLevel()
- 简化 Partner 构造函数,使用 Actor 的属性

统一体系:所有 Actor 子类(Player, Partner, Monster, NPC)都继承同一套天赋和属性系统

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 22:09:34 +08:00
e593d81942 重构:将天赋系统统一移到 Actor 基类
- 将天赋系统 (talents, talentWeights, talentBonus, getTalentStats) 集中在 Actor 基类
- 添加 allocateTalent(), resetTalents(), autoAllocateTalents(), gainExp() 到 Actor
- Monster 保留特有的基础属性、奖励和掉落表
- NPC 保留特有的标识和配置相关属性
- Player 保留特有的名称映射、NPC 标记、同伴系统和升级治疗逻辑
- 删除所有重复代码,提高代码复用性和可维护性

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 21:57:59 +08:00
hantao
05bff41e35 逻辑优化 2025-12-03 18:15:54 +08:00
826f0e38a4 法术 2025-12-02 23:13:38 +08:00
hantao
bacc28acce 操作优化 2025-12-02 17:56:53 +08:00
hantao
b4ec385827 添加怪物群 2025-12-02 13:45:20 +08:00
hantao
0c6cbd669a first 2025-12-01 18:13:15 +08:00