Project

General

Profile

Download (20.2 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / objects / RubikObjectList.java @ e3abaab9

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.objects;
11

    
12
import java.util.ArrayList;
13
import java.util.Locale;
14

    
15
import android.content.Context;
16
import android.content.SharedPreferences;
17

    
18
import org.distorted.external.RubikFiles;
19
import org.distorted.external.RubikScores;
20
import org.distorted.main.RubikActivity;
21
import org.distorted.objectlib.main.ObjectSignatures;
22
import org.distorted.objectlib.main.ObjectType;
23

    
24
import static org.distorted.main.RubikActivity.SHOW_IAP_DEBUG;
25
import static org.distorted.objectlib.main.TwistyObject.MESH_NICE;
26
import static org.distorted.objectlib.main.ObjectType.NUM_OBJECTS;
27
import static org.distorted.main.RubikActivity.SHOW_DOWNLOADED_DEBUG;
28
import static org.distorted.screens.RubikScreenPlay.LEVELS_SHOWN;
29

    
30
///////////////////////////////////////////////////////////////////////////////////////////////////
31

    
32
public class RubikObjectList
33
{
34
  public static final int DEF_OBJECT= ObjectSignatures.CUBE_3;
35
  private static RubikObjectList mThis;
36
  private static int mNumObjects;
37
  private static int mNumExtras;
38
  private static ArrayList<RubikObject> mObjects;
39
  private static int mObject = DEF_OBJECT;
40

    
41
  public static class DownloadedObject
42
    {
43
    String shortName;
44
    boolean icon,object,extras;
45
    int numScrambles, objectMinor, extrasMinor, price;
46

    
47
    DownloadedObject(String sName, int scrambles, int pr, int oMinor, int eMinor, boolean i, boolean o, boolean e)
48
      {
49
      shortName   = sName;
50
      numScrambles= scrambles;
51
      price       = pr;
52
      objectMinor = oMinor;
53
      extrasMinor = eMinor;
54

    
55
      icon   = i;
56
      object = o;
57
      extras = e;
58
      }
59
    }
60

    
61
  private static ArrayList<DownloadedObject> mDownloadedObjects;
62

    
63
  private static String mBoughtObjects;
64

    
65
///////////////////////////////////////////////////////////////////////////////////////////////////
66

    
67
  private RubikObjectList()
68
    {
69
    mNumObjects        = 0;
70
    mNumExtras         = 0;
71
    mObjects           = new ArrayList<>();
72
    mDownloadedObjects = new ArrayList<>();
73

    
74
    createBuiltinObjects();
75
    }
76

    
77
///////////////////////////////////////////////////////////////////////////////////////////////////
78

    
79
  private void createBuiltinObjects()
80
    {
81
    for(int i=0; i<NUM_OBJECTS; i++)
82
      {
83
      ObjectType type = ObjectType.getObject(i);
84
      RubikObject obj = new RubikObject(type);
85
      mObjects.add(obj);
86
      mNumObjects++;
87

    
88
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "creating local object "+type.name() );
89

    
90
      if( obj.hasExtras() )
91
        {
92
        if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "has extras "+mNumExtras );
93

    
94
        obj.setExtrasOrdinal(mNumExtras);
95
        mNumExtras++;
96
        }
97
      else
98
        {
99
        if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "no extras");
100
        }
101
      }
102
    }
103

    
104
///////////////////////////////////////////////////////////////////////////////////////////////////
105

    
106
  private static boolean internalAddDownloadedObject(DownloadedObject object)
107
    {
108
    String name = object.shortName;
109

    
110
    for(RubikObject ro : mObjects )
111
      if( ro.getLowerName().equals(name) )
112
        {
113
        return ro.updateObject(object);
114
        }
115

    
116
    RubikObject obj = new RubikObject(object);
117
    mObjects.add(obj);
118
    mNumObjects++;
119

    
120
    if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "creating downloaded object "+obj.getUpperName() );
121

    
122
    if( obj.hasExtras() )
123
      {
124
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "has extras "+mNumExtras );
125

    
126
      obj.setExtrasOrdinal(mNumExtras);
127
      mNumExtras++;
128
      }
129
    else
130
      {
131
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "no extras");
132
      }
133

    
134
    return true;
135
    }
136

    
137
///////////////////////////////////////////////////////////////////////////////////////////////////
138

    
139
  private static void restoreFreedObjects(SharedPreferences preferences)
140
    {
141
    mBoughtObjects = preferences.getString("rol_bought", "");
142

    
143
    if( SHOW_IAP_DEBUG )
144
      {
145
      android.util.Log.e("D", "bought objects: "+mBoughtObjects);
146
      }
147

    
148
    if( mBoughtObjects.length()>0 )
149
      {
150
      if( mBoughtObjects.charAt(0)=='*' )
151
        {
152
        for(int i=0; i<mNumObjects; i++)
153
          {
154
          RubikObject o = mObjects.get(i);
155
          if( o!=null ) o.markFree();
156
          }
157
        }
158
      else
159
        {
160
        String[] objs = mBoughtObjects.split(",");
161

    
162
        for( String obj : objs )
163
          {
164
          RubikObject o = getObject(obj);
165
          if( o!=null ) o.markFree();
166
          }
167
        }
168
      }
169
    }
170

    
171
///////////////////////////////////////////////////////////////////////////////////////////////////
172
// PUBLIC API
173

    
174
  public static boolean addDownloadedObject(Context context, String shortName, int numScrambles, int price, int objectMinor,
175
                                         int extrasMinor, boolean icon, boolean object, boolean extras)
176
    {
177
    if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "New downloaded object "+shortName+" icon="+icon+" object="+object+" extras="+extras);
178

    
179
    for( DownloadedObject obj : mDownloadedObjects )
180
      {
181
      if( obj.shortName.equals(shortName) )
182
        {
183
        obj.icon  |= icon;
184
        obj.object|= object;
185
        obj.extras|= extras;
186

    
187
        if( !obj.object ) objectMinor=-1;
188
        if( !obj.extras ) extrasMinor=-1;
189

    
190
        obj.objectMinor = objectMinor;
191
        obj.extrasMinor = extrasMinor;
192

    
193
        if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "Updating downloaded object "+shortName+" icon="+obj.icon+" object="+obj.object+" extras="+obj.extras);
194

    
195
        try
196
          {
197
          RubikActivity ract = (RubikActivity)context;
198
          ract.reloadObject(shortName);
199
          }
200
        catch(Exception ex)
201
          {
202
          android.util.Log.e("D", "exception trying to reload object: "+ex.getMessage() );
203
          }
204

    
205
        return false;
206
        }
207
      }
208

    
209
    if( !object ) objectMinor=-1;
210
    if( !extras ) extrasMinor=-1;
211

    
212
    DownloadedObject obj = new DownloadedObject(shortName,numScrambles,price,objectMinor,extrasMinor,icon,object,extras);
213
    if ( internalAddDownloadedObject(obj) )
214
      {
215
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "Adding new downloaded object "+shortName+" icon="+obj.icon+" object="+obj.object+" extras="+obj.extras);
216
      mDownloadedObjects.add(obj);
217
      return true;
218
      }
219
    else
220
      {
221
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "New downloaded object "+shortName+" is already built-in, deleting");
222
      RubikFiles files = RubikFiles.getInstance();
223
      files.deleteIcon(context,shortName);
224
      files.deleteJsonObject(context,shortName);
225
      files.deleteJsonExtras(context,shortName);
226
      return false;
227
      }
228
    }
229

    
230
///////////////////////////////////////////////////////////////////////////////////////////////////
231

    
232
  public static void setMeshState(int ordinal, int state)
233
    {
234
    if( ordinal>=0 && ordinal<mNumObjects ) mObjects.get(ordinal).setMeshState(state);
235
    }
236

    
237
///////////////////////////////////////////////////////////////////////////////////////////////////
238

    
239
  public static int getMeshState(int ordinal)
240
    {
241
    return (ordinal>=0 && ordinal<mNumObjects) ? mObjects.get(ordinal).getMeshState() : MESH_NICE;
242
    }
243

    
244
///////////////////////////////////////////////////////////////////////////////////////////////////
245

    
246
  public static void saveMeshState(SharedPreferences.Editor editor)
247
    {
248
    for(int i=0; i<mNumObjects; i++)
249
      {
250
      RubikObject obj = getObject(i);
251

    
252
      if( obj!=null )
253
        {
254
        String name = obj.getUpperName();
255
        editor.putInt("rol_"+name, obj.getMeshState() );
256
        }
257
      }
258
    }
259

    
260
///////////////////////////////////////////////////////////////////////////////////////////////////
261

    
262
  public static boolean allAlreadyBought()
263
    {
264
    return mBoughtObjects.equals("*");
265
    }
266

    
267
///////////////////////////////////////////////////////////////////////////////////////////////////
268

    
269
  public static boolean thereAreLockedObjects()
270
    {
271
    for(int i=0; i<mNumObjects; i++)
272
      {
273
      RubikObject o = mObjects.get(i);
274
      if( !o.isFree() ) return true;
275
      }
276

    
277
    return false;
278
    }
279

    
280
///////////////////////////////////////////////////////////////////////////////////////////////////
281

    
282
  public static boolean objectAlreadyBought(RubikObject object)
283
    {
284
    return ( object!=null && object.isFree() );
285
    }
286

    
287
///////////////////////////////////////////////////////////////////////////////////////////////////
288
// calling PurchaseScreenPane charges the user.
289

    
290
  public static void buyAll()
291
    {
292
    mBoughtObjects = "*";
293
    if( SHOW_IAP_DEBUG ) android.util.Log.e("D", "all objects marked as bought");
294

    
295
    for(int i=0; i<mNumObjects; i++)
296
      {
297
      RubikObject o = mObjects.get(i);
298
      o.markFree();
299
      }
300
    }
301

    
302
///////////////////////////////////////////////////////////////////////////////////////////////////
303
// calling PurchaseScreenPane charges the user.
304

    
305
  public static void buyObject(RubikObject object)
306
    {
307
    if( object!=null && !object.isFree() )
308
      {
309
      String shortName = object.getUpperName();
310
      if( SHOW_IAP_DEBUG ) android.util.Log.e("D", "object "+shortName+" marked as bought");
311
      object.markFree();
312
      String add = mBoughtObjects.length()==0 ? shortName : (","+shortName);
313
      mBoughtObjects += add;
314
      }
315
    }
316

    
317
///////////////////////////////////////////////////////////////////////////////////////////////////
318

    
319
  public static void savePreferences(SharedPreferences.Editor editor)
320
    {
321
    RubikObject obj = getObject(mObject);
322
    if( obj!=null ) editor.putString("rol_objName", obj.getUpperName() );
323

    
324
    int numDownloaded = mDownloadedObjects.size();
325

    
326
    if( numDownloaded>0 )
327
      {
328
      StringBuilder downloadedObjects = new StringBuilder();
329

    
330
      for(int i=0; i<numDownloaded; i++)
331
        {
332
        if( i>0 ) downloadedObjects.append(',');
333

    
334
        DownloadedObject object = mDownloadedObjects.get(i);
335
        downloadedObjects.append(object.shortName);
336
        downloadedObjects.append(' ');
337
        downloadedObjects.append(object.numScrambles);
338
        downloadedObjects.append(' ');
339
        downloadedObjects.append(object.objectMinor);
340
        downloadedObjects.append(' ');
341
        downloadedObjects.append(object.extrasMinor);
342
        downloadedObjects.append(' ');
343
        downloadedObjects.append(object.icon   ? "1":"0");
344
        downloadedObjects.append(' ');
345
        downloadedObjects.append(object.object ? "1":"0");
346
        downloadedObjects.append(' ');
347
        downloadedObjects.append(object.extras ? "1":"0");
348
        downloadedObjects.append(' ');
349
        downloadedObjects.append(object.price);
350
        }
351

    
352
      String objects = downloadedObjects.toString();
353
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "saving: "+objects);
354
      editor.putString("rol_downloaded", objects );
355
      }
356
    else
357
      {
358
      editor.putString("rol_downloaded", "" );
359
      }
360

    
361
    if( RubikActivity.USE_IAP )
362
      {
363
      editor.putString("rol_bought", mBoughtObjects);
364

    
365
      if( SHOW_IAP_DEBUG )
366
        {
367
        android.util.Log.e("D", "saving bought objects: "+mBoughtObjects);
368
        }
369
      }
370
    }
371

    
372
///////////////////////////////////////////////////////////////////////////////////////////////////
373

    
374
  public static void savePreferencesMinimal(SharedPreferences.Editor editor)
375
    {
376
    RubikObject obj = getObject(mObject);
377
    if( obj!=null ) editor.putString("rol_objName", obj.getUpperName() );
378
    }
379

    
380
///////////////////////////////////////////////////////////////////////////////////////////////////
381

    
382
  public static void restorePreferences(Context context, SharedPreferences preferences, boolean justStarted)
383
    {
384
    if( mThis==null ) mThis = new RubikObjectList();
385

    
386
    String downloaded = preferences.getString("rol_downloaded","");
387

    
388
    if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", downloaded);
389

    
390
    if( !downloaded.equals(""))
391
      {
392
      String[] dObjects = downloaded.split(",");
393

    
394
      for(String dObj : dObjects)
395
        {
396
        String[] parts = dObj.split(" ");
397
        int length = parts.length;
398

    
399
        if( length==7 || length==8 )
400
          {
401
          String name = parts[0];
402
          String scra = parts[1];
403
          String objM = parts[2];
404
          String extM = parts[3];
405
          String icon = parts[4];
406
          String obje = parts[5];
407
          String extr = parts[6];
408

    
409
          int price;
410

    
411
          if( length==7 ) price=0;
412
          else
413
            {
414
            char c = parts[7].charAt(0);
415
            if( c=='t' )      price = 0;
416
            else if( c=='f' ) price = ObjectType.DEFAULT_PRICE_OF_OLD_OBJECTS;
417
            else              price = Integer.parseInt(parts[7]);
418
            }
419

    
420
          int scrambles = Integer.parseInt(scra);
421
          int oMinor    = Integer.parseInt(objM);
422
          int eMinor    = Integer.parseInt(extM);
423

    
424
          boolean bIcon = icon.equals("1");
425
          boolean bObje = obje.equals("1");
426
          boolean bExtr = extr.equals("1");
427

    
428
          addDownloadedObject(context,name,scrambles,price,oMinor,eMinor,bIcon,bObje,bExtr);
429
          }
430
        }
431
      }
432

    
433
    RubikObject object = getObject(DEF_OBJECT);
434
    String defName = object==null ? "CUBE_3" : object.getUpperName();
435
    String objName= preferences.getString("rol_objName",defName);
436
    mObject = getOrdinal(objName);
437
    if( mObject<0 || mObject>=mNumObjects ) mObject = DEF_OBJECT;
438

    
439
    if( RubikActivity.USE_IAP && justStarted ) restoreFreedObjects(preferences);
440
    }
441

    
442
///////////////////////////////////////////////////////////////////////////////////////////////////
443

    
444
  public static void restoreMeshState(SharedPreferences preferences)
445
    {
446
    for(int i=0; i<mNumObjects; i++)
447
      {
448
      RubikObject obj = getObject(i);
449

    
450
      if( obj!=null )
451
        {
452
        String name  = obj.getUpperName();
453
        int meshState= preferences.getInt("rol_"+name,MESH_NICE);
454
        obj.setMeshState(meshState);
455
        }
456
      }
457
    }
458

    
459
///////////////////////////////////////////////////////////////////////////////////////////////////
460

    
461
  public static void firstUpgradeMarkAllSolvedAsFree()
462
    {
463
    RubikScores scores = RubikScores.getInstance();
464
    int numUnclaimed = scores.numberOfSolvedMAXes();
465

    
466
    if( numUnclaimed>0 )
467
      {
468
      int marked = markAllSolvedAsFree(scores);
469
      int stillUnclaimed = numUnclaimed-marked;
470
      if( stillUnclaimed>0) markObjectsAsFree(scores,stillUnclaimed);
471
      }
472
    }
473

    
474
///////////////////////////////////////////////////////////////////////////////////////////////////
475

    
476
  private static int markAllSolvedAsFree(RubikScores scores)
477
    {
478
    int numObjects = RubikObjectList.getNumObjects();
479
    int ret = 0;
480

    
481
    for(int obj=0; obj<numObjects; obj++)
482
      {
483
      RubikObject object = getObject(obj);
484

    
485
      if( object!=null && !object.isFree() && scores.isSolved(obj,LEVELS_SHOWN) )
486
        {
487
        markAsFree(object,scores);
488
        ret++;
489
        }
490
      }
491

    
492
    return ret;
493
    }
494

    
495
///////////////////////////////////////////////////////////////////////////////////////////////////
496

    
497
  private static void markObjectsAsFree(RubikScores scores, int numToBeMarked)
498
    {
499
    int numObjects = RubikObjectList.getNumObjects();
500

    
501
    for(int obj=0; obj<numObjects && numToBeMarked>0; obj++)
502
      {
503
      RubikObject object = getObject(obj);
504

    
505
      if( object!=null && !object.isFree() )
506
        {
507
        markAsFree(object,scores);
508
        numToBeMarked--;
509
        }
510
      }
511
    }
512

    
513
///////////////////////////////////////////////////////////////////////////////////////////////////
514

    
515
  private static void markAsFree(RubikObject object, RubikScores scores)
516
    {
517
    String shortName = object.getUpperName();
518
    if( SHOW_IAP_DEBUG ) android.util.Log.e("D", "object "+object.getUpperName()+" marked as free");
519
    object.markFree();
520
    int price = object.getPrice();
521
    scores.changeNumStars(-price);
522
    String add = mBoughtObjects.length()==0 ? shortName : (","+shortName);
523
    mBoughtObjects += add;
524
    }
525

    
526
///////////////////////////////////////////////////////////////////////////////////////////////////
527

    
528
  public static boolean setCurrObject(int ordinal)
529
    {
530
    if( mObject!=ordinal )
531
      {
532
      mObject = ordinal;
533
      return true;
534
      }
535

    
536
    return false;
537
    }
538

    
539
///////////////////////////////////////////////////////////////////////////////////////////////////
540

    
541
  public static int getCurrObject()
542
    {
543
    return mObject;
544
    }
545

    
546
///////////////////////////////////////////////////////////////////////////////////////////////////
547

    
548
  public static String getCurrentName()
549
    {
550
    RubikObject object = mObjects.get(mObject);
551
    return object==null ? "" : object.getUpperName();
552
    }
553

    
554
///////////////////////////////////////////////////////////////////////////////////////////////////
555

    
556
  public static RubikObject getObject(int ordinal)
557
    {
558
    if( mThis==null ) mThis = new RubikObjectList();
559
    return ordinal>=0 && ordinal<mNumObjects ? mObjects.get(ordinal) : null;
560
    }
561

    
562
///////////////////////////////////////////////////////////////////////////////////////////////////
563

    
564
  public static RubikObject getObject(String shortUpperName)
565
    {
566
    if( mThis==null ) mThis = new RubikObjectList();
567

    
568
    for(int i=0; i<mNumObjects; i++)
569
      {
570
      RubikObject object = mObjects.get(i);
571
      if( object.getUpperName().equals(shortUpperName) )
572
        {
573
        return object;
574
        }
575
      }
576

    
577
    return null;
578
    }
579

    
580
///////////////////////////////////////////////////////////////////////////////////////////////////
581

    
582
  public static int getNumObjects()
583
    {
584
    if( mThis==null ) mThis = new RubikObjectList();
585
    return mNumObjects;
586
    }
587

    
588
///////////////////////////////////////////////////////////////////////////////////////////////////
589

    
590
  public static int getOrdinal(String name)
591
    {
592
    if( mThis==null ) mThis = new RubikObjectList();
593

    
594
    String lowerName = name.toLowerCase(Locale.ENGLISH);
595

    
596
    for(int i=0; i<mNumObjects; i++)
597
      {
598
      RubikObject obj = mObjects.get(i);
599
      if( obj.getLowerName().equals(lowerName) ) return i;
600
      }
601

    
602
    return -1;
603
    }
604

    
605
///////////////////////////////////////////////////////////////////////////////////////////////////
606

    
607
  public static int getNumExtrasObjects()
608
    {
609
    return mNumExtras;
610
    }
611

    
612
///////////////////////////////////////////////////////////////////////////////////////////////////
613

    
614
  public static int getNumTutorialObjects()
615
    {
616
    return mNumExtras;
617
    }
618

    
619
///////////////////////////////////////////////////////////////////////////////////////////////////
620

    
621
  public static int getObjectOrdinal(int extrasOrdinal)
622
    {
623
    for(int i=extrasOrdinal; i<mNumObjects; i++)
624
      {
625
      RubikObject object = getObject(i);
626
      int extOrd = object!=null ? object.getExtrasOrdinal() : -1;
627
      if( extOrd==extrasOrdinal ) return i;
628
      }
629

    
630
    return -1;
631
    }
632

    
633
///////////////////////////////////////////////////////////////////////////////////////////////////
634

    
635
  public static int getExtrasOrdinal(int objectOrdinal)
636
    {
637
    RubikObject object = getObject(objectOrdinal);
638
    return object!=null ? object.getExtrasOrdinal() : -1;
639
    }
640

    
641
///////////////////////////////////////////////////////////////////////////////////////////////////
642

    
643
  public static int getTutorialOrdinal(int objectOrdinal)
644
    {
645
    RubikObject object = getObject(objectOrdinal);
646
    return object!=null ? object.getExtrasOrdinal() : -1;
647
    }
648

    
649
///////////////////////////////////////////////////////////////////////////////////////////////////
650

    
651
  public static int getLocalObjectMinor(int objectOrdinal)
652
    {
653
    RubikObject object = getObject(objectOrdinal);
654
    return object!=null ? object.getObjectMinor() : -1;
655
    }
656

    
657
///////////////////////////////////////////////////////////////////////////////////////////////////
658

    
659
  public static int getLocalExtrasMinor(int objectOrdinal)
660
    {
661
    RubikObject object = getObject(objectOrdinal);
662
    return object!=null ? object.getExtrasMinor() : -1;
663
    }
664
}
(2-2/2)