diff --git a/audit/history.jsonl b/audit/history.jsonl index cd1c3cb0..2ea7d041 100644 --- a/audit/history.jsonl +++ b/audit/history.jsonl @@ -530,3 +530,4 @@ {"time": "2026-09-24T03:00:00Z", "event": "port_round", "unit": "PORT-PLAN batch 2 P1: flying objects + effect/fly Python modules", "ported": ["GameLib/FlyingData.cpp (12)", "GameLib/FlyingInstance.cpp (20)", "GameLib/FlyingObjectManager.cpp (12)", "GameLib/FlyTrace.cpp (11)", "GameLib/ActorInstanceData.cpp (12)", "UserInterface/PythonEffectModule.cpp (8)", "UserInterface/PythonFlyModule.cpp (3)"], "adapted": ["CMapManager::GetTerrainHeight over native height tiles; GetHeight forwards to it"], "divergent": [], "needs_live": [], "tests": ["port.login_flow: indexed fly .msf registered by playersettingmodule and parses", "ctest all: 19/19 incl. port.login_live 192.168.21.203", "script/python_game_render_test.sh offline: PASS", "port_map.py check: 0 errors"], "todo": ["CEffectManager is a platform stub: fly effects are not rendered", "P2 network units already copied into port/ need verification and marking"]} {"time": "2026-09-24T04:00:00Z", "event": "port_round", "unit": "PORT-PLAN batch 2: verify and mark 28 units copied into port/ in 2V1/2A", "ported": ["28 units, 372 functions: PythonNetworkStream{,PhaseLoading,PhaseLogin,PhaseSelect,PhaseHandShake,PhaseOffline,Event}, AccountConnector, NetStream, NetPacketHeaderMap, NetAddress, NetDevice, TextTag, EterPack, EterPackManager, EterPackCursor, EterPackPolicy_CSHybridCrypt, Timer, cipher, lzo, Random, Stl, tea, Arabic, StringCodec, StringCodec_Vietnamese, InsultChecker, AffectFlagContainer"], "adapted": [], "divergent": [], "needs_live": [], "tests": ["port_copy.py diff: 23 exact mechanical copies, 5 with // PORT: edits only; StringCodec_Vietnamese (not CP949) differs by BOM + include case", "no same-named platform/pending files", "ctest all 19/19 + render test on the same tree", "port_map.py check: 0 errors"], "todo": ["P2 ServerStateChecker (module still stubbed)", "P3 items/minimap/text tail"]} {"time": "2026-09-24T05:00:00Z", "event": "port_round", "unit": "PORT-PLAN batch 2 P2: ServerStateChecker + module", "ported": ["UserInterface/ServerStateChecker.cpp", "UserInterface/ServerStateCheckerModule.cpp"], "adapted": [], "divergent": [], "needs_live": [], "tests": ["port.login_flow: fake state port answers CG_STATE_CHECKER, NotifyChannelState(2, 1)", "port.login_live 192.168.21.203: channel states {1: 1, 2: 1}", "ctest all 19/19, python_game_render_test offline PASS", "port_map.py check: 0 errors"], "todo": ["P3 item chain: ItemData, ItemManager, PythonItem, PythonExchange"]} +{"time": "2026-09-24T06:00:00Z", "event": "port_round", "unit": "PORT-PLAN batch 2 P3-a: ItemData, ItemManager, PythonNonPlayer + LoadLocaleData", "ported": ["GameLib/ItemData.cpp", "GameLib/ItemManager.cpp", "UserInterface/PythonNonPlayer.cpp", "UserInterface/PythonNonPlayerModule.cpp"], "adapted": ["UserInterface/PythonApplication.cpp:LoadLocaleData"], "divergent": [], "needs_live": [], "tests": ["port.login_flow 3c: item 19 Sword+9 type 1 refine 9, mob 101 Wild Dog", "port.login_live 192.168.21.203: same", "ctest all 19/19, python_game_render_test offline PASS", "port_map.py check: 0 errors"], "todo": ["P3-b PythonItem + PythonItemModule", "CPythonSkill (RegisterSkillDesc/Table) still pending"]} diff --git a/audit/port-map/GameLib/ItemData.cpp.json b/audit/port-map/GameLib/ItemData.cpp.json new file mode 100644 index 00000000..b4da1b94 --- /dev/null +++ b/audit/port-map/GameLib/ItemData.cpp.json @@ -0,0 +1,302 @@ +{ + "reference": "GameLib/ItemData.cpp", + "reference_sha256": "084e5fd9dc566fa4127ad71db3b848a8e923ddc64781381805a2f359c5b21272", + "priority": "P3", + "contracts": [], + "functions": { + "CItemData::New": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::New" + ] + }, + "CItemData::Delete": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::Delete" + ] + }, + "CItemData::DestroySystem": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::DestroySystem" + ] + }, + "CItemData::GetModelThing": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetModelThing" + ] + }, + "CItemData::GetSubModelThing": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetSubModelThing" + ] + }, + "CItemData::GetDropModelThing": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetDropModelThing" + ] + }, + "CItemData::GetIconImage": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetIconImage" + ] + }, + "CItemData::GetLODModelThingCount": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetLODModelThingCount" + ] + }, + "CItemData::GetLODModelThingPointer": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetLODModelThingPointer" + ] + }, + "CItemData::GetAttachingDataCount": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetAttachingDataCount" + ] + }, + "CItemData::GetCollisionDataPointer": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetCollisionDataPointer" + ] + }, + "CItemData::GetAttachingDataPointer": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetAttachingDataPointer" + ] + }, + "CItemData::SetSummary": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::SetSummary" + ] + }, + "CItemData::SetDescription": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::SetDescription" + ] + }, + "CItemData::SetDefaultItemData": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::SetDefaultItemData" + ] + }, + "CItemData::__LoadFiles": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::__LoadFiles" + ] + }, + "CItemData::__SetIconImage": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::__SetIconImage" + ] + }, + "CItemData::SetItemTableData": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::SetItemTableData" + ] + }, + "CItemData::GetTable": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetTable" + ] + }, + "CItemData::GetIndex": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetIndex" + ] + }, + "CItemData::GetName": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetName" + ] + }, + "CItemData::GetDescription": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetDescription" + ] + }, + "CItemData::GetSummary": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetSummary" + ] + }, + "CItemData::GetType": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetType" + ] + }, + "CItemData::GetSubType": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetSubType" + ] + }, + "CItemData::GetUseTypeString": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetUseTypeString" + ] + }, + "CItemData::GetWeaponType": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetWeaponType" + ] + }, + "CItemData::GetSize": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetSize" + ] + }, + "CItemData::IsAntiFlag": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::IsAntiFlag" + ] + }, + "CItemData::IsFlag": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::IsFlag" + ] + }, + "CItemData::IsWearableFlag": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::IsWearableFlag" + ] + }, + "CItemData::HasNextGrade": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::HasNextGrade" + ] + }, + "CItemData::GetWearFlags": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetWearFlags" + ] + }, + "CItemData::GetIBuyItemPrice": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetIBuyItemPrice" + ] + }, + "CItemData::GetISellItemPrice": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetISellItemPrice" + ] + }, + "CItemData::GetLimit": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetLimit" + ] + }, + "CItemData::GetApply": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetApply" + ] + }, + "CItemData::GetValue": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetValue" + ] + }, + "CItemData::SetSocket": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::SetSocket" + ] + }, + "CItemData::GetSocket": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetSocket" + ] + }, + "CItemData::GetSocketCount": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetSocketCount" + ] + }, + "CItemData::GetIconNumber": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetIconNumber" + ] + }, + "CItemData::GetSpecularPoweru": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetSpecularPoweru" + ] + }, + "CItemData::GetSpecularPowerf": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetSpecularPowerf" + ] + }, + "CItemData::GetRefine": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::GetRefine" + ] + }, + "CItemData::IsEquipment": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::IsEquipment" + ] + }, + "CItemData::Clear": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::Clear" + ] + }, + "CItemData::CItemData": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::CItemData" + ] + }, + "CItemData::~CItemData": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemData.cpp:CItemData::~CItemData" + ] + } + } +} diff --git a/audit/port-map/GameLib/ItemManager.cpp.json b/audit/port-map/GameLib/ItemManager.cpp.json new file mode 100644 index 00000000..3cd92b0b --- /dev/null +++ b/audit/port-map/GameLib/ItemManager.cpp.json @@ -0,0 +1,80 @@ +{ + "reference": "GameLib/ItemManager.cpp", + "reference_sha256": "3fee94861cd02dacfadcd5d31d5c787b0ee795ac8f7f19e0214d481946c17d42", + "priority": "P3", + "contracts": [], + "functions": { + "CItemManager::SelectItemData": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemManager.cpp:CItemManager::SelectItemData" + ] + }, + "CItemManager::GetSelectedItemDataPointer": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemManager.cpp:CItemManager::GetSelectedItemDataPointer" + ] + }, + "CItemManager::GetItemDataPointer": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemManager.cpp:CItemManager::GetItemDataPointer" + ] + }, + "CItemManager::MakeItemData": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemManager.cpp:CItemManager::MakeItemData" + ] + }, + "CItemManager::LoadItemList": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemManager.cpp:CItemManager::LoadItemList" + ] + }, + "__SnapString": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemManager.cpp:__SnapString" + ] + }, + "CItemManager::LoadItemDesc": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemManager.cpp:CItemManager::LoadItemDesc" + ] + }, + "GetHashCode": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemManager.cpp:GetHashCode" + ] + }, + "CItemManager::LoadItemTable": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemManager.cpp:CItemManager::LoadItemTable" + ] + }, + "CItemManager::Destroy": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemManager.cpp:CItemManager::Destroy" + ] + }, + "CItemManager::CItemManager": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemManager.cpp:CItemManager::CItemManager" + ] + }, + "CItemManager::~CItemManager": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/ItemManager.cpp:CItemManager::~CItemManager" + ] + } + } +} diff --git a/audit/port-map/UserInterface/PythonApplication.cpp.json b/audit/port-map/UserInterface/PythonApplication.cpp.json new file mode 100644 index 00000000..5fceb77b --- /dev/null +++ b/audit/port-map/UserInterface/PythonApplication.cpp.json @@ -0,0 +1,130 @@ +{ + "reference": "UserInterface/PythonApplication.cpp", + "reference_sha256": "9a9e5268c7475e6ed720bc8ee53ed58d334b22d1efa93310b3d45f1bbdd85bf3", + "priority": "P4", + "contracts": [], + "functions": { + "CPythonApplication::CPythonApplication": { + "status": "TODO" + }, + "CPythonApplication::~CPythonApplication": { + "status": "TODO" + }, + "CPythonApplication::GetMousePosition": { + "status": "TODO" + }, + "CPythonApplication::SetMinFog": { + "status": "TODO" + }, + "CPythonApplication::SetFrameSkip": { + "status": "TODO" + }, + "CPythonApplication::NotifyHack": { + "status": "TODO" + }, + "CPythonApplication::GetInfo": { + "status": "TODO" + }, + "CPythonApplication::Abort": { + "status": "TODO" + }, + "CPythonApplication::Exit": { + "status": "TODO" + }, + "CPythonApplication::RenderGame": { + "status": "TODO" + }, + "CPythonApplication::UpdateGame": { + "status": "TODO" + }, + "CPythonApplication::SkipRenderBuffering": { + "status": "TODO" + }, + "CPythonApplication::Process": { + "status": "TODO" + }, + "CPythonApplication::UpdateClientRect": { + "status": "TODO" + }, + "CPythonApplication::SetMouseHandler": { + "status": "TODO" + }, + "CPythonApplication::CheckDeviceState": { + "status": "TODO" + }, + "CPythonApplication::CreateDevice": { + "status": "TODO" + }, + "CPythonApplication::Loop": { + "status": "TODO" + }, + "LoadLocaleData": { + "status": "ADAPTED", + "impl": [ + "extension/src/platform/UserInterface/PythonApplication.cpp:LoadLocaleData" + ], + "note": "Body verbatim in the platform CPythonApplication stand-in; CPythonSkill is still pending, so RegisterSkillDesc fails and it returns false after the item and mob tables load (localeinfo.py ignores the result).", + "test": "extension/tests/port_login_flow_test.cpp step 3c (port.login_flow / port.login_live: item 19 Sword+9, mob 101 Wild Dog)" + }, + "__GetWindowMode": { + "status": "TODO" + }, + "CPythonApplication::Create": { + "status": "TODO" + }, + "CPythonApplication::SetGlobalCenterPosition": { + "status": "TODO" + }, + "CPythonApplication::SetCenterPosition": { + "status": "TODO" + }, + "CPythonApplication::GetCenterPosition": { + "status": "TODO" + }, + "CPythonApplication::SetServerTime": { + "status": "TODO" + }, + "CPythonApplication::GetServerTime": { + "status": "TODO" + }, + "CPythonApplication::GetServerTimeStamp": { + "status": "TODO" + }, + "CPythonApplication::GetGlobalTime": { + "status": "TODO" + }, + "CPythonApplication::GetGlobalElapsedTime": { + "status": "TODO" + }, + "CPythonApplication::SetFPS": { + "status": "TODO" + }, + "CPythonApplication::GetWidth": { + "status": "TODO" + }, + "CPythonApplication::GetHeight": { + "status": "TODO" + }, + "CPythonApplication::SetConnectData": { + "status": "TODO" + }, + "CPythonApplication::GetConnectData": { + "status": "TODO" + }, + "CPythonApplication::EnableSpecialCameraMode": { + "status": "TODO" + }, + "CPythonApplication::SetCameraSpeed": { + "status": "TODO" + }, + "CPythonApplication::SetForceSightRange": { + "status": "TODO" + }, + "CPythonApplication::Clear": { + "status": "TODO" + }, + "CPythonApplication::Destroy": { + "status": "TODO" + } + } +} diff --git a/audit/port-map/UserInterface/PythonNonPlayer.cpp.json b/audit/port-map/UserInterface/PythonNonPlayer.cpp.json new file mode 100644 index 00000000..c1a5076c --- /dev/null +++ b/audit/port-map/UserInterface/PythonNonPlayer.cpp.json @@ -0,0 +1,86 @@ +{ + "reference": "UserInterface/PythonNonPlayer.cpp", + "reference_sha256": "2eae3da909c68a8c7c56dd70e024a1e65f613c5c3dd05d8b84aa4ac10e3bbfad", + "priority": "P4", + "contracts": [], + "functions": { + "CPythonNonPlayer::LoadNonPlayerData": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonNonPlayer.cpp:CPythonNonPlayer::LoadNonPlayerData" + ] + }, + "CPythonNonPlayer::GetName": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonNonPlayer.cpp:CPythonNonPlayer::GetName" + ] + }, + "CPythonNonPlayer::GetInstanceType": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonNonPlayer.cpp:CPythonNonPlayer::GetInstanceType" + ] + }, + "CPythonNonPlayer::GetTable": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonNonPlayer.cpp:CPythonNonPlayer::GetTable" + ] + }, + "CPythonNonPlayer::GetEventType": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonNonPlayer.cpp:CPythonNonPlayer::GetEventType" + ] + }, + "CPythonNonPlayer::GetEventTypeByVID": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonNonPlayer.cpp:CPythonNonPlayer::GetEventTypeByVID" + ] + }, + "CPythonNonPlayer::GetMonsterName": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonNonPlayer.cpp:CPythonNonPlayer::GetMonsterName" + ] + }, + "CPythonNonPlayer::GetMonsterColor": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonNonPlayer.cpp:CPythonNonPlayer::GetMonsterColor" + ] + }, + "CPythonNonPlayer::GetMatchableMobList": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonNonPlayer.cpp:CPythonNonPlayer::GetMatchableMobList" + ] + }, + "CPythonNonPlayer::Clear": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonNonPlayer.cpp:CPythonNonPlayer::Clear" + ] + }, + "CPythonNonPlayer::Destroy": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonNonPlayer.cpp:CPythonNonPlayer::Destroy" + ] + }, + "CPythonNonPlayer::CPythonNonPlayer": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonNonPlayer.cpp:CPythonNonPlayer::CPythonNonPlayer" + ] + }, + "CPythonNonPlayer::~CPythonNonPlayer": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonNonPlayer.cpp:CPythonNonPlayer::~CPythonNonPlayer" + ] + } + } +} diff --git a/audit/port-map/UserInterface/PythonNonPlayerModule.cpp.json b/audit/port-map/UserInterface/PythonNonPlayerModule.cpp.json new file mode 100644 index 00000000..08e6131b --- /dev/null +++ b/audit/port-map/UserInterface/PythonNonPlayerModule.cpp.json @@ -0,0 +1,50 @@ +{ + "reference": "UserInterface/PythonNonPlayerModule.cpp", + "reference_sha256": "90e6460fd07557f1624adecea7a4866d992e586fbdeaedd773105f7490c5282a", + "priority": "P4", + "contracts": [], + "functions": { + "nonplayerGetEventType": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonNonPlayerModule.cpp:nonplayerGetEventType" + ] + }, + "nonplayerGetEventTypeByVID": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonNonPlayerModule.cpp:nonplayerGetEventTypeByVID" + ] + }, + "nonplayerGetLevelByVID": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonNonPlayerModule.cpp:nonplayerGetLevelByVID" + ] + }, + "nonplayerGetGradeByVID": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonNonPlayerModule.cpp:nonplayerGetGradeByVID" + ] + }, + "nonplayerGetMonsterName": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonNonPlayerModule.cpp:nonplayerGetMonsterName" + ] + }, + "nonplayerLoadNonPlayerData": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonNonPlayerModule.cpp:nonplayerLoadNonPlayerData" + ] + }, + "initNonPlayer": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonNonPlayerModule.cpp:initNonPlayer" + ] + } + } +} diff --git a/docs/PORT-PLAN.md b/docs/PORT-PLAN.md index 87046694..b9bcea06 100644 --- a/docs/PORT-PLAN.md +++ b/docs/PORT-PLAN.md @@ -434,6 +434,8 @@ extension/third_party/cpython-2.7.18/ # 静态库(2P 批次 批次 2 P0 收尾(2026-09-24):`UserInterface/PythonCharacterManager.cpp`(54 函数)与 `InstanceBaseMovement.cpp`(32 函数)在 2V2-b 已原样拷入 `port/`,2V3 起即是运行路径(行走、点地移动、远程角色同步都经它们),本轮逐行比对 40250(仅 include 大小写、注释编码和两处 `// PORT:` 修正:`CreateInstance` 的 TraceError 传 `m_dwVID`,`NEW_SyncPixelPosition` 用 32 位 `LONG &`),确认 pending/platform 无重复定义后标 PORTED。P0 队列已清空;P1 飞行物(同日):`GameLib/FlyingData`、`FlyingInstance`、`FlyingObjectManager`、`FlyTrace` 与 Python 模块 `PythonEffectModule`(`effect`)、`PythonFlyModule`(`fly`)原样移植,删除 `pending/GameLib/FlyingObjectManager.cpp` 替身和两个模块的桩,`initeffect()`/`initfly()` 按 40250 顺序在 `initnet()` 后调用;`CFlyingManager::SetMapManagerPtr(&CPythonBackground)` 按 40250 构造函数接上;`FlyTrace.h` 加 `// PORT:` include 以过头文件门禁。`CMapManager::GetTerrainHeight`(飞行物落地判断用)在 pending 层按 native 地形高度实现,`GetHeight` 转发到它(地图物件高度待 `CMapOutdoor`)。`ActorInstanceData.cpp` 早已原样在 port/,一并标 PORTED。`port.login_flow` 断言 `playersettingmodule.py` 已经 `effect.RegisterIndexedFlyData` 注册并能解析 `.msf`。特效本体(`CEffectManager`)仍是平台桩,飞行物不可见;队列里 P0/P1 已清空,剩下 P2 网络单元(多数已在 2V1 原样拷入 port/,待逐个核对后标记)。同日核对:队列中 28 个早已拷入 port/ 的单元(网络流各阶段、`AccountConnector`、`NetStream`/`NetDevice`/`NetAddress`、`EterPack*`、`lzo`/`tea`/`cipher`/`Timer` 等,372 函数)用 `port_copy.py diff` 比对,23 个与机械拷贝完全一致,其余 5 个的手改全部带 `// PORT:`(CP949 转义、`e-` pp-number、32 位 `LONG`、包密钥外置、`lzo_uint` 宽度、`ActivateCipher` 解密同批已收密文),平台层无同名替身,标 PORTED;logic 层 54.8% → 67.9%。队列剩余 P2 仅 `ServerStateChecker`(`ServerStateChecker` 模块仍是桩),其后是 P3 物品/小地图/名牌。 P2 收尾(2026-09-24):`ServerStateChecker.cpp` 与 `ServerStateCheckerModule.cpp` 原样移植,删除模块桩,实例按 `CPythonApplication::m_kServerStateChecker` 由 PythonBoot 持有,`initServerStateChecker()` 按 40250 顺序调用。`port.login_flow` 在选角后按 intrologin 的 `__RequestServerStateList` 调 `AddChannel`/`Request`/`Update`,假服新增状态端口按 `CInputHandshake`+`CInputDB::RespondChannelStatus` 应答(先握手字节,再 `210,n,TChannelStatus[n],1`);`TChannelStatus::nPort` 是 short,假服临时端口 >32767 对不上自身频道,离线以第二个频道 13002 为证。`port.login_live` 真服返回 {1: 1, 2: 1}。P2 队列清空,下一步 P3 物品链。 + P3-a(2026-09-24):`GameLib/ItemData.cpp`、`GameLib/ItemManager.cpp`、`UserInterface/PythonNonPlayer.cpp` 与 `PythonNonPlayerModule.cpp` 原样移植,删除三个 pending 替身与 nonplayer 模块桩,`initNonPlayer()` 按 40250 顺序插在 `initPlayer()` 之后。`LoadLocaleData` 的函数体原样放进平台 `PythonApplication.cpp`(选角阶段 `localeInfo.LoadLocaleData()` 调它):读 item_list/item_proto/itemdesc 与 mob_proto;`CPythonSkill` 仍是替身,`RegisterSkillDesc` 失败后返回 false(脚本不看返回值),记 ADAPTED。`port.login_flow` 3c 步:物品 19 = Sword+9(武器、refine 9、模型可载),怪 101 = Wild Dog;真服同样通过。下一步 P3-b:`PythonItem` + `PythonItemModule`(地面物品、item 模块)。 + 每个切片都必须同时跑 legacy/port 双路回归;只有 2V3 稳定并把默认路由切到 `port` 后,才能删除总开关和剩余 legacy 宿主。 ## 5. 数据源切换:m2dev assets → 40250 diff --git a/extension/src/platform/ScriptLib/GameplayModuleConstants.cpp b/extension/src/platform/ScriptLib/GameplayModuleConstants.cpp index d29d16bd..3526fd11 100644 --- a/extension/src/platform/ScriptLib/GameplayModuleConstants.cpp +++ b/extension/src/platform/ScriptLib/GameplayModuleConstants.cpp @@ -24,7 +24,6 @@ #include "UserInterface/AbstractApplication.h" #include "UserInterface/PythonMessenger.h" #include "UserInterface/PythonMiniMap.h" -#include "UserInterface/PythonNonPlayer.h" #include "EterLib/Profiler.h" #include "UserInterface/PythonQuest.h" #include "UserInterface/PythonSafeBox.h" @@ -393,23 +392,6 @@ void AddStubConstants_miniMap(PyObject* poModule) PyModule_AddIntConstant(poModule, "TYPE_EMPIRE", CPythonMiniMap::TYPE_EMPIRE); } -// 40250 UserInterface/PythonNonPlayerModule.cpp -void AddStubConstants_nonplayer(PyObject* poModule) -{ - (void) poModule; - PyModule_AddIntConstant(poModule, "ON_CLICK_EVENT_NONE", CPythonNonPlayer::ON_CLICK_EVENT_NONE); - PyModule_AddIntConstant(poModule, "ON_CLICK_EVENT_BATTLE", CPythonNonPlayer::ON_CLICK_EVENT_BATTLE); - PyModule_AddIntConstant(poModule, "ON_CLICK_EVENT_SHOP", CPythonNonPlayer::ON_CLICK_EVENT_SHOP); - PyModule_AddIntConstant(poModule, "ON_CLICK_EVENT_TALK", CPythonNonPlayer::ON_CLICK_EVENT_TALK); - PyModule_AddIntConstant(poModule, "ON_CLICK_EVENT_VEHICLE", CPythonNonPlayer::ON_CLICK_EVENT_VEHICLE); - PyModule_AddIntConstant(poModule, "PAWN", 0); - PyModule_AddIntConstant(poModule, "S_PAWN", 1); - PyModule_AddIntConstant(poModule, "KNIGHT", 2); - PyModule_AddIntConstant(poModule, "S_KNIGHT", 3); - PyModule_AddIntConstant(poModule, "BOSS", 4); - PyModule_AddIntConstant(poModule, "KING", 5); -} - // 40250 UserInterface/PythonProfilerModule.cpp void AddStubConstants_profiler(PyObject* poModule) { diff --git a/extension/src/platform/ScriptLib/GameplayModules.cpp b/extension/src/platform/ScriptLib/GameplayModules.cpp index 6a91cb66..4dff03e0 100644 --- a/extension/src/platform/ScriptLib/GameplayModules.cpp +++ b/extension/src/platform/ScriptLib/GameplayModules.cpp @@ -14,7 +14,6 @@ void AddStubConstants_ime(PyObject* poModule); void AddStubConstants_item(PyObject* poModule); void AddStubConstants_messenger(PyObject* poModule); void AddStubConstants_miniMap(PyObject* poModule); -void AddStubConstants_nonplayer(PyObject* poModule); void AddStubConstants_profiler(PyObject* poModule); void AddStubConstants_quest(PyObject* poModule); void AddStubConstants_safebox(PyObject* poModule); @@ -519,22 +518,6 @@ PyMethodDef methods_miniMap[] = { { "GetGuildAreaID", stub_miniMap_GetGuildAreaID, METH_VARARGS }, { NULL, NULL } }; -// 40250 UserInterface/PythonNonPlayerModule.cpp: nonplayer export names. -PyObject* stub_nonplayer_GetEventType(PyObject*, PyObject*) { return stub_call_named("nonplayer.GetEventType", Py_BuildValue("i", 0)); } -PyObject* stub_nonplayer_GetEventTypeByVID(PyObject*, PyObject*) { return stub_call_named("nonplayer.GetEventTypeByVID", Py_BuildValue("i", 0)); } -PyObject* stub_nonplayer_GetLevelByVID(PyObject*, PyObject*) { return stub_call_named("nonplayer.GetLevelByVID", Py_BuildValue("i", 0)); } -PyObject* stub_nonplayer_GetGradeByVID(PyObject*, PyObject*) { return stub_call_named("nonplayer.GetGradeByVID", Py_BuildValue("i", 0)); } -PyObject* stub_nonplayer_GetMonsterName(PyObject*, PyObject*) { return stub_call_named("nonplayer.GetMonsterName", Py_BuildValue("s", "")); } -PyObject* stub_nonplayer_LoadNonPlayerData(PyObject*, PyObject*) { return stub_call_named("nonplayer.LoadNonPlayerData", Py_BuildNone()); } -PyMethodDef methods_nonplayer[] = { - { "GetEventType", stub_nonplayer_GetEventType, METH_VARARGS }, - { "GetEventTypeByVID", stub_nonplayer_GetEventTypeByVID, METH_VARARGS }, - { "GetLevelByVID", stub_nonplayer_GetLevelByVID, METH_VARARGS }, - { "GetGradeByVID", stub_nonplayer_GetGradeByVID, METH_VARARGS }, - { "GetMonsterName", stub_nonplayer_GetMonsterName, METH_VARARGS }, - { "LoadNonPlayerData", stub_nonplayer_LoadNonPlayerData, METH_VARARGS }, - { NULL, NULL } -}; // 40250 UserInterface/PythonProfilerModule.cpp: profiler export names. PyObject* stub_profiler_Push(PyObject*, PyObject*) { return stub_call_named("profiler.Push", Py_BuildNone()); } PyObject* stub_profiler_Pop(PyObject*, PyObject*) { return stub_call_named("profiler.Pop", Py_BuildNone()); } @@ -922,11 +905,6 @@ void init_2v0_gameplay_stubs() { PyModule_AddIntConstant(module, "__port_stub__", 1); AddStubConstants_miniMap(module); } - { - PyObject* module = Py_InitModule("nonplayer", methods_nonplayer); - PyModule_AddIntConstant(module, "__port_stub__", 1); - AddStubConstants_nonplayer(module); - } { PyObject* module = Py_InitModule("profiler", methods_profiler); PyModule_AddIntConstant(module, "__port_stub__", 1); diff --git a/extension/src/platform/ScriptLib/PythonBoot.cpp b/extension/src/platform/ScriptLib/PythonBoot.cpp index 7612443a..9c67990e 100644 --- a/extension/src/platform/ScriptLib/PythonBoot.cpp +++ b/extension/src/platform/ScriptLib/PythonBoot.cpp @@ -347,6 +347,7 @@ bool run_main_script_body(const char* lpCmdLine, std::string* error) initchr(); initchrmgr(); initPlayer(); + initNonPlayer(); initChat(); initnet(); initeffect(); diff --git a/extension/src/platform/UserInterface/PythonApplication.cpp b/extension/src/platform/UserInterface/PythonApplication.cpp index 09c5a179..4940e1ef 100644 --- a/extension/src/platform/UserInterface/PythonApplication.cpp +++ b/extension/src/platform/UserInterface/PythonApplication.cpp @@ -7,6 +7,9 @@ #include "EterLib/ResourceManager.h" #include "UserInterface/PythonNetworkStream.h" #include "UserInterface/AccountConnector.h" +#include "UserInterface/PythonSkill.h" +#include "UserInterface/PythonNonPlayer.h" +#include "GameLib/ItemManager.h" #include "EterLib/NetDevice.h" #include "../PlatformStub.h" #include "../EterLib/UIRenderCommands.h" @@ -311,7 +314,91 @@ BOOL PERF_CHECKER_RENDER_GAME = FALSE; BOOL SKILL_EFFECT_UPGRADE_ENABLE = FALSE; double g_specularSpd = 0; -bool LoadLocaleData(const char*) { MT_PLATFORM_STUB(); return false; } +// 40250 UserInterface/PythonApplication.cpp, verbatim. PORT: CPythonSkill is still a stand-in, so +// RegisterSkillDesc fails and the function returns false after the item and mob tables load. +// SUPPORT_NEW_KOREA_SERVER +bool LoadLocaleData(const char* localePath) +{ + NANOBEGIN + CPythonNonPlayer& rkNPCMgr = CPythonNonPlayer::Instance(); + CItemManager& rkItemMgr = CItemManager::Instance(); + CPythonSkill& rkSkillMgr = CPythonSkill::Instance(); + CPythonNetworkStream& rkNetStream = CPythonNetworkStream::Instance(); + + char szItemList[256]; + char szItemProto[256]; + char szItemDesc[256]; + char szMobProto[256]; + char szSkillDescFileName[256]; + char szSkillTableFileName[256]; + char szInsultList[256]; + snprintf(szItemList, sizeof(szItemList) , "%s/item_list.txt", localePath); + snprintf(szItemProto, sizeof(szItemProto), "%s/item_proto", localePath); + snprintf(szItemDesc, sizeof(szItemDesc), "%s/itemdesc.txt", localePath); + snprintf(szMobProto, sizeof(szMobProto), "%s/mob_proto", localePath); + snprintf(szSkillDescFileName, sizeof(szSkillDescFileName), "%s/SkillDesc.txt", localePath); + snprintf(szSkillTableFileName, sizeof(szSkillTableFileName), "%s/SkillTable.txt", localePath); + snprintf(szInsultList, sizeof(szInsultList), "%s/insult.txt", localePath); + + rkNPCMgr.Destroy(); + rkItemMgr.Destroy(); + rkSkillMgr.Destroy(); + + if (!rkItemMgr.LoadItemList(szItemList)) + { + TraceError("LoadLocaleData - LoadItemList(%s) Error", szItemList); + } + + if (!rkItemMgr.LoadItemTable(szItemProto)) + { + TraceError("LoadLocaleData - LoadItemProto(%s) Error", szItemProto); + return false; + } + + if (!rkItemMgr.LoadItemDesc(szItemDesc)) + { + Tracenf("LoadLocaleData - LoadItemDesc(%s) Error", szItemDesc); + } + + if (!rkNPCMgr.LoadNonPlayerData(szMobProto)) + { + TraceError("LoadLocaleData - LoadMobProto(%s) Error", szMobProto); + return false; + } + + if (!rkSkillMgr.RegisterSkillDesc(szSkillDescFileName)) + { + TraceError("LoadLocaleData - RegisterSkillDesc(%s) Error", szMobProto); + return false; + } + + if (!rkSkillMgr.RegisterSkillTable(szSkillTableFileName)) + { + TraceError("LoadLocaleData - RegisterSkillTable(%s) Error", szMobProto); + return false; + } + + if (!rkNetStream.LoadInsultList(szInsultList)) + { + Tracenf("CPythonApplication - CPythonNetworkStream::LoadInsultList(%s)", szInsultList); + } + + if (LocaleService_IsYMIR()) + { + char szEmpireTextConvFile[256]; + for (DWORD dwEmpireID=1; dwEmpireID<=3; ++dwEmpireID) + { + sprintf(szEmpireTextConvFile, "%s/lang%d.cvt", localePath, dwEmpireID); + if (!rkNetStream.LoadConvertTable(dwEmpireID, szEmpireTextConvFile)) + { + TraceError("LoadLocaleData - CPythonNetworkStream::LoadConvertTable(%d, %s) FAILURE", dwEmpireID, szEmpireTextConvFile); + } + } + } + + NANOEND + return true; +} void TextTail_SetLivingTime(long) { MT_PLATFORM_STUB(); } namespace { // The supplied 40250 Client/locale.cfg selects "en" (code page 1252). diff --git a/extension/src/platform/pending/GameLib/ItemData.cpp b/extension/src/platform/pending/GameLib/ItemData.cpp deleted file mode 100644 index 7e4e6ab2..00000000 --- a/extension/src/platform/pending/GameLib/ItemData.cpp +++ /dev/null @@ -1,133 +0,0 @@ -// Stand-in for the 40250 logic unit GameLib/ItemData.cpp, not ported yet: the members the ported units -// reference, as platform_stub.py stubs. Delete this file in the commit that ports the unit into port/ -// (docs/PORT-PLAN.md). -#include "GameLib/StdAfx.h" -#include "GameLib/ItemData.h" - -#include "../../PlatformStub.h" - -auto CItemData::GetName() const -> const char * -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemData::GetType() const -> BYTE -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemData::GetValue(BYTE) const -> long -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemData::GetIndex() const -> DWORD -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemData::GetSubType() const -> BYTE -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemData::GetRefine() const -> UINT -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemData::GetWeaponType() const -> DWORD -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemData::GetSocketCount() const -> int -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemData::GetSpecularPowerf() const -> float -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemData::GetModelThing() -> CGraphicThing * -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemData::GetSubModelThing() -> CGraphicThing * -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemData::GetLODModelThingCount() -> DWORD -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemData::GetLODModelThingPointer(DWORD, CGraphicThing **) -> BOOL -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemData::GetAttachingDataCount() -> DWORD -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemData::GetAttachingDataPointer(DWORD, const NRaceData::TAttachingData **) -> BOOL -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemData::IsAntiFlag(DWORD) const -> BOOL -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemData::IsEquipment() const -> BOOL -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemData::IsFlag(DWORD) const -> BOOL -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemData::HasNextGrade() const -> BOOL -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemData::GetWearFlags() const -> DWORD -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemData::GetISellItemPrice() const -> DWORD -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} diff --git a/extension/src/platform/pending/GameLib/ItemManager.cpp b/extension/src/platform/pending/GameLib/ItemManager.cpp deleted file mode 100644 index 6e130484..00000000 --- a/extension/src/platform/pending/GameLib/ItemManager.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// Stand-in for the 40250 logic unit GameLib/ItemManager.cpp, not ported yet: the members the ported units -// reference, as platform_stub.py stubs. Delete this file in the commit that ports the unit into port/ -// (docs/PORT-PLAN.md). -#include "GameLib/StdAfx.h" -#include "GameLib/ItemManager.h" - -#include "../../PlatformStub.h" - -CItemManager::CItemManager() -{ - MT_PLATFORM_STUB(); -} - -CItemManager::~CItemManager() -{ - MT_PLATFORM_STUB(); -} - -auto CItemManager::GetItemDataPointer(DWORD, CItemData **) -> BOOL -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemManager::SelectItemData(DWORD) -> BOOL -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CItemManager::GetSelectedItemDataPointer() -> CItemData * -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} diff --git a/extension/src/platform/pending/UserInterface/PythonNonPlayer.cpp b/extension/src/platform/pending/UserInterface/PythonNonPlayer.cpp deleted file mode 100644 index e2063b75..00000000 --- a/extension/src/platform/pending/UserInterface/PythonNonPlayer.cpp +++ /dev/null @@ -1,41 +0,0 @@ -// Stand-in for the 40250 logic unit UserInterface/PythonNonPlayer.cpp, not ported yet: the members the ported units -// reference, as platform_stub.py stubs. Delete this file in the commit that ports the unit into port/ -// (docs/PORT-PLAN.md). -#include "UserInterface/StdAfx.h" -#include "UserInterface/PythonNonPlayer.h" - -#include "../../PlatformStub.h" - -CPythonNonPlayer::CPythonNonPlayer() -{ - MT_PLATFORM_STUB(); -} - -CPythonNonPlayer::~CPythonNonPlayer() -{ - MT_PLATFORM_STUB(); -} - -auto CPythonNonPlayer::GetName(DWORD, const char **) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CPythonNonPlayer::GetInstanceType(DWORD, BYTE *) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CPythonNonPlayer::GetEventType(DWORD) -> BYTE -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CPythonNonPlayer::GetMonsterColor(DWORD) -> DWORD -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} diff --git a/extension/src/platform/pending/UserInterface/PythonSkill.cpp b/extension/src/platform/pending/UserInterface/PythonSkill.cpp index 710f01b0..9f7edd30 100644 --- a/extension/src/platform/pending/UserInterface/PythonSkill.cpp +++ b/extension/src/platform/pending/UserInterface/PythonSkill.cpp @@ -191,3 +191,20 @@ auto CPythonSkill::SSkillData::GetType() const -> BYTE MT_PLATFORM_STUB(); return mt_platform_stub_return(); } + +auto CPythonSkill::Destroy() -> void +{ + MT_PLATFORM_STUB(); +} + +auto CPythonSkill::RegisterSkillTable(const char *) -> bool +{ + MT_PLATFORM_STUB(); + return mt_platform_stub_return(); +} + +auto CPythonSkill::RegisterSkillDesc(const char *) -> bool +{ + MT_PLATFORM_STUB(); + return mt_platform_stub_return(); +} diff --git a/extension/src/port/GameLib/ItemData.cpp b/extension/src/port/GameLib/ItemData.cpp new file mode 100644 index 00000000..65566340 --- /dev/null +++ b/extension/src/port/GameLib/ItemData.cpp @@ -0,0 +1,464 @@ +#include "StdAfx.h" +#include "../EterLib/ResourceManager.h" + +#include "ItemData.h" + +CDynamicPool CItemData::ms_kPool; + +extern DWORD GetDefaultCodePage(); + +CItemData* CItemData::New() +{ + return ms_kPool.Alloc(); +} + +void CItemData::Delete(CItemData* pkItemData) +{ + pkItemData->Clear(); + ms_kPool.Free(pkItemData); +} + +void CItemData::DestroySystem() +{ + ms_kPool.Destroy(); +} + +CGraphicThing * CItemData::GetModelThing() +{ + return m_pModelThing; +} + +CGraphicThing * CItemData::GetSubModelThing() +{ + if (m_pSubModelThing) + return m_pSubModelThing; + else + return m_pModelThing; +} + +CGraphicThing * CItemData::GetDropModelThing() +{ + return m_pDropModelThing; +} + +CGraphicSubImage * CItemData::GetIconImage() +{ + if(m_pIconImage == NULL && m_strIconFileName.empty() == false) + __SetIconImage(m_strIconFileName.c_str()); + return m_pIconImage; +} + +DWORD CItemData::GetLODModelThingCount() +{ + return m_pLODModelThingVector.size(); +} + +BOOL CItemData::GetLODModelThingPointer(DWORD dwIndex, CGraphicThing ** ppModelThing) +{ + if (dwIndex >= m_pLODModelThingVector.size()) + return FALSE; + + *ppModelThing = m_pLODModelThingVector[dwIndex]; + + return TRUE; +} + +DWORD CItemData::GetAttachingDataCount() +{ + return m_AttachingDataVector.size(); +} + +BOOL CItemData::GetCollisionDataPointer(DWORD dwIndex, const NRaceData::TAttachingData ** c_ppAttachingData) +{ + if (dwIndex >= GetAttachingDataCount()) + return FALSE; + + if (NRaceData::ATTACHING_DATA_TYPE_COLLISION_DATA != m_AttachingDataVector[dwIndex].dwType) + return FALSE; + + *c_ppAttachingData = &m_AttachingDataVector[dwIndex]; + return TRUE; +} + +BOOL CItemData::GetAttachingDataPointer(DWORD dwIndex, const NRaceData::TAttachingData ** c_ppAttachingData) +{ + if (dwIndex >= GetAttachingDataCount()) + return FALSE; + + *c_ppAttachingData = &m_AttachingDataVector[dwIndex]; + return TRUE; +} + +void CItemData::SetSummary(const std::string& c_rstSumm) +{ + m_strSummary=c_rstSumm; +} + +void CItemData::SetDescription(const std::string& c_rstDesc) +{ + m_strDescription=c_rstDesc; +} +/* +BOOL CItemData::LoadItemData(const char * c_szFileName) +{ + CTextFileLoader TextFileLoader; + + if (!TextFileLoader.Load(c_szFileName)) + { + //Lognf(1, "CItemData::LoadItemData(c_szFileName=%s) - FAILED", c_szFileName); + return FALSE; + } + + TextFileLoader.SetTop(); + + TextFileLoader.GetTokenString("modelfilename", &m_strModelFileName); + TextFileLoader.GetTokenString("submodelfilename", &m_strSubModelFileName); + TextFileLoader.GetTokenString("dropmodelfilename", &m_strDropModelFileName); + TextFileLoader.GetTokenString("iconimagefilename", &m_strIconFileName); + + char szDescriptionKey[32+1]; + _snprintf(szDescriptionKey, 32, "%ddescription", GetDefaultCodePage()); + if (!TextFileLoader.GetTokenString(szDescriptionKey, &m_strDescription)) + { + TextFileLoader.GetTokenString("description", &m_strDescription); + } + + // LOD Model File Name List + CTokenVector * pLODModelList; + if (TextFileLoader.GetTokenVector("lodmodellist", &pLODModelList)) + { + m_strLODModelFileNameVector.clear(); + m_strLODModelFileNameVector.resize(pLODModelList->size()); + + for (DWORD i = 0; i < pLODModelList->size(); ++i) + { + m_strLODModelFileNameVector[i] = pLODModelList->at(0); + } + } + + // Attaching Data + // Item 에 Attaching Data 일단 없음. +// if (TextFileLoader.SetChildNode("attachingdata")) +// { +// if (!NRaceData::LoadAttachingData(TextFileLoader, &m_AttachingDataVector)) +// return FALSE; +// +// TextFileLoader.SetParentNode(); +// } + + __LoadFiles(); + + return TRUE; +} +*/ +void CItemData::SetDefaultItemData(const char * c_szIconFileName, const char * c_szModelFileName) +{ + if(c_szModelFileName) + { + m_strModelFileName = c_szModelFileName; + m_strDropModelFileName = c_szModelFileName; + } + else + { + m_strModelFileName = ""; + m_strDropModelFileName = "d:/ymir work/item/etc/item_bag.gr2"; + } + m_strIconFileName = c_szIconFileName; + + m_strSubModelFileName = ""; + m_strDescription = ""; + m_strSummary = ""; + memset(m_ItemTable.alSockets, 0, sizeof(m_ItemTable.alSockets)); + + __LoadFiles(); +} + +void CItemData::__LoadFiles() +{ + // Model File Name + if (!m_strModelFileName.empty()) + m_pModelThing = (CGraphicThing *)CResourceManager::Instance().GetResourcePointer(m_strModelFileName.c_str()); + + if (!m_strSubModelFileName.empty()) + m_pSubModelThing = (CGraphicThing *)CResourceManager::Instance().GetResourcePointer(m_strSubModelFileName.c_str()); + + if (!m_strDropModelFileName.empty()) + m_pDropModelThing = (CGraphicThing *)CResourceManager::Instance().GetResourcePointer(m_strDropModelFileName.c_str()); + + + if (!m_strLODModelFileNameVector.empty()) + { + m_pLODModelThingVector.clear(); + m_pLODModelThingVector.resize(m_strLODModelFileNameVector.size()); + + for (DWORD i = 0; i < m_strLODModelFileNameVector.size(); ++i) + { + const std::string & c_rstrLODModelFileName = m_strLODModelFileNameVector[i]; + m_pLODModelThingVector[i] = (CGraphicThing *)CResourceManager::Instance().GetResourcePointer(c_rstrLODModelFileName.c_str()); + } + } +} + +void CItemData::__SetIconImage(const char * c_szFileName) +{ + if (!CResourceManager::Instance().IsFileExist(c_szFileName)) + { + TraceError("%s \306\304\300\317\300\314 \276\370\275\300\264\317\264\331.CItemData::__SetIconImage",c_szFileName); + m_pIconImage = NULL; + } + else if (m_pIconImage == NULL) + m_pIconImage = (CGraphicSubImage *)CResourceManager::Instance().GetResourcePointer(c_szFileName); +} + +void CItemData::SetItemTableData(TItemTable * pItemTable) +{ + memcpy(&m_ItemTable, pItemTable, sizeof(TItemTable)); +} + +const CItemData::TItemTable* CItemData::GetTable() const +{ + return &m_ItemTable; +} + +DWORD CItemData::GetIndex() const +{ + return m_ItemTable.dwVnum; +} + +const char * CItemData::GetName() const +{ + return m_ItemTable.szLocaleName; +} + +const char * CItemData::GetDescription() const +{ + return m_strDescription.c_str(); +} + +const char * CItemData::GetSummary() const +{ + return m_strSummary.c_str(); +} + + +BYTE CItemData::GetType() const +{ + return m_ItemTable.bType; +} + +BYTE CItemData::GetSubType() const +{ + return m_ItemTable.bSubType; +} + +#define DEF_STR(x) #x + +const char* CItemData::GetUseTypeString() const +{ + if (GetType() != CItemData::ITEM_TYPE_USE) + return "NOT_USE_TYPE"; + + switch (GetSubType()) + { + case USE_TUNING: + return DEF_STR(USE_TUNING); + case USE_DETACHMENT: + return DEF_STR(USE_DETACHMENT); + case USE_CLEAN_SOCKET: + return DEF_STR(USE_CLEAN_SOCKET); + case USE_CHANGE_ATTRIBUTE: + return DEF_STR(USE_CHANGE_ATTRIBUTE); + case USE_ADD_ATTRIBUTE: + return DEF_STR(USE_ADD_ATTRIBUTE); + case USE_ADD_ATTRIBUTE2: + return DEF_STR(USE_ADD_ATTRIBUTE2); + case USE_ADD_ACCESSORY_SOCKET: + return DEF_STR(USE_ADD_ACCESSORY_SOCKET); + case USE_PUT_INTO_ACCESSORY_SOCKET: + return DEF_STR(USE_PUT_INTO_ACCESSORY_SOCKET); + case USE_PUT_INTO_BELT_SOCKET: + return DEF_STR(USE_PUT_INTO_BELT_SOCKET); + case USE_PUT_INTO_RING_SOCKET: + return DEF_STR(USE_PUT_INTO_RING_SOCKET); + } + return "USE_UNKNOWN_TYPE"; +} + + +DWORD CItemData::GetWeaponType() const +{ + return m_ItemTable.bSubType; +} + +BYTE CItemData::GetSize() const +{ + return m_ItemTable.bSize; +} + +BOOL CItemData::IsAntiFlag(DWORD dwFlag) const +{ + return (dwFlag & m_ItemTable.dwAntiFlags) != 0; +} + +BOOL CItemData::IsFlag(DWORD dwFlag) const +{ + return (dwFlag & m_ItemTable.dwFlags) != 0; +} + +BOOL CItemData::IsWearableFlag(DWORD dwFlag) const +{ + return (dwFlag & m_ItemTable.dwWearFlags) != 0; +} + +BOOL CItemData::HasNextGrade() const +{ + return 0 != m_ItemTable.dwRefinedVnum; +} + +DWORD CItemData::GetWearFlags() const +{ + return m_ItemTable.dwWearFlags; +} + +DWORD CItemData::GetIBuyItemPrice() const +{ + return m_ItemTable.dwIBuyItemPrice; +} + +DWORD CItemData::GetISellItemPrice() const +{ + return m_ItemTable.dwISellItemPrice; +} + + +BOOL CItemData::GetLimit(BYTE byIndex, TItemLimit * pItemLimit) const +{ + if (byIndex >= ITEM_LIMIT_MAX_NUM) + { + assert(byIndex < ITEM_LIMIT_MAX_NUM); + return FALSE; + } + + *pItemLimit = m_ItemTable.aLimits[byIndex]; + + return TRUE; +} + +BOOL CItemData::GetApply(BYTE byIndex, TItemApply * pItemApply) const +{ + if (byIndex >= ITEM_APPLY_MAX_NUM) + { + assert(byIndex < ITEM_APPLY_MAX_NUM); + return FALSE; + } + + *pItemApply = m_ItemTable.aApplies[byIndex]; + return TRUE; +} + +long CItemData::GetValue(BYTE byIndex) const +{ + if (byIndex >= ITEM_VALUES_MAX_NUM) + { + assert(byIndex < ITEM_VALUES_MAX_NUM); + return 0; + } + + return m_ItemTable.alValues[byIndex]; +} + +long CItemData::SetSocket(BYTE byIndex,DWORD value) +{ + if (byIndex >= ITEM_SOCKET_MAX_NUM) + { + assert(byIndex < ITEM_SOCKET_MAX_NUM); + return -1; + } + + return m_ItemTable.alSockets[byIndex] = value; +} + +long CItemData::GetSocket(BYTE byIndex) const +{ + if (byIndex >= ITEM_SOCKET_MAX_NUM) + { + assert(byIndex < ITEM_SOCKET_MAX_NUM); + return -1; + } + + return m_ItemTable.alSockets[byIndex]; +} + +//서버와 동일 서버 함수 변경시 같이 변경!!(이후에 합친다) +//SocketCount = 1 이면 초급무기 +//SocketCount = 2 이면 중급무기 +//SocketCount = 3 이면 고급무기 +int CItemData::GetSocketCount() const +{ + return m_ItemTable.bGainSocketPct; +} + +DWORD CItemData::GetIconNumber() const +{ + return m_ItemTable.dwVnum; +//!@# +// return m_ItemTable.dwIconNumber; +} + +UINT CItemData::GetSpecularPoweru() const +{ + return m_ItemTable.bSpecular; +} + +float CItemData::GetSpecularPowerf() const +{ + UINT uSpecularPower=GetSpecularPoweru(); + + return float(uSpecularPower) / 100.0f; +} + +//refine 값은 아이템번호 끝자리와 일치한다-_-(테이블이용으로 바꿀 예정) +UINT CItemData::GetRefine() const +{ + return GetIndex()%10; +} + +BOOL CItemData::IsEquipment() const +{ + switch (GetType()) + { + case ITEM_TYPE_WEAPON: + case ITEM_TYPE_ARMOR: + return TRUE; + break; + } + + return FALSE; +} + +void CItemData::Clear() +{ + m_strSummary = ""; + m_strModelFileName = ""; + m_strSubModelFileName = ""; + m_strDropModelFileName = ""; + m_strIconFileName = ""; + m_strLODModelFileNameVector.clear(); + + m_pModelThing = NULL; + m_pSubModelThing = NULL; + m_pDropModelThing = NULL; + m_pIconImage = NULL; + m_pLODModelThingVector.clear(); + + memset(&m_ItemTable, 0, sizeof(m_ItemTable)); +} + +CItemData::CItemData() +{ + Clear(); +} + +CItemData::~CItemData() +{ +} diff --git a/extension/src/port/GameLib/ItemManager.cpp b/extension/src/port/GameLib/ItemManager.cpp new file mode 100644 index 00000000..f0d76fab --- /dev/null +++ b/extension/src/port/GameLib/ItemManager.cpp @@ -0,0 +1,404 @@ +#include "StdAfx.h" +#include "../EterPack/EterPackManager.h" +#include "../EterLib/ResourceManager.h" + +#include "ItemManager.h" + +static DWORD s_adwItemProtoKey[4] = +{ + 173217, + 72619434, + 408587239, + 27973291 +}; + +BOOL CItemManager::SelectItemData(DWORD dwIndex) +{ + TItemMap::iterator f = m_ItemMap.find(dwIndex); + + if (m_ItemMap.end() == f) + { + int n = m_vec_ItemRange.size(); + for (int i = 0; i < n; i++) + { + CItemData * p = m_vec_ItemRange[i]; + const CItemData::TItemTable * pTable = p->GetTable(); + if ((pTable->dwVnum < dwIndex) && + dwIndex < (pTable->dwVnum + pTable->dwVnumRange)) + { + m_pSelectedItemData = p; + return TRUE; + } + } + Tracef(" CItemManager::SelectItemData - FIND ERROR [%d]\n", dwIndex); + return FALSE; + } + + m_pSelectedItemData = f->second; + + return TRUE; +} + +CItemData * CItemManager::GetSelectedItemDataPointer() +{ + return m_pSelectedItemData; +} + +BOOL CItemManager::GetItemDataPointer(DWORD dwItemID, CItemData ** ppItemData) +{ + if (0 == dwItemID) + return FALSE; + + TItemMap::iterator f = m_ItemMap.find(dwItemID); + + if (m_ItemMap.end() == f) + { + int n = m_vec_ItemRange.size(); + for (int i = 0; i < n; i++) + { + CItemData * p = m_vec_ItemRange[i]; + const CItemData::TItemTable * pTable = p->GetTable(); + if ((pTable->dwVnum < dwItemID) && + dwItemID < (pTable->dwVnum + pTable->dwVnumRange)) + { + *ppItemData = p; + return TRUE; + } + } + Tracef(" CItemManager::GetItemDataPointer - FIND ERROR [%d]\n", dwItemID); + return FALSE; + } + + *ppItemData = f->second; + + return TRUE; +} + +CItemData * CItemManager::MakeItemData(DWORD dwIndex) +{ + TItemMap::iterator f = m_ItemMap.find(dwIndex); + + if (m_ItemMap.end() == f) + { + CItemData * pItemData = CItemData::New(); + + m_ItemMap.insert(TItemMap::value_type(dwIndex, pItemData)); + + return pItemData; + } + + return f->second; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// Load Item Table + +bool CItemManager::LoadItemList(const char * c_szFileName) +{ + CMappedFile File; + LPCVOID pData; + + if (!CEterPackManager::Instance().Get(File, c_szFileName, &pData)) + return false; + + CMemoryTextFileLoader textFileLoader; + textFileLoader.Bind(File.Size(), pData); + + CTokenVector TokenVector; + for (DWORD i = 0; i < textFileLoader.GetLineCount(); ++i) + { + if (!textFileLoader.SplitLine(i, &TokenVector, "\t")) + continue; + + if (!(TokenVector.size() == 3 || TokenVector.size() == 4)) + { + TraceError(" CItemManager::LoadItemList(%s) - StrangeLine in %d\n", c_szFileName, i); + continue; + } + + const std::string & c_rstrID = TokenVector[0]; + //const std::string & c_rstrType = TokenVector[1]; + const std::string & c_rstrIcon = TokenVector[2]; + + DWORD dwItemVNum=atoi(c_rstrID.c_str()); + + CItemData * pItemData = MakeItemData(dwItemVNum); + + extern BOOL USE_VIETNAM_CONVERT_WEAPON_VNUM; + if (USE_VIETNAM_CONVERT_WEAPON_VNUM) + { + extern DWORD Vietnam_ConvertWeaponVnum(DWORD vnum); + DWORD dwMildItemVnum = Vietnam_ConvertWeaponVnum(dwItemVNum); + if (dwMildItemVnum == dwItemVNum) + { + if (4 == TokenVector.size()) + { + const std::string & c_rstrModelFileName = TokenVector[3]; + pItemData->SetDefaultItemData(c_rstrIcon.c_str(), c_rstrModelFileName.c_str()); + } + else + { + pItemData->SetDefaultItemData(c_rstrIcon.c_str()); + } + } + else + { + DWORD dwMildBaseVnum = dwMildItemVnum / 10 * 10; + char szMildIconPath[MAX_PATH]; + sprintf(szMildIconPath, "icon/item/%.5d.tga", dwMildBaseVnum); + if (4 == TokenVector.size()) + { + char szMildModelPath[MAX_PATH]; + sprintf(szMildModelPath, "d:/ymir work/item/weapon/%.5d.gr2", dwMildBaseVnum); + pItemData->SetDefaultItemData(szMildIconPath, szMildModelPath); + } + else + { + pItemData->SetDefaultItemData(szMildIconPath); + } + } + } + else + { + if (4 == TokenVector.size()) + { + const std::string & c_rstrModelFileName = TokenVector[3]; + pItemData->SetDefaultItemData(c_rstrIcon.c_str(), c_rstrModelFileName.c_str()); + } + else + { + pItemData->SetDefaultItemData(c_rstrIcon.c_str()); + } + } + } + + return true; +} + +const std::string& __SnapString(const std::string& c_rstSrc, std::string& rstTemp) +{ + UINT uSrcLen=c_rstSrc.length(); + if (uSrcLen<2) + return c_rstSrc; + + if (c_rstSrc[0]!='"') + return c_rstSrc; + + UINT uLeftCut=1; + + UINT uRightCut=uSrcLen; + if (c_rstSrc[uSrcLen-1]=='"') + uRightCut=uSrcLen-1; + + rstTemp=c_rstSrc.substr(uLeftCut, uRightCut-uLeftCut); + return rstTemp; +} + +bool CItemManager::LoadItemDesc(const char* c_szFileName) +{ + const VOID* pvData; + CMappedFile kFile; + if (!CEterPackManager::Instance().Get(kFile, c_szFileName, &pvData)) + { + Tracenf("CItemManager::LoadItemDesc(c_szFileName=%s) - Load Error", c_szFileName); + return false; + } + + CMemoryTextFileLoader kTextFileLoader; + kTextFileLoader.Bind(kFile.Size(), pvData); + + std::string stTemp; + + CTokenVector kTokenVector; + for (DWORD i = 0; i < kTextFileLoader.GetLineCount(); ++i) + { + if (!kTextFileLoader.SplitLineByTab(i, &kTokenVector)) + continue; + + while (kTokenVector.size()second; + + pkItemDataFind->SetDescription(__SnapString(c_rstDesc, stTemp)); + pkItemDataFind->SetSummary(__SnapString(c_rstSumm, stTemp)); + } + return true; +} + +DWORD GetHashCode( const char* pString ) +{ + unsigned long i,len; + unsigned long ch; + unsigned long result; + + len = strlen( pString ); + result = 5381; + for( i=0; i itemNameMap; + + for (DWORD i = 0; i < dwElements; ++i, ++table) + { + CItemData * pItemData; + DWORD dwVnum = table->dwVnum; + + TItemMap::iterator f = m_ItemMap.find(dwVnum); + if (m_ItemMap.end() == f) + { + _snprintf(szName, sizeof(szName), "icon/item/%05d.tga", dwVnum); + + if (CResourceManager::Instance().IsFileExist(szName) == false) + { + std::map::iterator itVnum = itemNameMap.find(GetHashCode(table->szName)); + + if (itVnum != itemNameMap.end()) + _snprintf(szName, sizeof(szName), "icon/item/%05d.tga", itVnum->second); + else + _snprintf(szName, sizeof(szName), "icon/item/%05d.tga", dwVnum-dwVnum % 10); + + if (CResourceManager::Instance().IsFileExist(szName) == false) + { + #ifdef _DEBUG + TraceError("%16s(#%-5d) cannot find icon file. setting to default.", table->szName, dwVnum); + #endif + const DWORD EmptyBowl = 27995; + _snprintf(szName, sizeof(szName), "icon/item/%05d.tga", EmptyBowl); + } + } + + pItemData = CItemData::New(); + + pItemData->SetDefaultItemData(szName); + m_ItemMap.insert(TItemMap::value_type(dwVnum, pItemData)); + } + else + { + pItemData = f->second; + } + if (itemNameMap.find(GetHashCode(table->szName)) == itemNameMap.end()) + itemNameMap.insert(std::map::value_type(GetHashCode(table->szName),table->dwVnum)); + pItemData->SetItemTableData(table); + if (0 != table->dwVnumRange) + { + m_vec_ItemRange.push_back(pItemData); + } + } + +//!@# +// CItemData::TItemTable * table = (CItemData::TItemTable *) zObj.GetBuffer(); +// for (DWORD i = 0; i < dwElements; ++i, ++table) +// { +// CItemData * pItemData; +// DWORD dwVnum = table->dwVnum; +// +// TItemMap::iterator f = m_ItemMap.find(dwVnum); +// +// if (m_ItemMap.end() == f) +// { +// pItemData = CItemData::New(); +// +// pItemData->LoadItemData(_getf("d:/ymir work/item/%05d.msm", dwVnum)); +// m_ItemMap.insert(TItemMap::value_type(dwVnum, pItemData)); +// } +// else +// { +// pItemData = f->second; +// } +// pItemData->SetItemTableData(table); +// } + + delete [] pbData; + return true; +} + +void CItemManager::Destroy() +{ + TItemMap::iterator i; + for (i=m_ItemMap.begin(); i!=m_ItemMap.end(); ++i) + CItemData::Delete(i->second); + + m_ItemMap.clear(); +} + +CItemManager::CItemManager() : m_pSelectedItemData(NULL) +{ +} +CItemManager::~CItemManager() +{ + Destroy(); +} diff --git a/extension/src/port/UserInterface/PythonNonPlayer.cpp b/extension/src/port/UserInterface/PythonNonPlayer.cpp new file mode 100644 index 00000000..77a99865 --- /dev/null +++ b/extension/src/port/UserInterface/PythonNonPlayer.cpp @@ -0,0 +1,197 @@ +#include "StdAfx.h" +#include "../EterPack/EterPackManager.h" +#include "PythonNonPlayer.h" +#include "InstanceBase.h" +#include "PythonCharacterManager.h" + +bool CPythonNonPlayer::LoadNonPlayerData(const char * c_szFileName) +{ + static DWORD s_adwMobProtoKey[4] = + { + 4813894, + 18955, + 552631, + 6822045 + }; + + CMappedFile file; + LPCVOID pvData; + + Tracef("CPythonNonPlayer::LoadNonPlayerData: %s, sizeof(TMobTable)=%u\n", c_szFileName, sizeof(TMobTable)); + + if (!CEterPackManager::Instance().Get(file, c_szFileName, &pvData)) + return false; + + DWORD dwFourCC, dwElements, dwDataSize; + + file.Read(&dwFourCC, sizeof(DWORD)); + + if (dwFourCC != MAKEFOURCC('M', 'M', 'P', 'T')) + { + TraceError("CPythonNonPlayer::LoadNonPlayerData: invalid Mob proto type %s", c_szFileName); + return false; + } + + file.Read(&dwElements, sizeof(DWORD)); + file.Read(&dwDataSize, sizeof(DWORD)); + + BYTE * pbData = new BYTE[dwDataSize]; + file.Read(pbData, dwDataSize); + ///// + + CLZObject zObj; + + if (!CLZO::Instance().Decompress(zObj, pbData, s_adwMobProtoKey)) + { + delete [] pbData; + return false; + } + + if ((zObj.GetSize() % sizeof(TMobTable)) != 0) + { + TraceError("CPythonNonPlayer::LoadNonPlayerData: invalid size %u check data format.", zObj.GetSize()); + return false; + } + + TMobTable * pTable = (TMobTable *) zObj.GetBuffer(); + for (DWORD i = 0; i < dwElements; ++i, ++pTable) + { + TMobTable * pNonPlayerData = new TMobTable; + + memcpy(pNonPlayerData, pTable, sizeof(TMobTable)); + + //TraceError("%d : %s type[%d] color[%d]", pNonPlayerData->dwVnum, pNonPlayerData->szLocaleName, pNonPlayerData->bType, pNonPlayerData->dwMonsterColor); + m_NonPlayerDataMap.insert(TNonPlayerDataMap::value_type(pNonPlayerData->dwVnum, pNonPlayerData)); + } + + delete [] pbData; + return true; +} + +bool CPythonNonPlayer::GetName(DWORD dwVnum, const char ** c_pszName) +{ + const TMobTable * p = GetTable(dwVnum); + + if (!p) + return false; + + *c_pszName = p->szLocaleName; + + return true; +} + +bool CPythonNonPlayer::GetInstanceType(DWORD dwVnum, BYTE* pbType) +{ + const TMobTable * p = GetTable(dwVnum); + + // dwVnum를 찾을 수 없으면 플레이어 캐릭터로 간주 한다. 문제성 코드 -_- [cronan] + if (!p) + return false; + + *pbType=p->bType; + + return true; +} + +const CPythonNonPlayer::TMobTable * CPythonNonPlayer::GetTable(DWORD dwVnum) +{ + TNonPlayerDataMap::iterator itor = m_NonPlayerDataMap.find(dwVnum); + + if (itor == m_NonPlayerDataMap.end()) + return NULL; + + return itor->second; +} + +BYTE CPythonNonPlayer::GetEventType(DWORD dwVnum) +{ + const TMobTable * p = GetTable(dwVnum); + + if (!p) + { + //Tracef("CPythonNonPlayer::GetEventType - Failed to find virtual number\n"); + return ON_CLICK_EVENT_NONE; + } + + return p->bOnClickType; +} + +BYTE CPythonNonPlayer::GetEventTypeByVID(DWORD dwVID) +{ + CInstanceBase * pInstance = CPythonCharacterManager::Instance().GetInstancePtr(dwVID); + + if (NULL == pInstance) + { + //Tracef("CPythonNonPlayer::GetEventTypeByVID - There is no Virtual Number\n"); + return ON_CLICK_EVENT_NONE; + } + + WORD dwVnum = pInstance->GetVirtualNumber(); + return GetEventType(dwVnum); +} + +const char* CPythonNonPlayer::GetMonsterName(DWORD dwVnum) +{ + const CPythonNonPlayer::TMobTable * c_pTable = GetTable(dwVnum); + if (!c_pTable) + { + static const char* sc_szEmpty=""; + return sc_szEmpty; + } + + return c_pTable->szLocaleName; +} + +DWORD CPythonNonPlayer::GetMonsterColor(DWORD dwVnum) +{ + const CPythonNonPlayer::TMobTable * c_pTable = GetTable(dwVnum); + if (!c_pTable) + return 0; + + return c_pTable->dwMonsterColor; +} + +void CPythonNonPlayer::GetMatchableMobList(int iLevel, int iInterval, TMobTableList * pMobTableList) +{ +/* + pMobTableList->clear(); + + TNonPlayerDataMap::iterator itor = m_NonPlayerDataMap.begin(); + for (; itor != m_NonPlayerDataMap.end(); ++itor) + { + TMobTable * pMobTable = itor->second; + + int iLowerLevelLimit = iLevel-iInterval; + int iUpperLevelLimit = iLevel+iInterval; + + if ((pMobTable->abLevelRange[0] >= iLowerLevelLimit && pMobTable->abLevelRange[0] <= iUpperLevelLimit) || + (pMobTable->abLevelRange[1] >= iLowerLevelLimit && pMobTable->abLevelRange[1] <= iUpperLevelLimit)) + { + pMobTableList->push_back(pMobTable); + } + } +*/ +} + +void CPythonNonPlayer::Clear() +{ +} + +void CPythonNonPlayer::Destroy() +{ + for (TNonPlayerDataMap::iterator itor=m_NonPlayerDataMap.begin(); itor!=m_NonPlayerDataMap.end(); ++itor) + { + delete itor->second; + } + m_NonPlayerDataMap.clear(); +} + +CPythonNonPlayer::CPythonNonPlayer() +{ + Clear(); +} + +CPythonNonPlayer::~CPythonNonPlayer(void) +{ + Destroy(); +} \ No newline at end of file diff --git a/extension/src/port/UserInterface/PythonNonPlayerModule.cpp b/extension/src/port/UserInterface/PythonNonPlayerModule.cpp new file mode 100644 index 00000000..133cdaf3 --- /dev/null +++ b/extension/src/port/UserInterface/PythonNonPlayerModule.cpp @@ -0,0 +1,119 @@ +#include "StdAfx.h" +#include "PythonNonPlayer.h" + +#include "InstanceBase.h" +#include "PythonCharacterManager.h" + +PyObject * nonplayerGetEventType(PyObject * poSelf, PyObject * poArgs) +{ + int iVirtualNumber; + if (!PyTuple_GetInteger(poArgs, 0, &iVirtualNumber)) + return Py_BuildException(); + + BYTE iType = CPythonNonPlayer::Instance().GetEventType(iVirtualNumber); + + return Py_BuildValue("i", iType); +} + +PyObject * nonplayerGetEventTypeByVID(PyObject * poSelf, PyObject * poArgs) +{ + int iVirtualID; + if (!PyTuple_GetInteger(poArgs, 0, &iVirtualID)) + return Py_BuildException(); + + BYTE iType = CPythonNonPlayer::Instance().GetEventTypeByVID(iVirtualID); + + return Py_BuildValue("i", iType); +} + +PyObject * nonplayerGetLevelByVID(PyObject * poSelf, PyObject * poArgs) +{ + int iVirtualID; + if (!PyTuple_GetInteger(poArgs, 0, &iVirtualID)) + return Py_BuildException(); + + CInstanceBase * pInstance = CPythonCharacterManager::Instance().GetInstancePtr(iVirtualID); + + if (!pInstance) + return Py_BuildValue("i", -1); + + const CPythonNonPlayer::TMobTable * pMobTable = CPythonNonPlayer::Instance().GetTable(pInstance->GetVirtualNumber()); + + if (!pMobTable) + return Py_BuildValue("i", -1); + + float fAverageLevel = pMobTable->bLevel;//(float(pMobTable->abLevelRange[0]) + float(pMobTable->abLevelRange[1])) / 2.0f; + fAverageLevel = floor(fAverageLevel + 0.5f); + return Py_BuildValue("i", int(fAverageLevel)); +} + +PyObject * nonplayerGetGradeByVID(PyObject * poSelf, PyObject * poArgs) +{ + int iVirtualID; + if (!PyTuple_GetInteger(poArgs, 0, &iVirtualID)) + return Py_BuildException(); + + CInstanceBase * pInstance = CPythonCharacterManager::Instance().GetInstancePtr(iVirtualID); + + if (!pInstance) + return Py_BuildValue("i", -1); + + const CPythonNonPlayer::TMobTable * pMobTable = CPythonNonPlayer::Instance().GetTable(pInstance->GetVirtualNumber()); + + if (!pMobTable) + return Py_BuildValue("i", -1); + + return Py_BuildValue("i", pMobTable->bRank); +} + + +PyObject * nonplayerGetMonsterName(PyObject * poSelf, PyObject * poArgs) +{ + int iVNum; + if (!PyTuple_GetInteger(poArgs, 0, &iVNum)) + return Py_BuildException(); + + CPythonNonPlayer& rkNonPlayer=CPythonNonPlayer::Instance(); + return Py_BuildValue("s", rkNonPlayer.GetMonsterName(iVNum)); +} + +PyObject * nonplayerLoadNonPlayerData(PyObject * poSelf, PyObject * poArgs) +{ + char * szFileName; + if(!PyTuple_GetString(poArgs, 0, &szFileName)) + return Py_BuildException(); + + CPythonNonPlayer::Instance().LoadNonPlayerData(szFileName); + return Py_BuildNone(); +} + +void initNonPlayer() +{ + static PyMethodDef s_methods[] = + { + { "GetEventType", nonplayerGetEventType, METH_VARARGS }, + { "GetEventTypeByVID", nonplayerGetEventTypeByVID, METH_VARARGS }, + { "GetLevelByVID", nonplayerGetLevelByVID, METH_VARARGS }, + { "GetGradeByVID", nonplayerGetGradeByVID, METH_VARARGS }, + { "GetMonsterName", nonplayerGetMonsterName, METH_VARARGS }, + + { "LoadNonPlayerData", nonplayerLoadNonPlayerData, METH_VARARGS }, + + { NULL, NULL, NULL }, + }; + + PyObject * poModule = Py_InitModule("nonplayer", s_methods); + + PyModule_AddIntConstant(poModule, "ON_CLICK_EVENT_NONE", CPythonNonPlayer::ON_CLICK_EVENT_NONE); + PyModule_AddIntConstant(poModule, "ON_CLICK_EVENT_BATTLE", CPythonNonPlayer::ON_CLICK_EVENT_BATTLE); + PyModule_AddIntConstant(poModule, "ON_CLICK_EVENT_SHOP", CPythonNonPlayer::ON_CLICK_EVENT_SHOP); + PyModule_AddIntConstant(poModule, "ON_CLICK_EVENT_TALK", CPythonNonPlayer::ON_CLICK_EVENT_TALK); + PyModule_AddIntConstant(poModule, "ON_CLICK_EVENT_VEHICLE", CPythonNonPlayer::ON_CLICK_EVENT_VEHICLE); + + PyModule_AddIntConstant(poModule, "PAWN", 0); + PyModule_AddIntConstant(poModule, "S_PAWN", 1); + PyModule_AddIntConstant(poModule, "KNIGHT", 2); + PyModule_AddIntConstant(poModule, "S_KNIGHT", 3); + PyModule_AddIntConstant(poModule, "BOSS", 4); + PyModule_AddIntConstant(poModule, "KING", 5); +} \ No newline at end of file diff --git a/extension/src/port/UserInterface/StdAfx.h b/extension/src/port/UserInterface/StdAfx.h index 9abfe81a..c8c1a909 100644 --- a/extension/src/port/UserInterface/StdAfx.h +++ b/extension/src/port/UserInterface/StdAfx.h @@ -47,6 +47,7 @@ void initapp(); void initchr(); void initchrmgr(); void initPlayer(); +void initNonPlayer(); void initChat(); void initnet(); void initeffect(); diff --git a/extension/tests/port_login_flow_test.cpp b/extension/tests/port_login_flow_test.cpp index 43676d00..12e6a1c8 100644 --- a/extension/tests/port_login_flow_test.cpp +++ b/extension/tests/port_login_flow_test.cpp @@ -47,6 +47,7 @@ #include "GameLib/RaceMotionData.h" #include "GameLib/FlyingData.h" #include "GameLib/FlyingObjectManager.h" +#include "GameLib/ItemManager.h" #include "UserInterface/StdAfx.h" #include "UserInterface/PythonCharacterManager.h" #include "UserInterface/InstanceBase.h" @@ -297,6 +298,23 @@ int main(int argc, char** argv) CHECK(server->Has("state:checker")); } + // 3c. SetSelectCharacterPhase ran localeInfo.LoadLocaleData() → app.LoadLocaleData(app.GetLocalePath()): + // CItemManager read item_list.txt/item_proto/itemdesc.txt and CPythonNonPlayer read mob_proto. + { + CItemData* sword = nullptr; + CHECK(CItemManager::Instance().GetItemDataPointer(19, &sword) && sword); + if (sword) + { + std::printf("port_login_flow_test: item 19 %s type %u refine %u\n", sword->GetName(), sword->GetType(), sword->GetRefine()); + CHECK(sword->GetType() == CItemData::ITEM_TYPE_WEAPON && sword->GetRefine() == 9); + CHECK(sword->GetModelThing() != nullptr); + } + CHECK(py("import nonplayer\n" + "_mob = nonplayer.GetMonsterName(101)\n" + "assert _mob, 'mob 101 has no name'\n" + "import sys\nsys.stderr.write('port_login_flow_test: mob 101 %s\\n' % _mob)")); + } + // 4-5. Start the game on the slot: DirectEnter, the second game login and the loading phase. if (selecting) {