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
.drop
.DropController
;
9 import ru
.deadsoftware
.cavedroid
.game
.objects
.furnace
.FurnaceController
;
10 import ru
.deadsoftware
.cavedroid
.game
.world
.GameWorld
;
12 import javax
.annotation
.CheckForNull
;
14 import java
.nio
.ByteBuffer
;
15 import java
.util
.HashMap
;
18 public class GameSaver
{
20 private static final String TAG
= "GameSaver";
22 public static class Data
{
24 private MobsController mMobsController
;
26 private DropController mDropController
;
28 private FurnaceController mFurnaceController
;
30 private Block
[][] mForeMap
, mBackMap
;
32 public Data(MobsController mobsController
,
33 DropController dropController
,
34 FurnaceController furnaceController
,
37 mMobsController
= mobsController
;
38 mDropController
= dropController
;
39 mFurnaceController
= furnaceController
;
44 public MobsController
retrieveMobsController() {
45 assert mMobsController
!= null;
46 MobsController mobsController
= mMobsController
;
47 mMobsController
= null;
48 return mobsController
;
51 public DropController
retrieveDropController() {
52 assert mDropController
!= null;
53 DropController dropController
= mDropController
;
54 mDropController
= null;
55 return dropController
;
58 public FurnaceController
retrueveFurnaceController() {
59 assert mFurnaceController
!= null;
60 FurnaceController furnaceController
= mFurnaceController
;
61 mFurnaceController
= null;
62 return furnaceController
;
65 public Block
[][] retrieveForeMap() {
66 assert mForeMap
!= null;
67 Block
[][] foreMap
= mForeMap
;
72 public Block
[][] retrieveBackMap() {
73 assert mBackMap
!= null;
74 Block
[][] backMap
= mBackMap
;
79 public boolean isEmpty() {
80 return mMobsController
== null && mDropController
== null && mForeMap
== null && mBackMap
== null;
84 private static final int SAVE_VERSION
= 1;
86 private static byte[] intToBytes(int i
) {
87 return ByteBuffer
.allocate(4).putInt(i
).array();
90 private static Map
<String
, Integer
> buildBlocksDictionary(Block
[][] foreMap
, Block
[][] backMap
) {
91 final HashMap
<String
, Integer
> dict
= new HashMap
<>();
94 for (int i
= 0; i
< foreMap
.length
; i
++) {
95 for (int j
= 0; j
< foreMap
[i
].length
; j
++) {
96 for (int k
= 0; k
< 2; k
++) {
97 final Block block
= k
== 0 ? foreMap
[i
][j
] : backMap
[i
][j
];
98 final String key
= block
.getParams().getKey();
99 if (!dict
.containsKey(key
)) {
109 private static void saveDict(FileHandle file
, Map
<String
, Integer
> dict
) {
110 final String
[] arr
= new String
[dict
.size()];
112 for (Map
.Entry
<String
, Integer
> entry
: dict
.entrySet()) {
113 arr
[entry
.getValue()] = entry
.getKey();
116 final StringBuilder builder
= new StringBuilder();
117 for (String key
: arr
) {
119 builder
.append('\n');
122 file
.writeString(builder
.toString(), false);
125 private static String
[] loadDict(FileHandle file
) {
126 return file
.readString().split("\n");
129 private static void saveMap(FileHandle file
, Block
[][] map
, Map
<String
, Integer
> dict
) throws IOException
{
131 int width
= map
.length
;
132 int height
= map
[0].length
;
134 BufferedOutputStream out
= new BufferedOutputStream(file
.write(false));
136 out
.write(SAVE_VERSION
);
137 out
.write(intToBytes(width
));
138 out
.write(intToBytes(height
));
140 for (int y
= 0; y
< height
; y
++) {
141 block
= dict
.get(map
[0][y
].getParams().getKey());
143 for (Block
[] blocks
: map
) {
144 int newValue
= dict
.get(blocks
[y
].getParams().getKey());
145 if (run
>= 0xFF || newValue
!= block
) {
149 block
= dict
.get(blocks
[y
].getParams().getKey());
161 private static Block
[][] loadMap(GameItemsHolder gameItemsHolder
, FileHandle file
, String
[] dict
) throws Exception
{
163 int version
, width
, height
;
166 DataInputStream in
= new DataInputStream(file
.read());
168 version
= in
.readByte();
170 if (SAVE_VERSION
== version
) {
171 width
= in
.readInt();
172 height
= in
.readInt();
173 map
= new Block
[width
][height
];
174 for (int y
= 0; y
< height
; y
++) {
175 for (int x
= 0; x
< width
; x
+= run
) {
176 run
= in
.readUnsignedByte();
177 block
= in
.readUnsignedByte();
178 for (int i
= x
; i
< x
+ run
; i
++) {
179 map
[i
][y
] = gameItemsHolder
.getBlock(dict
[block
]);
184 throw new Exception("version mismatch");
192 public static Data
load(MainConfig mainConfig
, GameItemsHolder gameItemsHolder
) {
193 String folder
= mainConfig
.getGameFolder();
194 FileHandle file
= Gdx
.files
.absolute(folder
+ "/saves/game.sav");
197 ObjectInputStream in
= new ObjectInputStream(file
.read());
198 int version
= in
.readInt();
199 DropController dropController
;
200 MobsController mobsController
;
201 FurnaceController furnaceController
;
203 if (SAVE_VERSION
== version
) {
204 dropController
= (DropController
) in
.readObject();
205 mobsController
= (MobsController
) in
.readObject();
206 furnaceController
= (FurnaceController
) in
.readObject();
208 throw new Exception("version mismatch");
213 final String
[] dict
= loadDict(Gdx
.files
.absolute(mainConfig
.getGameFolder() + "/saves/dict"));
214 Block
[][] foreMap
= loadMap(gameItemsHolder
, Gdx
.files
.absolute(mainConfig
.getGameFolder() + "/saves/foremap.sav"), dict
);
215 Block
[][] backMap
= loadMap(gameItemsHolder
, Gdx
.files
.absolute(mainConfig
.getGameFolder() + "/saves/backmap.sav"), dict
);
217 if (dropController
== null || mobsController
== null) {
218 throw new Exception("couldn't load");
221 return new Data(mobsController
, dropController
, furnaceController
, foreMap
, backMap
);
222 } catch (Exception e
) {
223 Gdx
.app
.error("GameSaver", e
.getMessage());
229 public static void save(MainConfig mainConfig
,
230 DropController dropController
,
231 MobsController mobsController
,
232 FurnaceController furnaceController
,
233 GameWorld gameWorld
) {
234 String folder
= mainConfig
.getGameFolder();
235 FileHandle file
= Gdx
.files
.absolute(folder
+ "/saves/");
237 file
= Gdx
.files
.absolute(folder
+ "/saves/game.sav");
239 final Block
[][] foreMap
, backMap
;
240 foreMap
= gameWorld
.getFullForeMap();
241 backMap
= gameWorld
.getFullBackMap();
243 final Map
<String
, Integer
> dict
= buildBlocksDictionary(foreMap
, backMap
);
246 ObjectOutputStream out
= new ObjectOutputStream(file
.write(false));
247 out
.writeInt(SAVE_VERSION
);
248 out
.writeObject(dropController
);
249 out
.writeObject(mobsController
);
250 out
.writeObject(furnaceController
);
253 saveDict(Gdx
.files
.absolute(folder
+ "/saves/dict"), dict
);
254 saveMap(Gdx
.files
.absolute(folder
+ "/saves/foremap.sav"), gameWorld
.getFullForeMap(), dict
);
255 saveMap(Gdx
.files
.absolute(folder
+ "/saves/backmap.sav"), gameWorld
.getFullBackMap(), dict
);
256 } catch (Exception e
) {
261 public static boolean exists(MainConfig mainConfig
) {
262 String folder
= mainConfig
.getGameFolder();
263 return (Gdx
.files
.absolute(folder
+ "/saves/game.sav").exists() &&
264 Gdx
.files
.absolute(folder
+ "/saves/foremap.sav").exists() &&
265 Gdx
.files
.absolute(folder
+ "/saves/backmap.sav").exists());