Project

General

Profile

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

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

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.main.RubikActivity.USE_IAP;
26
import static org.distorted.objectlib.main.TwistyObject.MESH_NICE;
27
import static org.distorted.objectlib.main.ObjectType.NUM_OBJECTS;
28
import static org.distorted.main.RubikActivity.SHOW_DOWNLOADED_DEBUG;
29
import static org.distorted.screens.RubikScreenPlay.LEVELS_SHOWN;
30

    
31
///////////////////////////////////////////////////////////////////////////////////////////////////
32

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

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

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

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

    
62
  private static ArrayList<DownloadedObject> mDownloadedObjects;
63

    
64
  private static String mBoughtObjects;
65

    
66
///////////////////////////////////////////////////////////////////////////////////////////////////
67

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

    
75
    createBuiltinObjects();
76
    }
77

    
78
///////////////////////////////////////////////////////////////////////////////////////////////////
79

    
80
  private static boolean allObjectsUnlocked()
81
    {
82
    return mBoughtObjects!=null       &&
83
           mBoughtObjects.length()>0  &&
84
           mBoughtObjects.charAt(0)=='*';
85
    }
86

    
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88

    
89
  private void createBuiltinObjects()
90
    {
91
    for(int i=0; i<NUM_OBJECTS; i++)
92
      {
93
      ObjectType type = ObjectType.getObject(i);
94
      RubikObject obj = new RubikObject(type);
95
      mObjects.add(obj);
96
      mNumObjects++;
97

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

    
100
      if( obj.hasExtras() )
101
        {
102
        if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "has extras "+mNumExtras );
103

    
104
        obj.setExtrasOrdinal(mNumExtras);
105
        mNumExtras++;
106
        }
107
      else
108
        {
109
        if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "no extras");
110
        }
111
      }
112
    }
113

    
114
///////////////////////////////////////////////////////////////////////////////////////////////////
115

    
116
  private static boolean internalAddDownloadedObject(DownloadedObject object)
117
    {
118
    String name = object.shortName;
119

    
120
    for(RubikObject ro : mObjects )
121
      if( ro.getLowerName().equals(name) )
122
        {
123
        return ro.updateObject(object);
124
        }
125

    
126
    RubikObject obj = new RubikObject(object);
127
    mObjects.add(obj);
128
    mNumObjects++;
129

    
130
    if( USE_IAP && !obj.isFree() && allObjectsUnlocked() )
131
      {
132
      if( SHOW_IAP_DEBUG ) android.util.Log.e("D", "everything unlocked, so setting downloaded object free: "+obj.getUpperName() );
133
      obj.markFree();
134
      }
135

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

    
138
    if( obj.hasExtras() )
139
      {
140
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "has extras "+mNumExtras );
141

    
142
      obj.setExtrasOrdinal(mNumExtras);
143
      mNumExtras++;
144
      }
145
    else
146
      {
147
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "no extras");
148
      }
149

    
150
    return true;
151
    }
152

    
153
///////////////////////////////////////////////////////////////////////////////////////////////////
154

    
155
  private static void restoreFreedObjects(SharedPreferences preferences)
156
    {
157
    mBoughtObjects = preferences.getString("rol_bought", "");
158

    
159
    if( SHOW_IAP_DEBUG )
160
      {
161
      android.util.Log.e("D", "bought objects: "+mBoughtObjects);
162
      }
163

    
164
    if( mBoughtObjects.length()>0 )
165
      {
166
      if( mBoughtObjects.charAt(0)=='*' )
167
        {
168
        for(int i=0; i<mNumObjects; i++)
169
          {
170
          RubikObject o = mObjects.get(i);
171
          if( o!=null ) o.markFree();
172
          }
173
        }
174
      else
175
        {
176
        String[] objs = mBoughtObjects.split(",");
177

    
178
        for( String obj : objs )
179
          {
180
          RubikObject o = getObject(obj);
181
          if( o!=null ) o.markFree();
182
          }
183
        }
184
      }
185
    }
186

    
187
///////////////////////////////////////////////////////////////////////////////////////////////////
188
// PUBLIC API
189

    
190
  public static boolean addDownloadedObject(Context context, String shortName, int numScrambles, int price, int objectMinor,
191
                                         int extrasMinor, boolean icon, boolean object, boolean extras)
192
    {
193
    if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "New downloaded object "+shortName+" icon="+icon+" object="+object+" extras="+extras);
194

    
195
    for( DownloadedObject obj : mDownloadedObjects )
196
      {
197
      if( obj.shortName.equals(shortName) )
198
        {
199
        obj.icon  |= icon;
200
        obj.object|= object;
201
        obj.extras|= extras;
202

    
203
        if( !obj.object ) objectMinor=-1;
204
        if( !obj.extras ) extrasMinor=-1;
205

    
206
        obj.objectMinor = objectMinor;
207
        obj.extrasMinor = extrasMinor;
208

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

    
211
        try
212
          {
213
          RubikActivity ract = (RubikActivity)context;
214
          ract.reloadObject(shortName);
215
          }
216
        catch(Exception ex)
217
          {
218
          android.util.Log.e("D", "exception trying to reload object: "+ex.getMessage() );
219
          }
220

    
221
        return false;
222
        }
223
      }
224

    
225
    if( !object ) objectMinor=-1;
226
    if( !extras ) extrasMinor=-1;
227

    
228
    DownloadedObject obj = new DownloadedObject(shortName,numScrambles,price,objectMinor,extrasMinor,icon,object,extras);
229
    if ( internalAddDownloadedObject(obj) )
230
      {
231
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "Adding new downloaded object "+shortName+" icon="+obj.icon+" object="+obj.object+" extras="+obj.extras);
232
      mDownloadedObjects.add(obj);
233
      return true;
234
      }
235
    else
236
      {
237
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "New downloaded object "+shortName+" is already built-in, deleting");
238
      RubikFiles files = RubikFiles.getInstance();
239
      files.deleteIcon(context,shortName);
240
      files.deleteJsonObject(context,shortName);
241
      files.deleteJsonExtras(context,shortName);
242
      return false;
243
      }
244
    }
245

    
246
///////////////////////////////////////////////////////////////////////////////////////////////////
247

    
248
  public static void setMeshState(int ordinal, int state)
249
    {
250
    if( ordinal>=0 && ordinal<mNumObjects ) mObjects.get(ordinal).setMeshState(state);
251
    }
252

    
253
///////////////////////////////////////////////////////////////////////////////////////////////////
254

    
255
  public static int getMeshState(int ordinal)
256
    {
257
    return (ordinal>=0 && ordinal<mNumObjects) ? mObjects.get(ordinal).getMeshState() : MESH_NICE;
258
    }
259

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

    
262
  public static void saveMeshState(SharedPreferences.Editor editor)
263
    {
264
    for(int i=0; i<mNumObjects; i++)
265
      {
266
      RubikObject obj = getObject(i);
267

    
268
      if( obj!=null )
269
        {
270
        String name = obj.getUpperName();
271
        editor.putInt("rol_"+name, obj.getMeshState() );
272
        }
273
      }
274
    }
275

    
276
///////////////////////////////////////////////////////////////////////////////////////////////////
277

    
278
  public static boolean thereAreLockedObjects()
279
    {
280
    for(int i=0; i<mNumObjects; i++)
281
      {
282
      RubikObject o = mObjects.get(i);
283
      if( !o.isFree() ) return true;
284
      }
285

    
286
    return false;
287
    }
288

    
289
///////////////////////////////////////////////////////////////////////////////////////////////////
290

    
291
  public static boolean objectAlreadyBought(RubikObject object)
292
    {
293
    return ( object!=null && object.isFree() );
294
    }
295

    
296
///////////////////////////////////////////////////////////////////////////////////////////////////
297
// calling PurchaseScreenPane charges the user.
298

    
299
  public static void buyAll()
300
    {
301
    mBoughtObjects = "*";
302
    if( SHOW_IAP_DEBUG ) android.util.Log.e("D", "all objects marked as bought");
303

    
304
    for(int i=0; i<mNumObjects; i++)
305
      {
306
      RubikObject o = mObjects.get(i);
307
      o.markFree();
308
      }
309
    }
310

    
311
///////////////////////////////////////////////////////////////////////////////////////////////////
312
// calling PurchaseScreenPane charges the user.
313

    
314
  public static void buyObject(RubikObject object)
315
    {
316
    if( object!=null && !object.isFree() )
317
      {
318
      String shortName = object.getUpperName();
319
      if( SHOW_IAP_DEBUG ) android.util.Log.e("D", "object "+shortName+" marked as bought");
320
      object.markFree();
321
      String add = mBoughtObjects.length()==0 ? shortName : (","+shortName);
322
      mBoughtObjects += add;
323
      }
324
    }
325

    
326
///////////////////////////////////////////////////////////////////////////////////////////////////
327

    
328
  public static void savePreferences(SharedPreferences.Editor editor)
329
    {
330
    RubikObject obj = getObject(mObject);
331
    if( obj!=null ) editor.putString("rol_objName", obj.getUpperName() );
332

    
333
    int numDownloaded = mDownloadedObjects.size();
334

    
335
    if( numDownloaded>0 )
336
      {
337
      StringBuilder downloadedObjects = new StringBuilder();
338

    
339
      for(int i=0; i<numDownloaded; i++)
340
        {
341
        if( i>0 ) downloadedObjects.append(',');
342

    
343
        DownloadedObject object = mDownloadedObjects.get(i);
344
        downloadedObjects.append(object.shortName);
345
        downloadedObjects.append(' ');
346
        downloadedObjects.append(object.numScrambles);
347
        downloadedObjects.append(' ');
348
        downloadedObjects.append(object.objectMinor);
349
        downloadedObjects.append(' ');
350
        downloadedObjects.append(object.extrasMinor);
351
        downloadedObjects.append(' ');
352
        downloadedObjects.append(object.icon   ? "1":"0");
353
        downloadedObjects.append(' ');
354
        downloadedObjects.append(object.object ? "1":"0");
355
        downloadedObjects.append(' ');
356
        downloadedObjects.append(object.extras ? "1":"0");
357
        downloadedObjects.append(' ');
358
        downloadedObjects.append(object.price);
359
        }
360

    
361
      String objects = downloadedObjects.toString();
362
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "saving: "+objects);
363
      editor.putString("rol_downloaded", objects );
364
      }
365
    else
366
      {
367
      editor.putString("rol_downloaded", "" );
368
      }
369

    
370
    if( USE_IAP )
371
      {
372
      editor.putString("rol_bought", mBoughtObjects);
373

    
374
      if( SHOW_IAP_DEBUG )
375
        {
376
        android.util.Log.e("D", "saving bought objects: "+mBoughtObjects);
377
        }
378
      }
379
    }
380

    
381
///////////////////////////////////////////////////////////////////////////////////////////////////
382

    
383
  public static void savePreferencesMinimal(SharedPreferences.Editor editor)
384
    {
385
    RubikObject obj = getObject(mObject);
386
    if( obj!=null ) editor.putString("rol_objName", obj.getUpperName() );
387
    }
388

    
389
///////////////////////////////////////////////////////////////////////////////////////////////////
390

    
391
  public static void restorePreferences(Context context, SharedPreferences preferences, boolean justStarted)
392
    {
393
    if( mThis==null ) mThis = new RubikObjectList();
394

    
395
    String downloaded = preferences.getString("rol_downloaded","");
396

    
397
    if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", downloaded);
398

    
399
    if( !downloaded.equals(""))
400
      {
401
      String[] dObjects = downloaded.split(",");
402

    
403
      for(String dObj : dObjects)
404
        {
405
        String[] parts = dObj.split(" ");
406
        int length = parts.length;
407

    
408
        if( length==7 || length==8 )
409
          {
410
          String name = parts[0];
411
          String scra = parts[1];
412
          String objM = parts[2];
413
          String extM = parts[3];
414
          String icon = parts[4];
415
          String obje = parts[5];
416
          String extr = parts[6];
417

    
418
          int price;
419

    
420
          if( length==7 ) price=0;
421
          else
422
            {
423
            char c = parts[7].charAt(0);
424
            if( c=='t' )      price = 0;
425
            else if( c=='f' ) price = ObjectType.DEFAULT_PRICE_OF_OLD_OBJECTS;
426
            else              price = Integer.parseInt(parts[7]);
427
            }
428

    
429
          int scrambles = Integer.parseInt(scra);
430
          int oMinor    = Integer.parseInt(objM);
431
          int eMinor    = Integer.parseInt(extM);
432

    
433
          boolean bIcon = icon.equals("1");
434
          boolean bObje = obje.equals("1");
435
          boolean bExtr = extr.equals("1");
436

    
437
          addDownloadedObject(context,name,scrambles,price,oMinor,eMinor,bIcon,bObje,bExtr);
438
          }
439
        }
440
      }
441

    
442
    RubikObject object = getObject(DEF_OBJECT);
443
    String defName = object==null ? "CUBE_3" : object.getUpperName();
444
    String objName= preferences.getString("rol_objName",defName);
445
    mObject = getOrdinal(objName);
446
    if( mObject<0 || mObject>=mNumObjects ) mObject = DEF_OBJECT;
447

    
448
    if( USE_IAP && justStarted ) restoreFreedObjects(preferences);
449
    }
450

    
451
///////////////////////////////////////////////////////////////////////////////////////////////////
452

    
453
  public static void restoreMeshState(SharedPreferences preferences)
454
    {
455
    for(int i=0; i<mNumObjects; i++)
456
      {
457
      RubikObject obj = getObject(i);
458

    
459
      if( obj!=null )
460
        {
461
        String name  = obj.getUpperName();
462
        int meshState= preferences.getInt("rol_"+name,MESH_NICE);
463
        obj.setMeshState(meshState);
464
        }
465
      }
466
    }
467

    
468
///////////////////////////////////////////////////////////////////////////////////////////////////
469

    
470
  public static void firstUpgradeMarkAllSolvedAsFree()
471
    {
472
    RubikScores scores = RubikScores.getInstance();
473
    int numUnclaimed = scores.numberOfSolvedMAXes();
474

    
475
    if( numUnclaimed>0 )
476
      {
477
      int marked = markAllSolvedAsFree(scores);
478
      int stillUnclaimed = numUnclaimed-marked;
479
      if( stillUnclaimed>0) markObjectsAsFree(scores,stillUnclaimed);
480
      }
481
    }
482

    
483
///////////////////////////////////////////////////////////////////////////////////////////////////
484

    
485
  private static int markAllSolvedAsFree(RubikScores scores)
486
    {
487
    int numObjects = RubikObjectList.getNumObjects();
488
    int ret = 0;
489

    
490
    for(int obj=0; obj<numObjects; obj++)
491
      {
492
      RubikObject object = getObject(obj);
493

    
494
      if( object!=null && !object.isFree() && scores.isSolved(obj,LEVELS_SHOWN) )
495
        {
496
        markAsFree(object,scores);
497
        ret++;
498
        }
499
      }
500

    
501
    return ret;
502
    }
503

    
504
///////////////////////////////////////////////////////////////////////////////////////////////////
505

    
506
  private static void markObjectsAsFree(RubikScores scores, int numToBeMarked)
507
    {
508
    int numObjects = RubikObjectList.getNumObjects();
509

    
510
    for(int obj=0; obj<numObjects && numToBeMarked>0; obj++)
511
      {
512
      RubikObject object = getObject(obj);
513

    
514
      if( object!=null && !object.isFree() )
515
        {
516
        markAsFree(object,scores);
517
        numToBeMarked--;
518
        }
519
      }
520
    }
521

    
522
///////////////////////////////////////////////////////////////////////////////////////////////////
523

    
524
  private static void markAsFree(RubikObject object, RubikScores scores)
525
    {
526
    String shortName = object.getUpperName();
527
    if( SHOW_IAP_DEBUG ) android.util.Log.e("D", "object "+object.getUpperName()+" marked as free");
528
    object.markFree();
529
    int price = object.getPrice();
530
    scores.changeNumStars(-price);
531
    String add = mBoughtObjects.length()==0 ? shortName : (","+shortName);
532
    mBoughtObjects += add;
533
    }
534

    
535
///////////////////////////////////////////////////////////////////////////////////////////////////
536

    
537
  public static boolean setCurrObject(int ordinal)
538
    {
539
    if( mObject!=ordinal )
540
      {
541
      mObject = ordinal;
542
      return true;
543
      }
544

    
545
    return false;
546
    }
547

    
548
///////////////////////////////////////////////////////////////////////////////////////////////////
549

    
550
  public static int getCurrObject()
551
    {
552
    return mObject;
553
    }
554

    
555
///////////////////////////////////////////////////////////////////////////////////////////////////
556

    
557
  public static String getCurrentName()
558
    {
559
    RubikObject object = mObjects.get(mObject);
560
    return object==null ? "" : object.getUpperName();
561
    }
562

    
563
///////////////////////////////////////////////////////////////////////////////////////////////////
564

    
565
  public static RubikObject getObject(int ordinal)
566
    {
567
    if( mThis==null ) mThis = new RubikObjectList();
568
    return ordinal>=0 && ordinal<mNumObjects ? mObjects.get(ordinal) : null;
569
    }
570

    
571
///////////////////////////////////////////////////////////////////////////////////////////////////
572

    
573
  public static RubikObject getObject(String shortUpperName)
574
    {
575
    if( mThis==null ) mThis = new RubikObjectList();
576

    
577
    for(int i=0; i<mNumObjects; i++)
578
      {
579
      RubikObject object = mObjects.get(i);
580
      if( object.getUpperName().equals(shortUpperName) )
581
        {
582
        return object;
583
        }
584
      }
585

    
586
    return null;
587
    }
588

    
589
///////////////////////////////////////////////////////////////////////////////////////////////////
590

    
591
  public static int getNumObjects()
592
    {
593
    if( mThis==null ) mThis = new RubikObjectList();
594
    return mNumObjects;
595
    }
596

    
597
///////////////////////////////////////////////////////////////////////////////////////////////////
598

    
599
  public static int getOrdinal(String name)
600
    {
601
    if( mThis==null ) mThis = new RubikObjectList();
602

    
603
    String lowerName = name.toLowerCase(Locale.ENGLISH);
604

    
605
    for(int i=0; i<mNumObjects; i++)
606
      {
607
      RubikObject obj = mObjects.get(i);
608
      if( obj.getLowerName().equals(lowerName) ) return i;
609
      }
610

    
611
    return -1;
612
    }
613

    
614
///////////////////////////////////////////////////////////////////////////////////////////////////
615

    
616
  public static int getNumExtrasObjects()
617
    {
618
    return mNumExtras;
619
    }
620

    
621
///////////////////////////////////////////////////////////////////////////////////////////////////
622

    
623
  public static int getNumTutorialObjects()
624
    {
625
    return mNumExtras;
626
    }
627

    
628
///////////////////////////////////////////////////////////////////////////////////////////////////
629

    
630
  public static int getObjectOrdinal(int extrasOrdinal)
631
    {
632
    for(int i=extrasOrdinal; i<mNumObjects; i++)
633
      {
634
      RubikObject object = getObject(i);
635
      int extOrd = object!=null ? object.getExtrasOrdinal() : -1;
636
      if( extOrd==extrasOrdinal ) return i;
637
      }
638

    
639
    return -1;
640
    }
641

    
642
///////////////////////////////////////////////////////////////////////////////////////////////////
643

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

    
650
///////////////////////////////////////////////////////////////////////////////////////////////////
651

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

    
658
///////////////////////////////////////////////////////////////////////////////////////////////////
659

    
660
  public static int getLocalObjectMinor(int objectOrdinal)
661
    {
662
    RubikObject object = getObject(objectOrdinal);
663
    return object!=null ? object.getObjectMinor() : -1;
664
    }
665

    
666
///////////////////////////////////////////////////////////////////////////////////////////////////
667

    
668
  public static int getLocalExtrasMinor(int objectOrdinal)
669
    {
670
    RubikObject object = getObject(objectOrdinal);
671
    return object!=null ? object.getExtrasMinor() : -1;
672
    }
673
}
(2-2/2)