Revert "add rule AI"

This reverts commit ed9910f365.
This commit is contained in:
CuongNV
2026-03-24 14:36:22 +07:00
parent d21236aec7
commit 5d677cad1a
25 changed files with 10 additions and 13639 deletions
File diff suppressed because it is too large Load Diff
-52
View File
@@ -1,52 +0,0 @@
# Perfect World Port Architecture
## Overview
Project này port client Perfect World từ C++ sang Unity C# và xây dựng server mới bằng .NET.
Architecture gồm 3 layer chính:
Client Layer
Unity project chịu trách nhiệm:
- UI
- rendering
- input
- local gameplay logic
- network client
Server Layer
.NET 8 server sử dụng LiteNetLib.
Server chịu trách nhiệm:
- authoritative game state
- player session
- snapshot replication
- chat routing
Shared Layer
Game.Shared chứa:
- protocol definitions
- shared data types
- serialization logic
## Architecture Diagram
Unity Client
Game.Shared (protocol)
LiteNetLib transport
Game.Server
## Main Goals
- giữ gameplay logic từ Perfect World
- thay engine bằng Unity
- thay network stack
- modernize architecture
-63
View File
@@ -1,63 +0,0 @@
# Chat System
Chat system gốc của Perfect World gồm các bước:
Network Protocol
GameSession
GameUIMan
CECPateText
Render
## Components
ChatMessage
network protocol chứa:
channel
roleid
msg
emotion
GameSession::OnPrtcChatMessage
nhận packet từ network.
GameUIMan::AddChatMessage
thêm message vào UI.
CECPateText
parse text thành các item:
TEXT
EMOTION
ITEM LINK
## Emotion System
Emotion được encode trong text:
format:
emotionSet:index
Example:
1:5
## Rendering
CECPateText chia text thành item list.
Item gồm:
type
index
color
position
-21
View File
@@ -1,21 +0,0 @@
# Common Code Patterns
Pattern: Player Name Lookup
C++
Name2IDTable
ID2NameTable
C#
Dictionary<string, int>
Dictionary<int, string>
Pattern: Chat Rendering
Parse text
create item list
render UI
-33
View File
@@ -1,33 +0,0 @@
# Data Types Mapping
Perfect World sử dụng nhiều custom types.
Mapping sang C#:
ACString → string
ACHAR → wchar_t / char
A3DCOLOR → UnityEngine.Color hoặc Color32
Octets → byte[]
pair_type → Tuple hoặc struct
AArray<T> → List<T>
DWORD → uint
BYTE → byte
BOOL → bool
## Important Note
ACString trong C++ hỗ trợ:
- formatting
- substring
- concat
C# string là immutable nên cần cẩn thận performance.
-68
View File
@@ -1,68 +0,0 @@
# C++ to C# Porting Rules
Rule 1
const ACHAR* → string
Rule 2
output parameters
C++:
int& value
C#:
ref int value
Rule 3
pointer
T* → reference
Rule 4
array
ACHAR buffer[1024]
C#:
Span<char> hoặc string builder
Rule 5
container
AArray → List
Rule 6
memory ownership
C++ có delete
C# dùng GC
Rule 7
Chat Message Handling
C++:
g_pGame->GetGameRun()->AddChatMessage(str, p->channel, p->srcroleid, NULL, 0, p->emotion,pItem ? pItem->Clone() : NULL, strMsgOrigion);
C#:
EC_Game.GetGameRun().AddChatMessage(str, p.Channel, p.Srcroleid,null, 0, p.Emotion, null, strMsgOrigion);
Rule 8
Chat Bubble on Top Player
C++:
pPlayer.SetLastSaidWords(strTemp, p.Emotion);
C#:
EventBus.PublishChannel(p.Srcroleid, new EventChatMessageOnTopPlayer(p.Srcroleid, strTemp));
-31
View File
@@ -1,31 +0,0 @@
# Network Protocol
Protocol gốc sử dụng GNET.
Structure:
Protocol
Rpc::Data
Octets serialization
## Example
ChatMessage
fields:
channel
srcroleid
srclevel
msg
emotion
## Serialization
Octets chứa raw byte array.
C# equivalent:
byte[]
-11617
View File
File diff suppressed because it is too large Load Diff
+10 -28
View File
@@ -7,7 +7,7 @@ QualitySettings:
m_CurrentQuality: 0
m_QualitySettings:
- serializedVersion: 4
name: High
name: Mobile
pixelLightCount: 2
shadows: 2
shadowResolution: 1
@@ -17,7 +17,7 @@ QualitySettings:
shadowNearPlaneOffset: 3
shadowCascade2Split: 0.33333334
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
shadowmaskMode: 1
shadowmaskMode: 0
skinWeights: 2
globalTextureMipmapLimit: 0
textureMipmapLimitSettings: []
@@ -25,12 +25,12 @@ QualitySettings:
antiAliasing: 0
softParticles: 0
softVegetation: 1
realtimeReflectionProbes: 1
realtimeReflectionProbes: 0
billboardsFaceCameraPosition: 1
useLegacyDetailDistribution: 0
useLegacyDetailDistribution: 1
adaptiveVsync: 0
vSyncCount: 1
realtimeGICPUUsage: 50
vSyncCount: 0
realtimeGICPUUsage: 100
adaptiveVsyncExtraA: 0
adaptiveVsyncExtraB: 0
lodBias: 1
@@ -47,7 +47,7 @@ QualitySettings:
asyncUploadBufferSize: 16
asyncUploadPersistentBuffer: 1
resolutionScalingFixedDPIFactor: 1
customRenderPipeline: {fileID: 0}
customRenderPipeline: {fileID: 11400000, guid: 5e6cbd92db86f4b18aec3ed561671858, type: 2}
terrainQualityOverrides: 0
terrainPixelError: 1
terrainDetailDensityScale: 1
@@ -57,25 +57,7 @@ QualitySettings:
terrainBillboardStart: 50
terrainFadeLength: 5
terrainMaxTrees: 50
excludedTargetPlatforms: []
excludedTargetPlatforms:
- Standalone
m_TextureMipmapLimitGroupNames: []
m_PerPlatformDefaultQuality:
Android: 2
EmbeddedLinux: 5
GameCoreScarlett: 5
GameCoreXboxOne: 5
Kepler: 5
LinuxHeadlessSimulation: 5
Nintendo Switch: 5
Nintendo Switch 2: 5
PS4: 5
PS5: 5
QNX: 5
Server: 5
Standalone: 5
VisionOS: 5
WebGL: 3
Windows Store Apps: 5
XboxOne: 5
iPhone: 2
tvOS: 2
m_PerPlatformDefaultQuality: {}
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
-10
View File
@@ -1,10 +0,0 @@
import os
try:
with open(r'd:\perfect-world-source\perfect-world-source\CElement\CElementClient\EC_Player.cpp', 'r', encoding='gbk') as f:
content = f.read()
with open(r'c:\Unity\CuongNV\perfect-world-unity\EC_Player_clean.cpp', 'w', encoding='utf-8') as f2:
f2.write(content.replace('\r', ''))
print("Cleaned EC_Player.cpp successfully.")
except Exception as e:
print("Error:", e)
BIN
View File
Binary file not shown.
Binary file not shown.
-13
View File
@@ -1,13 +0,0 @@
3289: void CECGameUIMan::AddChatMessage(const ACHAR *pszMsg,
3290: char cChannel, int idPlayer, const ACHAR *pszPlayer, char byFlag, char cEmotion, CECIvtrItem *pItem,const ACHAR *pszMsgOrigion)
3291: {
3292: auto_delete<CECIvtrItem> tmp(pItem);
3293:
3294: bool bIsKing = false;
3295: if( cChannel == GP_CHAT_COUNTRY && (cEmotion & 0x80) )
-212
View File
@@ -1,212 +0,0 @@
3289: void CECGameUIMan::AddChatMessage(const ACHAR *pszMsg,
3290: char cChannel, int idPlayer, const ACHAR *pszPlayer, char byFlag, char cEmotion, CECIvtrItem *pItem,const ACHAR *pszMsgOrigion)
3291: {
3292: auto_delete<CECIvtrItem> tmp(pItem);
3293:
3294: bool bIsKing = false;
3295: if( cChannel == GP_CHAT_COUNTRY && (cEmotion & 0x80) )
3296: {
3297: cEmotion &= ~0x80;
3298: bIsKing = true;
3299: }
3300:
3301: // 修正表情
3302: ACString strModified = FilterEmotionSet(pszMsg, cEmotion);
3303:
3304: // 修正给GM的额外信息
3305: ACString GM_MsgShow;
3306: ACHAR GM_MsgType(0);
3307: bool GM_MsgValid(false);
3308: if (g_pGame->GetGameRun()->GetHostPlayer()->IsGM() &&
3309: GP_CHAT_WHISPER == cChannel)
3310: {
3311: int nSymbolPos = strModified.Find(GM_HELP_MSG_TYPE_BASE);
3312: if (nSymbolPos >= 0 && nSymbolPos+1 < strModified.GetLength())
3313: {
3314: ACHAR type = strModified[nSymbolPos + 1];
3315: if (TheGMHelpMsgArray::Instance()->FindByType(type, NULL))
3316: {
3317: GM_MsgValid = true;
3318: GM_MsgType = type;
3319: GM_MsgShow = strModified;
3320: GM_MsgShow.CutLeft(nSymbolPos + 2);
3321:
3322: strModified = strModified.Left(nSymbolPos) + strModified.Right(strModified.GetLength() - (nSymbolPos+2));
3323: }
3324: }
3325: }
3326:
3327: // 考虑本地化对某些内容不显示的要求,当ingame.stf找不到相关字符串、并导致此处字符中为空时,隐藏显示
3328: if (strModified.IsEmpty())
3329: return;
3330:
3331: // 标明来自GT频道的消息
3332: if (byFlag == CHANNEL_GAMETALK)
3333: strModified += GetStringFromTable(9312);
3334:
3335: pszMsg = strModified;
3336:
3337: if( PlayerIsBlack(idPlayer) )
3338: return;
3339: if( cChannel == GP_CHAT_SYSTEM && a_stricmp(pszMsg, GetStringFromTable(809)) == 0 )
3340: return;
3341:
3342: if( byFlag == CHANNEL_FRIEND || byFlag == CHANNEL_FRIEND_RE || byFlag == CHANNEL_GAMETALK)
3343: {
3344: AddFriendMessage(pszMsg, idPlayer, pszPlayer, byFlag, cEmotion, pItem ? pItem->Clone() : NULL,pszMsgOrigion);
3345: return;
3346: }
3347: else if( byFlag == CHANNEL_USERINFO )
3348: {
3349: if( pszMsg[0] == 'R' )
3350: {
3351: CECFriendMan *pMan = g_pGame->GetGameRun()->GetHostPlayer()->GetFriendMan();
3352: if (!pMan)
3353: return;
3354: if( pMan->GetFriendByID(idPlayer) )
3355: FriendAction(idPlayer, -1, CDlgFriendList::FRIEND_ACTION_INFO_REFRESH, 0);
3356: }
3357: else if( pszMsg[0] == 'L' )
3358: FriendAction(idPlayer, -1, CDlgFriendList::FRIEND_ACTION_INFO_LEVEL, a_atoi(pszMsg + 1));
3359: else if( pszMsg[0] == 'A' )
3360: FriendAction(idPlayer, -1, CDlgFriendList::FRIEND_ACTION_INFO_AREA, a_atoi(pszMsg + 1));
3361: return;
3362: }
3363:
3364: ACHAR *pszText;
3365: CDlgChat::CHAT_MSG msg;
3366: ACHAR szText[512], szMsg[512];
3367: CDlgChat *pChat1 = m_pDlgChat;
3368: CDlgChat *pChat2 = m_pDlgChat2;
3369: CDlgChat *pChat3 = m_pDlgChat3;
3370: EC_GAME_SETTING gs = g_pGame->GetConfigs()->GetGameSettings();
3371: PAUITEXTAREA pShow1 = dynamic_cast<PAUITEXTAREA>(pChat1->GetDlgItem("Txt_Content"));
3372: PAUITEXTAREA pShow2 = dynamic_cast<PAUITEXTAREA>(pChat2->GetDlgItem("Txt_Content"));
3373: PAUITEXTAREA pShow3 = dynamic_cast<PAUITEXTAREA>(pChat3->GetDlgItem("Txt_Content"));
3374: abase::vector<CDlgChat::CHAT_MSG> &vecChatMsg = m_pDlgChat->GetAllChatMsgs();
3375: abase::vector<CDlgChat::CHAT_MSG> &superFarCryMsg = m_pDlgChat->GetSuperFarCryMsgs();
3376: abase::vector<CDlgChat::LINKED_MSG> &whisperMsg = m_pDlgChat->GetWhisperChatMsgs();
3377:
3378: msg.idPlayer = idPlayer;
3379: msg.strMsg = pszMsg;
3380: msg.cChannel = cChannel;
3381: msg.cEmotion = cEmotion;
3382: msg.strMsgOrigion = pszMsgOrigion;
3383: if( cChannel == GP_CHAT_LOCAL ||
3384: cChannel == GP_CHAT_FARCRY ||
3385: cChannel == GP_CHAT_TEAM ||
3386: cChannel == GP_CHAT_FACTION ||
3387: cChannel == GP_CHAT_WHISPER ||
3388: cChannel == GP_CHAT_TRADE ||
3389: cChannel == GP_CHAT_SUPERFARCRY ||
3390: cChannel == GP_CHAT_BATTLE ||
3391: cChannel == GP_CHAT_COUNTRY)
3392: {
3393: if (ISPLAYERID(idPlayer)){
3394: g_pGame->GetGameRun()->GetUIManager()->FilterBadWords(msg.strMsg);
3395: }
3396: }
3397:
3398: int nMsgLen = a_strlen(pszMsg);
3399: // Booth Message
3400: if( cChannel == GP_CHAT_WHISPER &&
3401: pszMsg[nMsgLen - 2] == '!' &&
3402: pszMsg[nMsgLen - 1] == '#' )
3403: {
3404: if( m_pDlgBooth1->IsShow() )
3405: m_pDlgBooth1->AddBoothMessage(pszMsg);
3406: return;
3407: }
3408:
3409: ACString strName;
3410: A3DCOLOR clrName;
3411: TransformNameColor(pItem, strName, clrName);
3412: AWString msgWithColor = _AL("");
3413: if( ISNPCID(idPlayer) )
3414: msgWithColor += _AL("^C8FF64");
3415: else
3416: {
3417: if( cChannel == GP_CHAT_COUNTRY && bIsKing )
3418: msgWithColor += CDlgChat::m_pszKingColor;
3419: else
3420: msgWithColor += CDlgChat::GetChatColor(cChannel, idPlayer);
3421: }
3422:
3423: msgWithColor += GetChatChannelImage(cChannel);
3424: if( cChannel == GP_CHAT_COUNTRY && bIsKing )
3425: msgWithColor += GetStringFromTable(10310);
3426: msgWithColor += msg.strMsg;
3427:
3428: if( cChannel == GP_CHAT_WHISPER &&
3429: (int)m_pDlgChatWhisper->GetData() == idPlayer )
3430: {
3431: pShow1 = dynamic_cast<PAUITEXTAREA>(m_pDlgChatWhisper->GetDlgItem("Txt_Chat"));
3432: pszText = (ACHAR *)pShow1->GetText();
3433:
3434: if( a_strlen(pShow1->GetText()) > 0 )
3435: pShow1->AppendText(_AL("\r"));
3436:
3437: pShow1->AppendText(msgWithColor, pItem ? CDlgChat::m_nMsgIndex : 0, strName, clrName);
3438:
3439: if( !m_pDlgChat->IsLocked() )
3440: {
3441: pShow1->ScrollToTop();
3442: pShow1->ScrollToBottom();
3443: }
3444: if( !m_pDlgChatWhisper->IsShow() )
3445: m_pMiniBarMgr->FlashDialog(m_pDlgChatWhisper);
3446:
3447: // 将可点击的消息,保存起来供点击查询
3448: if (pItem)
3449: {
3450: CDlgChat::LINKED_MSG linkedMsg;
3451: linkedMsg.pItem = pItem;
3452: tmp._ptr = NULL;
3453: linkedMsg.nMsgIndex = CDlgChat::m_nMsgIndex++;
3454:
3455: whisperMsg.push_back(linkedMsg);
3456: if( (int)whisperMsg.size() >= CECGAMEUIMAN_MAX_MSGS )
3457: {
3458: CDlgChat::LINKED_MSG &msgDelete = *(whisperMsg.begin());
3459: delete msgDelete.pItem;
3460: msgDelete.pItem = NULL;
3461: whisperMsg.erase(whisperMsg.begin());
3462: }
3463: }
3464: }
3465: else
3466: {
3467: msg.pItem = pItem;
3468: msg.nMsgIndex = CDlgChat::m_nMsgIndex++;
3469: tmp._ptr = NULL;
3470: msg.strMsg = msgWithColor;
3471:
3472: int nActiveChannelSet = m_pDlgChat->GetActiveChannelSet();
3473: if( gs.bChannel[nActiveChannelSet][cChannel] )
3474: {
3475: pszText = (ACHAR *)pShow1->GetText();
3476:
3477: /*
3478: if( m_pDlgChat->GetMsgCount(1) >= CECGAMEUIMAN_MAX_MSGS )
3479: {
3480: pch = a_strstr(pszText, _AL("\r"));
3481: if( pch )
3482: {
3483: ACString strText = pszText;
3484: strText.CutLeft(pch - pszText + 1);
3485: pShow1->SetText(strText);
3486: }
3487: }
3488: */
3489:
3490: if( glb_IsTextNotEmpty(pShow1))
3491: pShow1->AppendText(_AL("\r"));
3492:
3493: pShow1->AppendText(msgWithColor, msg.nMsgIndex, strName, clrName);
3494:
3495: if( !pChat1->IsLocked() )
3496: {
3497: pShow1->ScrollToTop();
3498: pShow1->ScrollToBottom();
3499: }
3500:
-32
View File
@@ -1,32 +0,0 @@
# Project Context & Tracking (Antigravity/Gemini)
## 🎯 Project Overview
- **Main Objective:** Porting features (like Task/Chat) from the Perfect World C++ Client to Unity (C#).
- **C++ Source Repository:** `d:\perfect-world-source\perfect-world-source\CElement\CElementClient`
- **Unity Target Repository:** `c:\Unity\CuongNV\perfect-world-unity`
## 📊 Current Status
- **Active Focus:** Chuyển đổi hệ thống Task/Chat (đang phân tích `DlgTaskTrace.cpp``ChatInputHandler.cs`).
## 🛠️ Trạng thái Công việc (TODOs)
- [x] Phân tích logic của `DlgTaskTrace.cpp`
- [x] Triển khai `HeadChatBubble.cs` cơ bản.
- [ ] Hoàn thiện luồng Chat cơ bản trong `GameSession.cs` (Bỏ qua Task/Policy/Filter).
- [ ] Kiểm thử hiển thị chat trên đầu nhân vật.
## 📌 Quy ước Code (Guidelines)
*(Ghi chú các quy tắc code, kiến trúc, hoặc lưu ý đặc biệt đối với dự án Unity tại đây)*
- Sử dụng chuẩn C# cho Unity.
- Tối ưu hóa UI/Sự kiện (Events).
- Thêm log debug ở cả 2 dự án theo quy tắc: `[Cuong] + Tên hàm + Nội dung (nếu có)`.
- Ví dụ C++: `a_LogOutput(1, "[Cuong] Method Tick %s", szTxt);`
- Ví dụ C#: `Debug.Log("[Cuong] Method Tick " + szTxt);`
## ⚙️ Quy trình Build & Deploy
- **C++ Client (`CElementClient`)**: Sau khi build, cần copy ghi đè các file thay đổi từ thư mục build sang thư mục client.
- **Nguồn**: `D:\perfect-world-source\perfect-world-source\CElement\CBin`
- **Đích**: `D:\perfect-world-source\perfect-world-source\PW_client\client\element`
- *(Đã tạo sẵn script tự động: `D:\perfect-world-source\perfect-world-source\CElement\CopyBuild.bat`)*
---
*File này được tạo để theo dõi tiến độ và lưu giữ ngữ cảnh của dự án. File sẽ được cập nhật liên tục khi chúng ta xử lý các task mới.*
View File
-6
View File
@@ -1,6 +0,0 @@
{
"name": "perfect-world-unity",
"lockfileVersion": 3,
"requires": true,
"packages": {}
}
-25
View File
@@ -1,25 +0,0 @@
import os
import sys
def read_file(path, lines=250):
encodings = ['utf-8', 'gbk', 'utf-16', 'latin1', 'utf-8-sig']
content = ""
for enc in encodings:
try:
with open(path, 'r', encoding=enc) as f:
content = f.read()
print(f"--- SUCCESS reading {os.path.basename(path)} with encoding {enc} ---")
break
except Exception:
pass
if content:
lines_list = content.splitlines()
print(f"Total lines: {len(lines_list)}")
print("\n".join(lines_list[:lines]))
print("...\n" if len(lines_list) > lines else "\n")
else:
print(f"FAILED to read {path}\n")
read_file(r"d:\perfect-world-source\perfect-world-source\CElement\CElementClient\DlgTaskTrace.cpp")
read_file(r"c:\Unity\CuongNV\perfect-world-unity\Assets\Scripts\ChatInputHandler.cs")