1 package ru
.deadsoftware
.cavedroid
.game
;
3 import com
.badlogic
.gdx
.Gdx
;
4 import com
.badlogic
.gdx
.files
.FileHandle
;
5 import ru
.deadsoftware
.cavedroid
.MainConfig
;
6 import ru
.deadsoftware
.cavedroid
.game
.mobs
.MobsController
;
7 import ru
.deadsoftware
.cavedroid
.game
.model
.block
.Block
;
8 import ru
.deadsoftware
.cavedroid
.game
.objects
.DropController
;
9 import ru
.deadsoftware
.cavedroid
.game
.world
.GameWorld
;
11 import javax
.annotation
.CheckForNull
;
13 import java
.nio
.ByteBuffer
;
14 import java
.util
.HashMap
;
17 public class GameSaver
{
19 private static final String TAG
= "GameSaver";
21 public static class Data
{
23 private MobsController mMobsController
;
25 private DropController mDropController
;
27 private Block
[][] mForeMap
, mBackMap
;
29 public Data(MobsController mobsController
, DropController dropController
, Block
[][] foreMap
, Block
[][] backMap
) {
30 mMobsController
= mobsController
;
31 mDropController
= dropController
;
36 public MobsController
retrieveMobsController() {
37 assert mMobsController
!= null;
38 MobsController mobsController
= mMobsController
;
39 mMobsController
= null;
40 return mobsController
;
43 public DropController
retrieveDropController() {
44 assert mDropController
!= null;
45 DropController dropController
= mDropController
;
46 mDropController
= null;
47 return dropController
;
50 public Block
[][] retrieveForeMap() {
51 assert mForeMap
!= null;
52 Block
[][] foreMap
= mForeMap
;
57 public Block
[][] retrieveBackMap() {
58 assert mBackMap
!= null;
59 Block
[][] backMap
= mBackMap
;
64 public boolean isEmpty() {
65 return mMobsController
== null && mDropController
== null && mForeMap
== null && mBackMap
== null;
69 private static final int SAVE_VERSION
= 1;
71 private static byte[] intToBytes(int i
) {
72 return ByteBuffer
.allocate(4).putInt(i
).array();
75 private static Map
<String
, Integer
> buildBlocksDictionary(Block
[][] foreMap
, Block
[][] backMap
) {
76 final HashMap
<String
, Integer
> dict
= new HashMap
<>();
79 for (int i
= 0; i
< foreMap
.length
; i
++) {
80 for (int j
= 0; j
< foreMap
[i
].length
; j
++) {
81 for (int k
= 0; k
< 2; k
++) {
82 final Block block
= k
== 0 ? foreMap
[i
][j
] : backMap
[i
][j
];
83 final String key
= block
.getParams().getKey();
84 if (!dict
.containsKey(key
)) {
94 private static void saveDict(FileHandle file
, Map
<String
, Integer
> dict
) {
95 final String
[] arr
= new String
[dict
.size()];
97 for (Map
.Entry
<String
, Integer
> entry
: dict
.entrySet()) {
98 arr
[entry
.getValue()] = entry
.getKey();
101 final StringBuilder builder
= new StringBuilder();
102 for (String key
: arr
) {
104 builder
.append('\n');
107 file
.writeString(builder
.toString(), false);
110 private static String
[] loadDict(FileHandle file
) {
111 return file
.readString().split("\n");
114 private static void saveMap(FileHandle file
, Block
[][] map
, Map
<String
, Integer
> dict
) throws IOException
{
116 int width
= map
.length
;
117 int height
= map
[0].length
;
119 BufferedOutputStream out
= new BufferedOutputStream(file
.write(false));
121 out
.write(intToBytes(SAVE_VERSION
));
122 out
.write(intToBytes(width
));
123 out
.write(intToBytes(height
));
125 for (int y
= 0; y
< height
; y
++) {
126 block
= dict
.get(map
[0][y
].getParams().getKey());
128 for (Block
[] blocks
: map
) {
129 int newValue
= dict
.get(blocks
[y
].getParams().getKey());
130 if (newValue
!= block
) {
131 out
.write(intToBytes(run
));
132 out
.write(intToBytes(block
));
134 block
= dict
.get(blocks
[y
].getParams().getKey());
138 out
.write(intToBytes(run
));
139 out
.write(intToBytes(block
));
146 private static Block
[][] loadMap(GameItemsHolder gameItemsHolder
, FileHandle file
, String
[] dict
) throws Exception
{
148 int version
, width
, height
;
151 DataInputStream in
= new DataInputStream(file
.read());
153 version
= in
.readInt();
155 if (SAVE_VERSION
== version
) {
156 width
= in
.readInt();
157 height
= in
.readInt();
158 map
= new Block
[width
][height
];
159 for (int y
= 0; y
< height
; y
++) {
160 for (int x
= 0; x
< width
; x
+= run
) {
162 block
= in
.readInt();
163 for (int i
= x
; i
< x
+ run
; i
++) {
164 map
[i
][y
] = gameItemsHolder
.getBlock(dict
[block
]);
169 throw new Exception("version mismatch");
177 public static Data
load(MainConfig mainConfig
, GameItemsHolder gameItemsHolder
) {
178 String folder
= mainConfig
.getGameFolder();
179 FileHandle file
= Gdx
.files
.absolute(folder
+ "/saves/game.sav");
182 ObjectInputStream in
= new ObjectInputStream(file
.read());
183 int version
= in
.readInt();
184 DropController dropController
;
185 MobsController mobsController
;
187 if (SAVE_VERSION
== version
) {
188 dropController
= (DropController
) in
.readObject();
189 mobsController
= (MobsController
) in
.readObject();
191 throw new Exception("version mismatch");
196 final String
[] dict
= loadDict(Gdx
.files
.absolute(mainConfig
.getGameFolder() + "/saves/dict"));
197 Block
[][] foreMap
= loadMap(gameItemsHolder
, Gdx
.files
.absolute(mainConfig
.getGameFolder() + "/saves/foremap.sav"), dict
);
198 Block
[][] backMap
= loadMap(gameItemsHolder
, Gdx
.files
.absolute(mainConfig
.getGameFolder() + "/saves/backmap.sav"), dict
);
200 if (dropController
== null || mobsController
== null) {
201 throw new Exception("couldn't load");
204 return new Data(mobsController
, dropController
, foreMap
, backMap
);
205 } catch (Exception e
) {
206 Gdx
.app
.error("GameSaver", e
.getMessage());
212 public static void save(MainConfig mainConfig
,
213 DropController dropController
,
214 MobsController mobsController
,
215 GameWorld gameWorld
) {
216 String folder
= mainConfig
.getGameFolder();
217 FileHandle file
= Gdx
.files
.absolute(folder
+ "/saves/");
219 file
= Gdx
.files
.absolute(folder
+ "/saves/game.sav");
221 final Block
[][] foreMap
, backMap
;
222 foreMap
= gameWorld
.getFullForeMap();
223 backMap
= gameWorld
.getFullBackMap();
225 final Map
<String
, Integer
> dict
= buildBlocksDictionary(foreMap
, backMap
);
228 ObjectOutputStream out
= new ObjectOutputStream(file
.write(false));
229 out
.writeInt(SAVE_VERSION
);
230 out
.writeObject(dropController
);
231 out
.writeObject(mobsController
);
234 saveDict(Gdx
.files
.absolute(folder
+ "/saves/dict"), dict
);
235 saveMap(Gdx
.files
.absolute(folder
+ "/saves/foremap.sav"), gameWorld
.getFullForeMap(), dict
);
236 saveMap(Gdx
.files
.absolute(folder
+ "/saves/backmap.sav"), gameWorld
.getFullBackMap(), dict
);
237 } catch (Exception e
) {
242 public static boolean exists(MainConfig mainConfig
) {
243 String folder
= mainConfig
.getGameFolder();
244 return (Gdx
.files
.absolute(folder
+ "/saves/game.sav").exists() &&
245 Gdx
.files
.absolute(folder
+ "/saves/foremap.sav").exists() &&
246 Gdx
.files
.absolute(folder
+ "/saves/backmap.sav").exists());