11package com .github .manolo8 .darkbot .core .objects .swf ;
22
33import com .github .manolo8 .darkbot .core .api .util .DataReader ;
4+ import com .github .manolo8 .darkbot .core .itf .Updatable ;
45import com .github .manolo8 .darkbot .core .utils .ByteUtils ;
5- import com .github .manolo8 .darkbot .core .utils .Lazy ;
66
7- import java .lang .reflect .ParameterizedType ;
8- import java .lang .reflect .Type ;
7+ import java .lang .reflect .Array ;
98import java .util .Arrays ;
10- import java .util .HashMap ;
119import java .util .Map ;
12- import java .util .function .Consumer ;
1310
1411import static com .github .manolo8 .darkbot .Main .API ;
1512
16- public abstract class FlashDictionary <K , V > extends SwfPtrCollection {
13+ // TODO unfished, dont use it
14+
15+ // tableOffset = API.readInt(address, 0x10, 0x28, 236);
16+ // isDictionary = (API.readInt(address, 0x10, 0x28, 248) & (1 << 4)) != 0; // need to read heap hashtable
17+ public class FlashMap <K , V > extends SwfPtrCollection {
1718
1819 private final AtomKind keyKind ;
1920 private final AtomKind valueKind ;
2021
21- private final Map <K , Lazy <V >> listeners = new HashMap <>();
22+ private final boolean keyUpdatable , valueUpdatable ;
23+ private final Class <K > keyClazz ;
24+ private final Class <V > valueClazz ;
2225
2326 private int size ;
24- private boolean autoUpdatable , ignoreEmpty = true ;
25-
26- private Entry [] entries = new Entry [0 ];
27+ private boolean autoUpdatable ;
2728
2829 @ SuppressWarnings ("unchecked" )
29- private FlashDictionary () {
30- Type [] types = ((ParameterizedType ) getClass ()
31- .getGenericSuperclass ()).getActualTypeArguments ();
30+ private Entry [] entries = (Entry []) Array .newInstance (Entry .class , 0 );
31+
32+ private FlashMap (Class <K > key , Class <V > value ) {
33+ this .keyClazz = key ;
34+ this .valueClazz = value ;
3235
33- keyKind = AtomKind .of ((Class <K >) types [0 ]);
34- valueKind = AtomKind .of ((Class <V >) types [1 ]);
36+ this .keyUpdatable = Updatable .class .isAssignableFrom (keyClazz );
37+ this .valueUpdatable = Updatable .class .isAssignableFrom (valueClazz );
38+
39+ this .keyKind = AtomKind .of (keyClazz );
40+ this .valueKind = AtomKind .of (valueClazz );
3541
3642 if (keyKind == null || keyKind == AtomKind .UNUSED || valueKind == null || valueKind == AtomKind .UNUSED )
3743 throw new IllegalArgumentException ("Provided types are not supported" );
3844 }
3945
40- public static <K , V > FlashDictionary <K , V > ofDictionary ( ) {
41- return new FlashDictionary <K , V >() {} ;
46+ public static <K , V > FlashMap <K , V > of ( Class < K > key , Class < V > value ) {
47+ return new FlashMap <K , V >(key , value ) ;
4248 }
4349
44- public FlashDictionary <K , V > setAutoUpdatable (boolean updatable ) {
50+ public FlashMap <K , V > setAutoUpdatable (boolean updatable ) {
4551 this .autoUpdatable = updatable ;
4652 return this ;
4753 }
4854
49- public FlashDictionary <K , V > setIgnoreEmpty (boolean ignoreEmpty ) {
50- this .ignoreEmpty = ignoreEmpty ;
51- return this ;
52- }
53-
54- public void addListener (K key , Consumer <V > consumer ) {
55- addListener (key , consumer , true );
56- }
57-
58- public void addListener (K key , Consumer <V > consumer , boolean cacheValue ) {
59- this .listeners .computeIfAbsent (key , k -> (cacheValue ? new Lazy <>() : new Lazy .NoCache <>())).add (consumer );
60- }
61-
62- @ SuppressWarnings ("unchecked" )
6355 @ Override
6456 public void update () {
65- if (address == 0 || (ignoreEmpty && listeners .isEmpty ())) return ;
57+ if (address == 0 ) return ;
58+
59+ // heap hashtable
60+ boolean isDictionary = (API .readInt (address , 0x10 , 0x28 , 248 ) & (1 << 4 )) != 0 ;
61+ int tableOffset = API .readInt (address , 0x10 , 0x28 , 236 );
62+
63+ long table = address + tableOffset ;
64+ if (isDictionary ) table = API .readLong (table ) + 8 ;
6665
67- long hashTable = API .readLong (address + 32 ); //todo get table offset from script object traits
68- if (hashTable == 0 ) return ;
66+ if (table == 0 ) return ;
6967
70- long atoms = API .readLong (hashTable + 8 );
71- long sizeAndExp = API .readLong (hashTable + 16 );
68+ long atoms = API .readLong (table );
69+ long sizeAndExp = API .readLong (table + 8 );
7270
7371 //boolean hasIterIndex = (atoms & 0x04) != 0; //unused here
7472
@@ -95,10 +93,10 @@ public void update() {
9593 AtomKind keyKind = AtomKind .of (key );
9694 if (keyKind != this .keyKind ) continue ;
9795
98- Entry < K , V > entry = entries [idx ];
99- if (entry == null ) entries [idx ] = entry = new Entry <>( listeners );
96+ Entry entry = entries [idx ];
97+ if (entry == null ) entries [idx ] = entry = new Entry ( );
10098
101- entry .set (( K ) keyKind . read ( key ), ( V ) valueKind . read ( r .getLong () ));
99+ entry .set (key , r .getLong ());
102100 idx ++;
103101 }
104102 }
@@ -123,18 +121,23 @@ public long getPtr(int i) {
123121 if (entry != null && entry .value instanceof Long )
124122 return (long ) entry .value ;
125123 }
126-
127124 return 0 ;
128125 }
129126
130- private static class Entry <K , V > {
131- private final Map <K , Lazy <V >> listeners ;
132127
128+ public class Entry implements Map .Entry <K , V > {
133129 private K key ;
134130 private V value ;
135131
136- public Entry (Map <K , Lazy <V >> listeners ) {
137- this .listeners = listeners ;
132+ private Entry () {
133+ try {
134+ if (keyUpdatable )
135+ key = keyClazz .newInstance ();
136+ if (valueUpdatable )
137+ value = valueClazz .newInstance ();
138+ } catch (InstantiationException | IllegalAccessException e ) {
139+ throw new RuntimeException (e );
140+ }
138141 }
139142
140143 public K getKey () {
@@ -145,12 +148,22 @@ public V getValue() {
145148 return value ;
146149 }
147150
148- private void set (K key , V value ) {
149- this .key = key ;
150- this .value = value ;
151+ @ Override
152+ public V setValue (V value ) {
153+ return null ;
154+ }
151155
152- Lazy <V > l = listeners .get (key );
153- if (l != null ) l .send (value );
156+ @ SuppressWarnings ("unchecked" )
157+ private void set (long keyAtom , long valueAtom ) {
158+ if (keyUpdatable ) {
159+ ((Updatable ) key ).update (keyAtom & ByteUtils .ATOM_MASK );
160+ if (autoUpdatable ) ((Updatable ) key ).update ();
161+ } else key = (K ) keyKind .read (keyAtom );
162+
163+ if (valueUpdatable ) {
164+ ((Updatable ) value ).update (valueAtom & ByteUtils .ATOM_MASK );
165+ if (autoUpdatable ) ((Updatable ) value ).update ();
166+ } else value = (V ) valueKind .read (valueAtom );
154167 }
155168
156169 @ Override
0 commit comments