Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Добавление классов в TObjectDictionary / 10 сообщений из 10, страница 1 из 1
13.07.2019, 18:10
    #39837110
Vizit0r
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление классов в TObjectDictionary
Вычитываю XML, добавляю в TObjectDictionary

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
  TAssetType = record
    padding : Byte;
    directory : String;
    FileExt : String;
  end;

  TAssetBoolType = array[Boolean] of TAssetType; //False - unpacked, True - packed;

  TAssetClass = class
  private
    fVal : TAssetBoolType;
    function Get(T: Boolean): TAssetType;
  public
    property Val[T: Boolean] : TAssetType read Get; default;
    constructor Create;
  end;


----------------


  fUOPAssets := TObjectDictionary<Byte,TAssetClass>.Create([doOwnsValues]);

  for i := 0 to XMLDoc.Root.ItemCount - 1 do
  begin
    XML_Element := XMLDoc.Root.Items[i];
...
    if not fUOPAssets.TryGetValue(Num,AssetClass) then
      AssetClass := TAssetClass.Create;

    AssetClass.fVal[IsFilePacked].padding := XML_Element.Properties.IntValue('resourcetpaddingype',0);
    AssetClass.fVal[IsFilePacked].directory := XML_Element.Properties.Value('directory','').ToLower;
    AssetClass.fVal[IsFilePacked].FileExt := XML_Element.Properties.Value('suffix','').ToLower;

    fUOPAssets.AddOrSetValue(Num, AssetClass);
  end;



Какого-то беса результат TAssetClass.Create - есть указатель на тот же адрес, что и в прошлой итерации цикла. Уже и перекрывал конструктор, без толку.
Вроде просто всё, проще некуда. А не работает, точнее работает неправильно.

Содержимое словаря в приложенной картинкой, стрелками разных цветов выделил дублирующиеся указатели на объект.
Словарь заполняется один раз, освобождается в конце работы, в процессе - только чтение.

Что я делаю не так?
...
Рейтинг: 0 / 0
13.07.2019, 18:37
    #39837111
x1ca4064
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление классов в TObjectDictionary
Vizit0rЧто я делаю не так?

Судьба Num не ясна, думаю, в нем собака и зарыта :)
...
Рейтинг: 0 / 0
13.07.2019, 19:02
    #39837114
Vizit0r
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление классов в TObjectDictionary
Код: pascal
1.
2.
3.
    Num := XML_Element.Properties.IntValue('resourcetype',$FF);
    if Num = $FF then
      Continue;



$FF для пропуска строк без 'resourcetype', ну это понятно.
...
Рейтинг: 0 / 0
13.07.2019, 19:31
    #39837119
x1ca4064
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление классов в TObjectDictionary
Vizit0r,

А как этот код расположен по отношению к остальному?

Я подозреваю, что у Вас Num меняется в процессе: .Create не вызывается, меняется Num, старый объект с новым Num добавляется.
...
Рейтинг: 0 / 0
13.07.2019, 20:28
    #39837125
Vizit0r
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление классов в TObjectDictionary
на отладке смотрел - нормально меняется на каждой итерации, в соотвествии с resourcetype в каждом элементе.

Выложу почти полный исходник:

под спойлером типы и классы.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
type
  TUOPAssets = class;

  TGetUOPAssets = function : TUOPAssets of object;

  TAssetType = record
    padding : Byte;
    directory : String;
    FileExt : String;
  end;

  TAssetBoolType = array[Boolean] of TAssetType; //False - unpacked, True - packed;

  TAssetClass = class
  private
    fVal : TAssetBoolType;
    function Get(T: Boolean): TAssetType;
  public
    property Val[T: Boolean] : TAssetType read Get; default;
    constructor Create;
  end;

  TUOPAssets = class
  private
    fUOPAssets : TObjectDictionary<Byte,TAssetClass>;
    FInited : Boolean;
  public
    constructor Create(ShardDir : String);
    property Inited : Boolean read FInited;
    property Assets : TObjectDictionary<Byte,TAssetClass> read fUOPAssets;
  end;

implementation
function TAssetClass.Get(T: Boolean): TAssetType;
begin
  Result := fVal[T];
end;

constructor TAssetClass.Create;
begin
  inherited Create;
end;



вот весь конструктор целиком, с разбором XML

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
constructor TUOPAssets.Create(ShardDir : String);
var UOPPackage : TMythicPackage;
    FileBuf : TArray<byte>;
    XMLDoc : TJclSimpleXML;
    XML_Element : TJclSimpleXMLElem;
    XMLString : String;
    IsFilePacked : Boolean;
    i  : Integer;
    AssetClass : TAssetClass;
    Asset : TAssetBoolType;
    Num : Byte;
begin
  inherited Create;
  FInited := False;
  if not FileExists(shardDir + 'MainMisc.uop') then
    Exit;
  UOPPackage := TMythicPackage.Create;
  UOPPackage.Open(shardDir + 'MainMisc.uop');
  if UOPPackage.FileCount = 0 then
  begin
    UOPPackage.DisposeOf;
    Exit;
  end;
  FileBuf := UOPPackage.UnpackByName('data/assetmap.xml');
  if Length(FileBuf) = 0 then
  begin
    UOPPackage.DisposeOf;
    Exit;
  end;
  XMLString := TEncoding.ANSI.GetString(FileBuf);
  fUOPAssets := TObjectDictionary<Byte,TAssetClass>.Create([doOwnsValues]);

  try
    XMLDoc := TJclSimpleXML.Create;
    XMLDoc.LoadFromString(XMLString);
  except
    Exit;
  end;
  if XMLDoc.Root.name <> 'assetmap' then Exit;

  for i := 0 to XMLDoc.Root.ItemCount - 1 do
  begin
    XML_Element := XMLDoc.Root.Items[i];
//    if XML_Element.Name <> 'patternmap' then Continue;
    if Assigned(XML_Element.Properties.ItemNamed['fileFormat']) then
      IsFilePacked := XML_Element.Properties.ItemNamed['fileFormat'].Value = 'packed'
    else
      IsFilePacked := True;
    Num := XML_Element.Properties.IntValue('resourcetype',$FF);
    if Num = $FF then
      Continue;
    if not fUOPAssets.TryGetValue(Num,AssetClass) then
      AssetClass := TAssetClass.Create;

    AssetClass.fVal[IsFilePacked].padding := XML_Element.Properties.IntValue('resourcetpaddingype',0);
    AssetClass.fVal[IsFilePacked].directory := XML_Element.Properties.Value('directory','').ToLower;
    AssetClass.fVal[IsFilePacked].FileExt := XML_Element.Properties.Value('suffix','').ToLower;

    fUOPAssets.AddOrSetValue(Num, AssetClass);
  end;
  FInited := True;
  XMLDoc.DisposeOf;
  UOPPackage.DisposeOf;
end;



а вот файл, который разбирается.

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
<assetmap>
   <patternmap resourcetype="1" fileFormat="raw" padding="8" directory="Data/WorldArt/" suffix="*" patternMatch="1" />
   <patternmap resourcetype="1" fileFormat="packed" padding="8" directory="Build/WorldArt/" suffix=".dds"/>
   <patternmap resourcetype="2" directory="Data/Maps/" suffix=".dat" />
   <patternmap resourcetype="3" fileFormat="raw" directory="Data/Definitions/Terrain/" suffix=".xml" />
   <patternmap resourcetype="3" fileFormat="packed" directory="Build/TerrainDefinition/" suffix=".bin" />
   <patternmap resourcetype="5" directory="Data/Statics/" suffix=".dat" />
   <patternmap resourcetype="6" fileFormat="raw" padding="8" directory="Data/Definitions/TileArt/" suffix=".tileart" />
   <patternmap resourcetype="6" fileFormat="packed" padding="8" directory="Build/TileArt/" suffix=".bin" />
   <patternmap resourcetype="8" padding="8" directory="Data/Textures/" suffix="*" patternMatch="1" />
   <patternmap resourcetype="8" fileFormat="packed" padding="8" directory="Build/TerrainTexture/" suffix=".dds"/>
   <bitmaskmap resourcetype="9" fileFormat="raw" directory="Data/Sectors/" suffix=".sector">
      <section prefix="Facet_" mask="0x3f" padding="2"/>
      <section prefix="/" mask="0xffffffc0" padding="8"/>
   </bitmaskmap>
   <bitmaskmap resourcetype="9" fileFormat="packed" directory="Build/Sectors/" suffix=".bin">
      <section prefix="Facet_" mask="0x3f" padding="2"/>
      <section prefix="/" mask="0xffffffc0" padding="8"/>
   </bitmaskmap>
   <patternmap resourcetype="10" padding="8" directory="Data/Definitions/LegacyTerrain/" suffix=".legacyterrain" />
   <patternmap resourcetype="11" fileFormat="raw" padding="8" directory="Data/Definitions/Animation/" suffix=".animation" />
   <patternmap resourcetype="11" fileFormat="packed" padding="8" directory="Build/AnimationDefinition/" suffix=".bin" />
   <patternmap resourcetype="12" fileFormat="raw" padding="8" directory="Data/Definitions/Animation/" suffix=".sequence" />
   <patternmap resourcetype="12" fileFormat="packed" padding="8" directory="Build/AnimationSequence/" suffix=".bin" />
   <patternmap resourcetype="13" fileFormat="raw" padding="8" directory="Data/Definitions/Effect/" suffix=".effects" />
   <patternmap resourcetype="13" fileFormat="packed" padding="8" directory="Build/EffectDefinitionCollection/" suffix=".bin" />
   <bitmaskmap resourcetype="14" directory="Data/Anim/" suffix=".tga">
      <section isDirectory="1" patternMatch="1" mask="0xffffc000" padding="6"/>
      <section isDirectory="1" patternMatch="1" mask="0x3f00" padding="2"/>
      <section mask="0xff" padding="4"/>
   </bitmaskmap>
   <patternmap resourcetype="15" padding="3" directory="Data/LocalizedStrings/" suffix=".cliloc" />
   <bitmaskmap resourcetype="16" fileFormat="packed" directory="Build/AnimationFrame/" suffix=".bin">
      <section isDirectory="1" mask="0xffff00" padding="6"/>
      <section mask="0xff" padding="2"/>
   </bitmaskmap>
   <bitmaskmap resourcetype="25" fileFormat="packed" directory="Build/AnimationLegacyFrame/" suffix=".bin">
      <section isDirectory="1" mask="0xffff00" padding="6"/>
      <section mask="0xff" padding="2"/>
   </bitmaskmap>
   <bitmaskmap resourcetype="18" fileFormat="packed" directory="Build/Paperdoll/" suffix=".bin">
      <section isDirectory="1" mask="0xffffc0" padding="6"/>
      <section mask="0x3f" padding="2"/>
   </bitmaskmap>
   <patternmap resourcetype="19" fileFormat="raw" padding="6" directory="Data/Definitions/Multi/" suffix=".multi" />
   <patternmap resourcetype="19" fileFormat="packed" padding="6" directory="Build/MultiCollection/" suffix=".bin" />
   <simplemap resourcetype="20" fileFormat="raw" resourcenumber="0" filename="Data/Definitions/Multi/housing.xml" />
   <simplemap resourcetype="20" fileFormat="packed" resourcenumber="0" filename="Build/MultiCollection/housing.bin" />
   <simplemap resourcetype="21" fileFormat="raw" resourcenumber="0" filename="Data/Sectors/waypoint.xml" />
   <simplemap resourcetype="21" fileFormat="packed" resourcenumber="0" filename="Build/Sectors/waypoint.bin" />
   <patternmap resourcetype="22" fileFormat="raw" directory="Data/TileArtLegacy/" suffix="*" patternMatch="1" />
   <patternmap resourcetype="22" fileFormat="packed" padding="8" directory="Build/TileArtLegacy/" suffix=".dds"/>
   <patternmap resourcetype="23" fileFormat="raw" padding="8" directory="Data/Definitions/Facet/" suffix=".xml" />
   <patternmap resourcetype="23" fileFormat="packed" padding="8" directory="Build/FacetDefinition/" suffix=".bin" />
   <patternmap resourcetype="24" fileFormat="raw" padding="8" directory="EditorData/BrushMulti/" suffix=".multi" />
   <!-- Resource type 25 is only used by legacy -->
   <patternmap resourcetype="26" fileFormat="raw" directory="Data/TileArtEnhanced/" suffix="*" patternMatch="1" />
   <patternmap resourcetype="26" fileFormat="packed" padding="8" directory="Build/TileArtEnhanced/" suffix=".dds" />
 </assetmap>

...
Рейтинг: 0 / 0
14.07.2019, 01:35
    #39837170
white_nigger
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление классов в TObjectDictionary
Vizit0rКакого-то беса результат TAssetClass.Create - есть указатель на тот же адрес, что и в прошлой итерации цикла.Так код этому и не противоречит. Как написал - так и работает.
...
Рейтинг: 0 / 0
14.07.2019, 07:21
    #39837180
Vizit0r
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление классов в TObjectDictionary
а поподробнее?
AssetClass := TAssetClass.Create;
же должно создавать НОВЫЙ экземпляр класса.
...
Рейтинг: 0 / 0
14.07.2019, 08:18
    #39837181
Vizit0r
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление классов в TObjectDictionary
докопался.

оказывается, в TDictionary.DoSetValue
происходит

ValueNotify(oldValue, cnRemoved);
ValueNotify(Value, cnAdded);


а на cnRemoved в TObjectDictionary происходит уничтожение объекта.


вот уж чего не ожидал.
...
Рейтинг: 0 / 0
14.07.2019, 09:40
    #39837189
Cobalt747
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление классов в TObjectDictionary
Vizit0rдокопался.

оказывается, в TDictionary.DoSetValue
происходит

ValueNotify(oldValue, cnRemoved);
ValueNotify(Value, cnAdded);


а на cnRemoved в TObjectDictionary происходит уничтожение объекта.


вот уж чего не ожидал.
Рекомендую обращать внимание на параметры конструктора используемых объектов.
...
Рейтинг: 0 / 0
14.07.2019, 10:31
    #39837193
Vizit0r
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление классов в TObjectDictionary
обращал, и doOwnsValues ставил вполне осознанно.
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Добавление классов в TObjectDictionary / 10 сообщений из 10, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]