Files
metin2-client/tools/server/ava2-items/tests/test_items.py
T
shenleiandClaude Opus 5.5 90f213c4cc Import the AVA2 drop items the server lacks as ordinary 40250 items
tools/server/ava2-items stages the 478 items referenced by the AVA2 drop
tables that 203 does not have: server item_proto/item_names rows, a client
item_proto/item_list/itemdesc patch over the biolog tables, and the AVA2
icons, ground models (BitKnit gr2 via sdk/gr2) and their textures, packed
as ava2items ahead of biolog. Materials, quest items, chests, the guardian
weapons and shoes keep their meaning; items of AVA2-only systems (pets,
pendants, new rings, mounts, sashes, costume enchants, talisman items, new
skill books) become plain ITEM_NONE items until those systems are ported.
Names are translated in names_zh.tsv.

item_proto_patch is the full-record successor of biolog_proto_patch, with
--dump for checking conversions against the shipped table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 10:10:47 +09:00

36 lines
2.5 KiB
Python

import sys,unittest
from pathlib import Path
HERE=Path(__file__).resolve().parents[1];sys.path.insert(0,str(HERE))
import make_items as m
READER=HERE.parents[3]/'metin2-server/src/server/db/src/ProtoReader.cpp'
def row(vnum,t,st,anti='NONE',flags='NONE',wear='NONE',applies=('APPLY_NONE','0')*3,values=('0',)*6,refine=('0','0')):
return [str(vnum),'x',t,st,'1',anti,flags,wear,'NONE','10','20',refine[0],refine[1],'0','LEVEL','120','LIMIT_NONE','0',*applies,*values,'0','0','-1','']
@unittest.skipUnless(READER.is_file(),'needs ../metin2-server')
class ConvertTests(unittest.TestCase):
E=m.enums(READER) if READER.is_file() else None
def test_weapon_kept_without_unknown_flags(self):
s,c,kept=m.convert(row(320,'ITEM_WEAPON','WEAPON_SWORD','ANTI_MUDANG | ANTI_WOLFMAN','ITEM_TUNABLE','WEAR_WEAPON',
('APPLY_ATT_SPEED','18','APPLY_ATTBONUS_BOSS','5','APPLY_NONE','0'),refine=('321','81')),self.E,{320})
self.assertTrue(kept);self.assertEqual(s[5],'ANTI_MUDANG');self.assertEqual(s[7],'WEAR_WEAPON')
self.assertEqual(s[18:22],['APPLY_ATT_SPEED','18','APPLY_NONE','0'])
self.assertEqual(s[11:13],['0','0']) # the +1 item is not imported
self.assertEqual(c[1:3],[self.E['type'].index('ITEM_WEAPON'),0]);self.assertEqual(c[4],1<<self.E['anti'].index('ANTI_MUDANG'))
self.assertEqual(len(s),33);self.assertEqual(len(c),31)
def test_costume_enchant_is_locked(self):
s,c,kept=m.convert(row(54001,'ITEM_USE','USE_CHANGE_ATTRIBUTE',flags='ITEM_STACKABLE',values=('23','10','2','0','0','0')),self.E,set())
self.assertFalse(kept);self.assertEqual(s[2:4],['ITEM_NONE','0']);self.assertEqual(s[24:30],['0']*6)
self.assertEqual(c[1:3],[0,0]);self.assertEqual(c[5],1<<self.E['flag'].index('ITEM_STACKABLE'))
def test_unknown_type_and_stackable_anti(self):
s,_,kept=m.convert(row(55010,'ITEM_PET','PET_SKILL','ITEM_STACKABLE','LOG','WEAR_PENDANT'),self.E,set())
self.assertFalse(kept);self.assertEqual(s[5:8],['NONE','LOG | ITEM_STACKABLE','NONE'])
def test_quest_subtype(self):
s,c,kept=m.convert(row(30400,'ITEM_QUEST','QUEST_NONE',values=('APPLY_NONE','0','0','0','0','0')),self.E,set())
self.assertTrue(kept);self.assertEqual(s[3],'0');self.assertEqual(s[24],'0')
def test_names_cover_ranges(self):
n=m.names();self.assertEqual(len(n),478);self.assertEqual(n[54100],'武器外观强化石')
self.assertTrue(all(len(v.encode('gbk'))<=24 for v in n.values()))
if __name__=='__main__':unittest.main()