PowerBuilder: calcFunc cache keyed by node.modKey conflates same-modKey nodes — the tree heatmap can show one twin's power for the other (and which one varies per launch)
Maintainer thường phản hồi trong vòng 8 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 64/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Ít trao đổi
- Công nghệ
- lua
- Lĩnh vực
- desktop-dev
Hướng nghiên cứu
Bắt đầu trong src/ bằng cách lần theo đường dẫn cache của PowerBuilder, sau đó chạy luajit powerbuilder_conflation_repro.lua với XML build. So sánh các cột DIRECT và POWERBUILDER rồi lặp lại trên các process mới; hoàn tất khi giá trị được cache của mỗi node khớp với giá trị theo từng node khi không dùng cache và heatmap không còn thay đổi.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Check version
- I'm running the latest version of Path of Building and I've verified this by checking the changelog
Check for duplicates
- I've checked for duplicate open and closed issues by using the search function of the issue tracker
Check for support
- I've checked that the behaviour is supposed to be supported. If it isn't please open a feature request instead (Red text is a feature request).
What platform are you running Path of Building on?
Windows
What is the behaviour in-game?
N/A — the node-power heatmap is a PoB-only feature with no in-game counterpart. The correctness reference here is PoB's own cache-free computation of the same per-node value: computing
calcFunc({addNodes={node}})directly for each node (exactly what PowerBuilder caches) gives each node its true delta; the cached path shows one shared value for all same-modKey nodes. Driver output demonstrating the difference is below.
What is the behaviour in Path of Building?
Every member of a same-modKey node group displays the power delta of whichever member seeded the
cache[node.modKey]entry first. On the attached test build, a 5-node group has two members whose true delta is +0.577%-class offence and three whose true delta is zero — the heatmap shows the non-zero value for all five (over-ranking three no-op nodes). Which member seeds the cache depends onpairs()order, so the displayed values also change between app launches (8 fresh processes produced 3 distinct node-power tables).
How to reproduce the issue
- Save the attached driver into a stock checkout's
src/.luajit powerbuilder_conflation_repro.lua yourbuild.xml— scan mode finds a conflated group on any reasonably-sized build (no special build needed); the attached build code reproduces the exact output shown.- Compare the DIRECT column (per-node truth) with the POWERBUILDER column (shared cached value); rerun to see the shared value flip across processes.
PoB for PoE1 build code
eNrtfVtz20ay8PPyV6BUle_Fso25Ysafvad0s6zEshVJtpO8uAbAQEQMAgwASla29r-fngFIAhRAgpJyObverXJEoLtnpu89N7z8n6-TxLnWeRFn6asd9MzdcXQaZGGcXr3a-XD5-qnY-Z9_jl6eqXL8PtqfxYl588_RP17av51EX-sE8FzAK1V-pcuPc1rkMzybqrQc6yw9Vb9m-XEWvtq5yBKVx8WO46s0jMtXO3tJnKsdJ0hUUbxTE_1q51ylVzrfcVQR6DQ8WL4wvYjiNDQvg7HKVVDq_K3pwt6szE6zEGAilRR6x5moOL3Igi-6PM6z2fTVDt1xrmN9UwFdnh8dNToXp3Xnzm-LBNpQOzDCf7w8S9Stzi9KVToF_ANdBUapK32oJvAv0FPJDIgR-oxwKRDeeb4WbX-WF-W2uBdTrcMl-DPJXdILfJbroyjSQRlf64M8Lg_GKg2WjbE-vA5Y_MxbB306S8p4msRGEjUGetZL_83drtA-2MusVMnh2cWSLuHPEGKUEcGk2ICXlQs8tw_yU1yOAfAebRjM_QQEck_ck6s0LvU9kA_UrCjjwKhy2mqcCk5c95lAElPisXWNn2VxkaUP4Ow92j2YJQn4iyZmr1jOdaHza1XG7U72wh9kEz9O9So7KAxKEsqlx1GvQeZavY8qUzlXYTwrTnWZ66Kh_b3cOFWpOsiKpZ6htaBnOgcnVrYw3A0IFzrIwO81URh7RuF_YkBT3QR623wbR7oFideCbjWeGqGjO558hl1OB7S05XCOLobCbU34fh06B3c_DPIimyUDIcuG2-VrLOq3FiTrtdND_XUpf7SOYBMSeb0x4iRtKhRaQ7AJiRjq7-F1ZlzDZuZYd3X05mwZNIVH-TPiYkww8WRv8BzfFnGgklP1NZ7MJhCzLtUXvWyQC7lGX6_GZQqerg8ZHFP_2F7Hue5DZMhj_ZE4S8J7tQjROCv6MCWjqN_PxOkbSNz2gmAG6dft0qD7UxhjzMtuMVesyXWCFwb6JA2WhPk6uh_S3IaNRo60rgWDcg7GaxIyP9GDcZbN1E5gqbKuu76xK53WLd42sj6BnqF1eG-1DsbHwOxzVS676T5zuSQMoi5xqeTrgsECRxBvLb8NcJPfa0NMB7sR5cMw7nDOg5BGMJWei8j6INrNRSCwtuluHtJn2PMQZb2oR6nOr24vxrFOlqPszyWa4PMuHqjpAEzL_iZ6UwyIDWuwizHuENQeDevNIFUeDgt22_bpWhVNv065129SFcsqjBa31iihhoQdUEK9UoL0J7xnefarKaKSLfH28kk2yxsBY_04KvDmMDDdFJyq8vFch7OgFQ1RvzrPC8L9BMrhlbG4G7Ggp0myFepeWargy2EWXumhKLaRrTDa_buYTafgZoxWrBCQ7rqgCyVH3Mi3hgC_B61umjddG5wHN7AEXm2AbU46BreygrHaFPfW5gsrzZAh0KtNbBboKfiNCcQJO_FxmjXnPqjbH6VfQ6U5qGy0gO1ithf2LLuB7o_NvFaxHTTkVsuO93Yl1-nvt6v0h4EPauAoDSFLA3tYbQMNxehq5jKegE8tikNVKies8_KPKo9VWmJD2ym0yoPxW5D_a5UkPriDVzvNp-bXCiKad-rlczuzaP46mUyzvHT0V_OfM5WXt_PpPQtonwCdooxTO21g5hKTHedinN3shddmFJdZlhSLOUE1neo0bNG4zLV21NyTBKYTdozmhxMks6LU-RtVjF9n-UQt5zaxmWA0724rvYU2_sVcyNR3OeX437v_IsxD8LfwGPzgjGGxiwX3OPxijEp4h1zpwS8spSS7yBMM_7s143kSGo47aQYDNGmmwBIIMkF2MZKC7mKPM75LqRRiFyHIonY5MzCYUg_vEuxCI1J43i7GHIldIgVHuwT-I3cRRpTsUiw5kMEehb7ZXhDMqbuLXeF6u0h4XO4yhFy0W_fYpfDWDowRaHEXUQQ9IMRjxLQNBDgQg-euMGQIIXSXEyTpLpPEgyeSMnhCEQJiXBAMz5lgu5i5TAAkNowQSEDvGXMtTQzUCGS8u8TjvGqFmhFKvisZPMZCMGkeI8-QpDBCSoFFgE6EGQ8HYhwLz5BnCMhTwncZ1EbQIOLQcSDlMoMLJCljlgseN8-l6-4iiWBA3APuQokADZo-cfMvjA06A2QYpOLQCDVIXCIX-OpCP0yfgFEuNf1DBhwoesLwFVhBhStNvzEMkHBhhs8ECBJakkYACNux2scSmO4iQxj-3SWIm_ERSGB3K70CKvAS2A994VgyQ1DAUEG-2AzYxbugk55RTczZLoJxe8B57nKQEfwwI0DAeSxA1MBrBkqFgP2MWR2Gihn4DA8AhCDoe63n3HaPS9eyw7X9AB5ywgmIGht1gGZB27jrAeOgjhUcOsUr2UMvhREOsJMYCVE7YMAEmcA4QEMx9E6YYZmBC2T1FfSSgKIK40vMDIzKb_faFoPAZEqw6cYqBBb14oJ5j615_-Plh_O39o9_jMtyWrx4_vzm5ubZVJXjLNJfIfF7FmST51NAAsfwtPgSJ8lTQ_b5Hvxv_-qE-LfTd5-Pwo_0-OYk924K_vHpz9HHYpJ8HKuJ9-no64W8nsrzn8mbD9OI7p-fu8n5V0Z-vnl68_NhdHamfw1Pr2SKjg-mP3-69TGeRb8FN1528-lNLH9Hb_az367fTZ5evkFPb76_lDczqn7_-sP3n5MMf5Zf353sv_vlg3j30_5X_-SX6PP1gXeUnxxn-Jo__eXn33__4c3t1_zp9DD9Ghen_OLjDx797J38-jlTv6LXp-Ev9Ow3cn3ovjv8_PSM85NZ7jO2d_5Onr-h-eXrpzdfPn__9NdPPx0dnr2-PNn__mRWnMsvl08v3138cPnu9uuXnz4fvU7K8t2b8kxMf9j3P_20P1aff_3l5Je4uDrde09jOpXllM2CvfHp_vc_vk72z_f2T_ZeT_bOv7w-_vHjj3sXJ_s_XB1d7n3a21dXr-P9jyevP10d_bh_DvBXH19fA9-839Kfbz6j_DB6d7N_9pkeX3rH5z--emUF-HwuwZfVKk9RibP-Zd2mkbc1vR0nLvXEir_OWToAjWttALI-QOt9l4DE7QO0ltqgSHoBjQdtAIo-QOsuG4Col6JxYQ1A3gdoLboBSHspGrfaAOwftYkwDUDcy0cTeJaAqHfU1mc3KMpeEYL3bRCcw7183tSQlyYjzWMIqjWR-W8nBG9xqcoyy5wscsqxdi5VoZI4cy4N-DiOSrPaFQc20cjL5_jQ_HthnMMJPCzm_qJ4XpSzNNRfn03Tq53lOMD37dS5RpU1nJharknrw4l9VDw_SY_VBLwNpDBFmavkEnKk5PlZRd_kLFVHi-d1F-G9r-vX-8e23Wp4_0Dud2apFAg5ZebsXWdx6PgaSgDnAjqZ6rDiwvM5G_5srtio-I0tq2yx0fEbW1bZYrORb2xZZYuwOdE3rqzYkCl5vrFllS029f_PYMvNOFPOG5370LSZmRrCkwhKgS93gzOm6I_wt6aH_Tyh3zlxGuRaFTp0XpuOOVXbzuEst1Maf7muEJMf_p_QleVPm9pB2jfVgZ1QMm2bP95lZfXOPJz_eGmZUThFlpfHelLs3x6eXbw2KyQrW0zqWSIDfaHLap6rifNqp8xn2kxsRWqWmOc_zmCYZtLKbT59W22ZS82M0nyxGUiNsxszjV1RvLydmlmfvbdvqzdv9ZUKbk1T89mrapaq7owTh_OZq_qhUySZ2Xilk4kuq91we8v-286D5iUzEHNaT51Cl-LkDuiBSoLCwuvULJmG9TBrTYQu1S-OkwzMEM-5UG8MxO5O6z2av7-upv2Mkp3pMo-jWIf7SWbme2253fXitzk_DdWrKs0_1aUKVamen0DeXzw3LKrUG_5axW-PwAmyWVrJMQW9rab_FihOhfN84Djp5mHW0j1KEzMLb9bbFwO9-2o5VLR-qAuV2QvD2HgMlfx0Nmioy9aGDhKjzaM8zpVZflkMrf79W8MUBkiuxhowigryMUdwqgA4S3TaGkfr6ZajqRbtjHcyU-d7M7PddcDQmk0uSllD8q6dnxvfiP5CO4dqeyNjIcBN9KEqxg22Np5tydQG5gBeWmjHgm9g5X6WlcXfnJO11Z9muZ4nCne9SfvtYN-5cCgn88xkSWSI0kKri-xluF0OCBNmi_dkdazNh9uGhybugJE1wNcMq15q6h9XDdAY2EelkjdmNakxrsazLe2igTlgUAbaqcAfU1YnkwkokTK2kDRG1X68lBcZNLI29mJwNUO7RjfHcCzKRsMPb535Fo475o-3NH98T_PfIpGYTM2Cc0caMX8xVHM6cgibpA5LI-rWHlN96h59hLz_VKXxdJb0-Li7ENv7ubs0htiNKUlaWM8f0b8bq6y3_O_leXaz4hjar7Z1e3cpDPUTNZZToT1mzlVLwxJ-l12ru5JuvNpexA3kIY7eQDsW_I9Q6jiIs1mx3GNWdKh1B8z2o57vGVuSqbdm1UeQhoi96ojT7MkfwJOLmzgq96IoiYNuO78DsD03ztU0Dg91oG4Hjdy26DSa3BA9Pmk1zdK_NAffwtCOogg0w2zfvhM8Fm-2Z_ESd0jcmAM_ph-5zL7GwTlwtTGwxrNtM44G6oARWWjHgn8Lht-ynW1t8r8nMAznyWlsDs7u5cG4S_Ttt9vzoY0_pLi1CE6NsSEiwOCudfE3n3tdeLi9pPy5y2lWz7esQe_rN80ihjmqqvM4vXpUfar2zjYnnuoH28461WhDppwq0D8gFNSnai_KPP6i75rFyuvt7WKFwICx1hhOjfIHjNkc6Imy_EqHNj3v8I13IbaOCHdJDJqmnSM5NdZ9J2utD-hxDYnyDcf6fISFWelskc3yQL_aMUN9QV-cqTTUkyyNZxPncpanu86HtNClY7qzxqVUrde1a4-4FqI41MVUxSvBuJuHlu6Si3PMXt7dh1vvU-cHg3uapWaztnP0dZpk1Wmj7dlokUN9b1bZtwtOHaV6cjsnWT02-9kt4tbMW2dwf3WnGqKs_7zQpV2WrRZezZ-W-xbiJJ3OSkvk1c4kLoLP_iyKTqvulLm9lOTo9eujg8uTj0f1cYQmiu3y53Q28U1Er_5rsswK8kLbUs4pZn5R_WkSGX1jO3IIniFOCjOaJFHTojG1aFZX654ngLeGmoV6Ey9u-eimtQTop3T0VecljPeTyoM81r39Wrzf0Kmqwaxeg-qjZu7P6CdUZYkHqiirM4M9nLI3lvRTMdeH9A7HvFyDezKZqqS35frtBk6UZm0dNDSG-tOcfFkvcrMSX0Gt4cviMHSvvOtjaf007LUifQSql_3I1dUefdj12zVctdeS9HK1etuPXk-q9GiUfdmPvDiGmqXApj4qC6g1lN5lqVVyMJq9ODFHyHolewQVzxykn-B7k4jW53v6KJ2Cj5qDrDWcPPZnZb8ZNyDW8MoepO_hkHnXj1odCe8Zg3m3xhO1zkP3MLQJ00-qOkTc68jWoVbHCXv5V59NXCOCemGnh_3V2zVMmJ9S7hl__XqNkVj_a7cyVQdUe8xlBWydw8iCLw8nY0_dPpzM6jHch1O02-F65V2_7Uf_UMYmXemgUuUsg4gYo3oYBWNbD6NwCSluOcv1vQmcr2YiS9zz9TnI4tRoJ_L87TrPUR8mvTeFebl9T_SzambwntjW_x_qyGzAWRsAFjBrBgIFpkk46knVB9EyeyCXezIeRMoOsdspLTm1Fa0qrHZybWuKlbOoL6dZ508qkA2EIC94sybzHEZpcUz9jVaJuVMtSx5G8M4lPA8hZm7dmE2hzp-Te9-V7y_lMJB7WVkATXss-9Bc7vFQHpoqs4NQf79ePp9XiPbAtqnZ6tPkF2VuJkV-z7LJz7Y0NX_VO2xJvasWsvfDGOSWW32bt2MAf5qf5n9pp4PqLb7m78UO334Cs0JX94BVS38Wo7E311Bp7ss9V1Da3L5wzvfOj0YHKs8NW37Qejp6a_4600k5qtOIFw6TbP5jXxXzq9DiRL9w3GdCemz0IY1_m2nn5PCFIwSKfKZQpMLIxUGIheuGCAscKh5y5KNIY8mJqwlWyKPCpR7lirHIwzLAAR_ZrlqmATE2qrctv3CwO6qPzkG3n-4_PX66P7Jg5_q3F46HR1BwJXEQm_d4hN3mbnYT-Bx7FYyuPJVjasYRxt85ubm9ZA5iLjwz075VbVmM_hWZWz0h3oX_foJocxv4PLtwbK7hVDoyQqzZas0z0xaY--gJItKgTiojc0w8Hz2h3nfmobnTw6nyRtMEPOf2ubmKo_n8X0GuotL2x7y2DDA9rlhjZv2yI8dMJC4hUYsV5rZBg1D5DjsncpqF9pJTJzf_moud2E6tLPWsSS8E3ghBNkLQjRBsIwTfCOFthBAbIea3tdn52rZd4bZdfXh38uOHo9GlOQNhzgAYjhvXN_oIJGdQXDj7xsQadhMxggPPZW6kCQop8zyOUYSoEEIhgpFLGZeIKe2qgHmR5FFIhZRgbB43GKOLsZrq3DE9atuQ1zQT0TQTNHpCELWnGmzJ4YBjXdVa5LbUxyitM79PyYnybFIdFSlWAWuT6wCs_mPuv0jM1nZo_TabOWN1rR3ctp9KRW2TNdKVWZfBTp0uOdoSJ_UB_GJkG22Cohr0DmSdkbeASS_d_zYr6dJw0qnhpyrJUn37_yDoFP-_cE61cZFxMRm9z1Nwsc6PM4hheVPRA9fV0tOBcgX1kIQowBTWXkBCj0URCXlAfU8yqTiKWOS6foRIpHytXE-wKJQt5fbQMkA04sM-xIdmdKCsrfZvVAGqUYHbH7j-UYwu8_jqCuxILV3qfnbjVNP-N2OdWm2tAoRzE5djgASA3fnfqFYa8NzgurObdCRb7rdCtNOSoydM3AkIrBll9pPYWCSkKLHxIakDqVTV0DxC_WdpZpfe0Y6MZXX1aLRcPGqqmlYo8MBRytDFPlI-kj6LKOaS-jgQkYyEDpHU0o2iEPse4aCUkIVoKRW8BgG1_Chp6FdDt7hYo1uNBOJglhd6IUsrxHqZqRYsOGNuhH6SlpBSxFfa5gEm7YCHVYLhGG9qA4mzvPMacgXWVKNq-sup5r-AQOXhW0q2yA3eZelTMxuc6nrJtDp-Zp3xU8_g2QtMl9nRN1doyd9VyfNZqp3jTIWjjzoxsdQe3Vgm0RSvSaKZh2lTcb2Iu1JicJQhlgIkGGFPEOqCt2Q-QowhRSQmOoKUAHEsKQoxJA1SgsbD_8PeJPpODn3e0GRBV3Jocvfg41Fi70MDlZjPWY9a50b3qgqr8m_bps9yXfYsvcHJM0GDOs6bzZl5DJv_2KnMRebSSKNFK72pL4abj3QB1WraphXv0yJRs6tx6URZ7tB5UmGs3qwHf0vB75GCr-OY22-4vDOH-XGmdTo_svw6A70sR4f2IrdbsCFlZpKWdow5ctcYMvJ405BDL0AUEh3scsY9HFHEuYxo6IUqirjQvsJYuiSgSka-K6kHZg_5PoIUyBdM8NUI1FMNH8__37BmJtvW3Fcw2mKRLwtha0x1uCnNpAeUyWKdYXruXcPsKWqJ6CxqnyBpny9uhGy-NDXBokhvWx3qt0jH1ELcdVd6u-vMpqYlj303ekqxM9982BpwVa2Y6TnHv3X20niikmJ0kOX5bFpWx72_GeyfY7BeR6Q9zNUVCPRdlhV6tHdlqoy9ySzRrXKaUMjouKegVNYMAqT0w0gQpVlAEfapUhIpqK5JyGhEAoa5AijCfeFrwFR3pqEa-R5r29XC9e8lEDmgN4XzTkHQA6U6B4UMIdsbPcE20b8oc51emTIB4kwrzWtGSsw3Znxm4qrfIE3cNlZmLj5tm1nLAygIvFVZY11Ax9uKQgNmZfbpNE7rjLNeWpkX0N9M5I6JdGm36AxHn2IoG8cqTkYH-SzUprpsarb0CYZaJvRU4AaUoNBXUaC0iJCLmO-FyPNUJHwX6mgkQe0ZR8SNAt_3WYiZ8Ibkhvs2mti40lR2d4RFy-f6WTordDV9Aj-t3zz6bRZPp_CrLv2385tdbJIdTuBoMr2FTqTOca6K6Whvoktw5XdLQCIkIySIAu16BGlP8ohjIkPwDdoTCAo_FqjQF24QEoW00pEbQKAmOCRIMEXW-AG6MpXWb3ZscwmHsE1vV02ZomZsNVXYqD2dWzHFGGy1aBCZb_KMnlRx1tjwMu9ddqn4VgA-rACEkNURl2bFF0h5gEWfbkHGaQF5BZSEapaWiZlZquZYIWQQWv99N380N542ck2A7E01LWhD06kQ2kM4MlfYkUi4WhEUMI_70nVBxwXnKvBAvSNKiMs9NwwB0MWh0NSnjEdD_MLdLHO1ZnzCNpd5T4wKLyxlnVk0wyJjzRA6apdj7Wk1hPmdlLS9NNNjNoR2m_CyvMNr1lKWUPwOVD30b3HxcZZbUNc65qGZErTnYUYHcalCSGRWYqeL_YAg8PBICcwCHHiMY0QVplqa8ssstXhYgcH4RAdIcZ_5kfBCA8HdoB07ubvORlarMdEOpE8QsTFBfy21GcJoLwwLxz7jzRKs8ZzhRoFUv4Xol0KZAsTsKokpeuyCtp1P_PsoW6cIcYcIX5ts_jwLR_t5psKxVvUxho51BCiYwwgCOjgyLITn-zoMBTg1CPSCIvtRFT9CPvN8DbE9iqTwIy8yiwiaIAp50BtwzD0LZg259iX-aN28Pt4Y8Zuz-HXQBTQ6zC92IiN8d563cSDOOYtN-IDSw1GLo4bOpf1K5oi0nGPdsm1ksfZR9DrB5si_JQf21u-WYp_uHZ8cjPaSYKwnEFDmS2Wg0cGXIk6MfKvb9uoZqIOx1qUat2K7R7FwQy-izOeQnzIauGHAIKyjUCpGCai20h5k5yJ0IcENMUGRj7WLsSJEsZZ-I9dtzSP1L2UsJP7BCNoufs1XSEH4wdiJZkkywt5ygmZxU2B7JVdXARLRNRM2UEIaxzZkX8IjKkGnAGmXAA-V7yc6n4tvPy4mMzCQlujMsUG_HXK0KzmWAoco4sxjWigoRYiWimjsQW4G_klFobnJH1HEUQQg0qNB5NMwZEiidfth-ouRgZITQyVnttM03EZnUfF3kiDrkuCFnZYxc55H4PjNOJZbC-yunyTR13HFhaYEwY5CV2Np1l58F0HxiMznIl3fbF_ypQexRzKoJaG6JmGEEESdQPpcYu4TEbm9c7ikP7q4I97ObyfmVNN8VQIcLSFL0S12WZjBzVOCk8lklpoc1y4jg4EZ0ZgFCLlYgIgjs23MqAcEiAVQF4FFDV9dRLiWjrLiN5MDt6t4f_eMhA9y3JfZVP3etnt71kc1lYYrn0A-GSAZMJdFmCLQFzcSDDPGzMcbo1D7rqaSRQFUbQz74AAUcwmEccyobisN7zN7715mT4eaPXf75xm3Mfc_eIsA8gYJ7qIj2P6gvsDb1torwpiGCAzZ1SiS3KOShCrwIZRijqMA8kcaKgUVNMOuDAJMQiigI18oyjkU1G3J4cd12GSo5FjDtde3-MKI7R4Eu_JoNrH8jfx190zoqbYfeF8szUEaC6WdOSxaOt_rG5005QapkBuFklEaeNw1nxnCxBNaC4YYlxKbpEgJTVykmcRCeiFTNHIpwp7HI33H4lre-KmHNsyoPaULgMVGjE7A7tipoOILlJ03Bb95azYQjKHY00XpnK4hB4IvSqiS_jTP2im9rgnaH3K7lGa2gZlegyxDs1vnoPqK1V3xEeFzgZiSlEvfLIuCrYF_VCELkZBBKAQiEptqjkgpJAPTM7skuQ60j30t2tvCSLP0bpkaaSzYmNKaOvWlz3fLHAcAQB6t904Msqp6v9jj06BnNhJMjA60iTpXJqaC1W--YnsNEZUU2ZzSE7JBH4fSoZ0rtb1j389h6FUCcJaVOg1u-2EvpvEXbTbCpUEWzO8P_68vD7Hb6es-pGm9aniSmq0H4JE_xnkcxlCw3zEWDJWf9nQIih9GBEKTCJEkvqTg_BSYSkADziMlvNAjmHBfUeyGkG5ECErCwGOrRUX12fkXlbq0Pd98VbNHl2KTDhjkSqGcNCvHjSTSYMwXicCLf4Ckexi5R1KVTgF0zR2-95P42u5cSupVq-4oI6kP_sYjkBBo7SkhCFTaHHgaEGImo0TgSawlVUGolfniGAuF6zJOvcgPINq0OY_avG6tAn_Xns3p2BnxxJu7gOWB3ZV57jsThog0Xzdnmv7myTnu32FvB2nU61QrM9bRWQ7FuTKXQ96Rny8JdSmk5WAxPAx9HnmeyyGySPOpX-T5kOtRTxjRcWG2iGqwIg0ZhMd9FHK3z3LemlytLc1eS1n633ZA2FoanXwiXaul6goqsw2qTSPQW5drTSNElYt91xUk8IkrhatCKZBgXoACKSUEZKhtuRtxKF9AswOfK5es1rnt-W7Rpaut4Z_G6WLWu_WivbVogGH8HbfqdMqqa2_zR_BD4VxWm7KmwHxdEeqRyIWSBFEWaAHaS5XHIqmw0KFGmgvKpAS_7yMkIwaOi6kwdCUhKxtFPXdw1sT-zKypveK9nNNuLJH8mSnT4hyZdtxnUBaA41ksvlRn8PpTonM91YCYr0maxnmsvxiF3s-S8tvRk7j6_mGX719828X5GJuJiTUJk1kiEp7AVEWCax6I0A-ZjjiLPAoVhGLg7LRQkCcRz8UK4jsSmoeSGC8YEbXq9tu-jbWX8mCI5qsdeVEv5qxbDK80y5yFum1D9-1adlTpMPe7uiaOc-ej-R7yH5ku8a4DGIm6AtZ-hOEAo23w63dSkjJfhcB5V_rMFyERykOBMgdAhUYKinZgOzdBl0lBFOGSSwJezXiswBVqNbA0ZlHcdU5K9Dop3GV9VRHedFLFVl4K98byezkWtp1n-ZAW4Fq-mKuwnOM4gr6vAb1R1_ZWQ1C6o-s46Qf9FAdf7PP_wn3qncbQtSEV6lz45Xyf3fbmVoFZEOChEsyc6xA0FFGouNmA5oc-iTCkW5BmEdcPGEJMQMTWoQ9hPBTgjMA7bZ9btcoAc0tWvcxWTdKPs2pmTc2PCf2XJFyiS3zZLHEOcrN8vSnd8j1wWCFyEfW0iiCzgtLOrAe5RDGOIygKaQgFIsacBfB_yRUkyiEKfGb2Xvmo35P9jSapHivdop17_R8rWfuWYj2uY1szh3sEQb6y8r7CkQsNDi1yBQ4x9TkOtSKe7wsmPagQI1cyxVyqGHYFWAILAACHAcaeihgJ1jo32RtV2YNcFpYbF0j-z7g10rUd9W2myrFzUWap3pSgBYKFUD8Gds5KE4G5yYwpJxgilsc4VJcylIqqMJBCMOxxhjSLAhFgn60K0JP_sQla7ZRWXdq3nOyvcl3ma5P9N9-0P0RpFeYk_HD-dvWD89VtrZVeNb5Bf-YD7PLm2IskK1vPa7zltzbmH3sXm1DsncuND9i7mxDMZSHOnn9bFGqu-g7eAn_ex1UabHsa-BFoIOfiRk1XCfFHGBB_hAF10ujQHkKkkG3tqR91aU-X-glK-Ir6VY-2UD97zHx1CNvoVvVV1lUK6IHaeS9BdGkFewStQI-gFegR-kG3ZOoSHD_Ish7DVQyjUd1ZNr-UrKJYrXM35IjIvZQaP1AlyQNH0JAe4ps6UH1v4yFK1G2X_IGDaPQAsXXOiSNBaNs51Y-2cE7dXNjGpKuTvUsE7776Sx7BB5CBkQEjKVZ4Vz96MO_oA-XfMCK0kZfHJrfeSmltZtNoQ27l-5d4ZBh3GoNx7-VT2FCJYo-KFYlWjwZJtF8eDZVC9H4uAT_YqTw8XdgqsnUJgg4UBHc9wlbcUvXoHil7Z7DcKi9ffqX18V39oyXWaGhCS6kgKwlt9WirfLSXJXiojClb7Uf96KF5Md9WTZfw7H7-epsWuykMDTpcopVatnqyBc_m3wKat0fvGyjpY6kuexxjfLgUHpp8DvVvBHt81QarR9vofkcH0ONwkjxWXbe9f2xEyge1jB8aq-5TTjY6j7dg_xKND0vW8OOImT4OmXuHsAa70Po5GI-tmkv1aOAcDEH8TsyrHj3Q3thjGcpjFC74sTrzaNM6jxYhhjpWJplYSRzrR3cEXU0yVx8GM3e8q1Bf2PvdP2mzklRUl8DbiyPs98KyNIqv6hy_-lFf2G7xF0-cMi4TbT5CFKmZndxpTE83vxvmqzQ0Xx-af2NsL4nz-de_W4D7OUAW9gD2WIeXmT36v_zSGOrCmRW6-o7F4nsafpYlWqV1ddKBYibX7clPS_9gHCeJ-TrURrzJ4sD6O2Cff3uucv0-r9ad6ntQN3S23fL8hOI2Xd7X2nzK6Vybm1OS2wGoU5WWY52lp-rXLD_OwqUcLrJE5XHRhXQYF2aV5-jNmfku1Pu0_h7O8H6aY1_2YKEtC7forvkk3eKkW3Gs03i2lUzNN862aG5VpsPkuOBpnK7w9Py2SFQ5VpulX335q0_vzhIVaLOrRec1tjZI1effFp3zXHcDgl0WrL_ftEAjm7AWK8zzT-3NMTGmaFOL-eKDbAs01o9zMQbNurCXP3cwva8NeHKPrplTQfdAqz9gPccQtB9-qU7Vl3Z1aId2YE47X-gkagyRDRjjquDYYMGdma-dLOQ9FGvr9hZf7loMy0WUDOGPtYE35vjMDTQMXmKiB8l_osFrHtZL1duwM19-OHKwHRgZbMVJa26rzQjJ-9Gmi_1IdwdF3QEKvY3Mluxvc76yv3M9gVIx3L_dS5LbQcK4CDL7mZjtrLfiz3mWJHZtvOnONmDOi4g5AkdmfbIXp4iv4uR9ZD9UBZ280sM6GVQZzhTEkqvkMr7SuTXgQf5sIZet9GZ-b2u_d3r5fJF4Vd_ssb_-OXr5_AzizfvIfkAI5PnP0f8CEQtACA==
Screenshots
Summary
CalcsTab:PowerBuilder() caches per-node power results by node.modKey.
Nodes with identical modKeys share one cache entry, so every member of a
same-modKey group displays the delta of whichever member pairs()
visited first — a per-launch coin, same pairs()-order family as
#10027 (separate issues per your preference in #9947).
For most twins this is harmless: nodes with identical mods usually have
identical toggle-deltas, so the shared value is right for both. It goes
wrong exactly when same-modKey nodes have different true deltas —
position/structure-dependent cases, e.g. a cluster-jewel notable vs a
tree node with the same stats (different dependency cascades on
dealloc), or nodes under distance-scaling jewels (Split Personality
class). Then the heatmap silently shows a wrong delta for one twin, and
WHICH twin is wrong changes between launches.
Versions
Found on v2.65.0; still present in v2.66.2 (current release): the
modKey-keyed cache and its shared lookups are unchanged
(Classes/CalcsTab.lua:606-618 — cache[node.modKey] /
cache[node.modKey.."_remove"]).
Evidence (reproduced on an unmodified v2.66.2 source archive)
The driver below is self-contained: run it on ANY build with no extra
arguments and it scans same-modKey groups of unallocated nodes, computes
each member's TRUE delta directly (cache-free, mirroring PowerBuilder's
default-mode computation exactly — CalcsTab.lua:477/530/547), and
stops at the first group whose members disagree:
luajit powerbuilder_conflation_repro.lua yourbuild.xml
Verbatim from a cluster-heavy CI/ES test build (2,589 power-carrying
nodes) on the v2.66.2 archive:
node same-key? DIRECT offence POWERBUILDER offence modKey (first 40)
4219 true 0.0057731675377536949 0.0057731675377536949 [10 = Evasion|INC|-|-|-][5 = EnergyShiel
46136 true 0 0.0057731675377536949 [10 = Evasion|INC|-|-|-][5 = EnergyShiel
58649 true 0 0.0057731675377536949 [10 = Evasion|INC|-|-|-][5 = EnergyShiel
62795 true 0.0057731675377536949 0.0057731675377536949 [10 = Evasion|INC|-|-|-][5 = EnergyShiel
64501 true 0 0.0057731675377536949 [10 = Evasion|INC|-|-|-][5 = EnergyShiel
Five nodes share one modKey; two genuinely carry +0.577%-class offence
power, three genuinely carry zero — the heatmap shows the non-zero
value for all five, i.e. it actively over-ranks three no-op nodes.
Cross-launch nondeterminism, same build: over 8 fresh processes the
full node-power table took three distinct values — at least three
conflated groups, each flipping between its members' true deltas
(0.00577… ↔ 0) depending on which member seeds the cache in that
process. First caught as a 2-node byte-flicker in k=3 fresh-process
comparison testing on v2.65.0.
- For scale: a typical build carries ~450 same-modKey groups among
power-carrying nodes, and virtually all are benign (equal deltas) —
which is also why the bug is so hard to notice by eye. - Same testing caveat as #10027: determinism is conditional
on identical execution history; identical-history A/B runs pass on
both sides. Only cross-process comparison (or the direct-vs-cached
check the driver does in one run) exposes it.
Fix directions (mindful of your #9947 hash-weight constraint)
Per-node cache keys are the obvious fix and exactly the shape you
reported abandoning in #9947 for hash-weight reasons — the cache is why
PowerBuilder is tolerable at all, so a heavier key on the hot path is
unattractive. Two scoped alternatives with zero cost on the common path:
- Hazard-scoped keying: key by
(modKey, nodeId)ONLY for nodes
whose delta can be position-dependent (node inside any radius
jewel's influence, or cluster-jewel nodes when the group spans
cluster+tree). Everything else keeps the light modKey key. - Hazard-scoped bypass: skip the cache (compute directly) for that
same node set; the set is small in practice.
Either restores per-node truth exactly where conflation can be wrong,
and leaves the fast path untouched.
powerbuilder_conflation_repro.lua (self-contained driver — save into src/ and run)
-- powerbuilder_conflation_repro.lua
-- Repro for: PowerBuilder's calcFunc cache is keyed by node.modKey, so
-- same-modKey nodes share one cached power value even when their TRUE
-- per-node deltas differ; which member seeds the cache depends on pairs()
-- order (per-process). PoB v2.65.0 / v2.66.2.
-- Run from a stock PathOfBuilding checkout's src/ directory:
-- luajit powerbuilder_conflation_repro.lua build.xml nodeId [nodeId...]
-- For each node id: DIRECT = calcFunc({addNodes={node}}) computed for THAT
-- node alone (no cache); POWERBUILDER = node.power.offence after a normal
-- PowerBuilder pass. Same-modKey nodes print ONE shared POWERBUILDER value
-- while their DIRECT values differ -- and rerunning flips which member's
-- DIRECT value the shared one equals.
-- Usage A (scan -- works on any build with no extra info):
-- luajit powerbuilder_conflation_repro.lua build.xml
-- scans same-modKey groups of unallocated nodes and stops at the first
-- whose members have DIFFERENT direct deltas (a conflated group).
-- Usage B (explicit): pass the node ids of a known group.
local pathBuild = assert(arg[1], "arg1: build.xml")
local nodeIds = {}
for i = 2, #arg do
nodeIds[#nodeIds + 1] = assert(tonumber(arg[i]), "nodeId: " .. tostring(arg[i]))
end
for i = #arg, 1, -1 do arg[i] = nil end
package.path = package.path .. ";../runtime/lua/?.lua;../runtime/lua/?/init.lua"
package.cpath = package.cpath .. ";../runtime/?.dll"
dofile("HeadlessWrapper.lua")
local f = assert(io.open(pathBuild, "r"), "cannot open " .. tostring(pathBuild))
local xml = f:read("*a")
f:close()
loadBuildFromXML(xml, "pb-conflation-repro")
wipeGlobalCache()
build.calcsTab:BuildOutput()
-- DIRECT per-node deltas (the cache-free ground truth), mirroring
-- PowerBuilder's default-mode computation EXACTLY (CalcsTab.lua:477,530,547):
-- useFullDPS = false when powerStat is nil; offence =
-- CalculateCombinedOffDefStat(node-added output, calcBase)
local calcFunc, calcBase = build.calcsTab:GetMiscCalculator(build)
local useFullDPS = false
local function directOffence(node)
local out = calcFunc({ addNodes = { [node] = true } }, useFullDPS)
return build.calcsTab:CalculateCombinedOffDefStat(out, calcBase)
end
if #nodeIds == 0 then
-- scan mode: group unallocated power-eligible nodes by modKey, find the
-- first group whose members' DIRECT deltas differ
local groups = {}
local order = {}
for id, node in pairs(build.spec.nodes) do
if not node.alloc and node.modKey and node.modKey ~= "" and type(id) == "number"
and not node.isProxy and not node.ascendancyName then
if not groups[node.modKey] then
groups[node.modKey] = {}
order[#order + 1] = node.modKey
end
table.insert(groups[node.modKey], id)
end
end
table.sort(order)
for _, key in ipairs(order) do
local ids = groups[key]
if #ids >= 2 and #ids <= 6 then
table.sort(ids)
local vals = {}
local differ = false
for _, id in ipairs(ids) do
vals[id] = string.format("%.17g", directOffence(build.spec.nodes[id]))
if vals[id] ~= vals[ids[1]] then differ = true end
end
if differ then
nodeIds = ids
print("scan: conflated group found, modKey = " .. string.sub(key, 1, 60))
break
end
end
end
assert(#nodeIds > 0, "scan found no conflated group on this build; try another build")
end
local direct = {}
for _, id in ipairs(nodeIds) do
local node = assert(build.spec.nodes[id], "unknown node id " .. id)
assert(not node.alloc, "node " .. id .. " is allocated; this driver uses the addNodes path")
direct[id] = directOffence(node)
end
-- normal PowerBuilder pass (what the heatmap shows)
build.calcsTab.powerStat = nil
build.calcsTab:PowerBuilder()
print(string.format("%-8s %-10s %-24s %-24s %s", "node", "same-key?", "DIRECT offence", "POWERBUILDER offence", "modKey (first 40)"))
for _, id in ipairs(nodeIds) do
local node = build.spec.nodes[id]
print(string.format("%-8d %-10s %-24.17g %-24.17g %s",
id, tostring(node.modKey == build.spec.nodes[nodeIds[1]].modKey),
direct[id], (node.power and node.power.offence) or -1,
string.sub(node.modKey or "", 1, 40)))
end
print("rerun: the shared POWERBUILDER value flips to a different member's DIRECT value across processes")
- Ngôn ngữ chính
- Lua
- Star
- 5.5k
- Fork
- 2.4k
- Merge trung bình
- 6 ngày 14 giờ
- Pull request đã merge (30 ngày)
- 13
Chuẩn bị môi trường
- Có Dockerfile hoặc tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của PathOfBuildingCommunity/PathOfBuilding
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
PathOfBuildingCommunity/PathOfBuilding#10431 ·
Maintainer thường phản hồi trong vòng 8 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 79/100
PathOfBuildingCommunity/PathOfBuilding#10428 ·
Maintainer thường phản hồi trong vòng 8 ngày
-
enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 60/100
PathOfBuildingCommunity/PathOfBuilding#10420 ·
Maintainer thường phản hồi trong vòng 8 ngày
-
enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
PathOfBuildingCommunity/PathOfBuilding#10395 ·
Maintainer thường phản hồi trong vòng 8 ngày
-
bug: accuracy
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
PathOfBuildingCommunity/PathOfBuilding#9911 ·
Maintainer thường phản hồi trong vòng 8 ngày
Tất cả issue của PathOfBuildingCommunity/PathOfBuilding
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 5 ngày
-
enhancement priority::low upstream
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày
-
bug reviewed-by-AI
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
olimorris/codecompanion.nvim#3508 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
The Balanced badge stays on a card after it changes to an enhancement that isn't rebalancedCó thể đã có người làm @Jr-JoshS đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 71/100
Balatro-Multiplayer/BalatroMultiplayerPvP#640 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Babies count as citizens for housing and the lost-fort check, though a baby uses no bed or seatĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Layr-Labs/arena-fortress#141 ·
Maintainer thường phản hồi trong vòng 1 ngày