tiles_tools 0.2.0

High-performance tile-based game development toolkit with comprehensive coordinate systems (hexagonal, square, triangular, isometric), pathfinding, ECS integration, and grid management.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
//! Serialization system demonstration showing save/load functionality.

#![allow(clippy::needless_return)]
#![allow(clippy::implicit_return)]
#![allow(clippy::uninlined_format_args)]
#![allow(clippy::items_after_statements)]
#![allow(clippy::unnecessary_cast)]
#![allow(clippy::doc_markdown)]
#![allow(clippy::cast_sign_loss)]
#![allow(clippy::explicit_iter_loop)]
#![allow(clippy::format_in_format_args)]
#![allow(clippy::cast_precision_loss)]
#![allow(clippy::wildcard_imports)]
#![allow(clippy::too_many_lines)]
#![allow(clippy::std_instead_of_core)]
#![allow(clippy::similar_names)]
#![allow(clippy::duplicated_attributes)]
#![allow(clippy::cast_possible_truncation)]
#![allow(clippy::trivially_copy_pass_by_ref)]
#![allow(clippy::missing_inline_in_public_items)]
#![allow(clippy::useless_vec)]
#![allow(clippy::unnested_or_patterns)]
#![allow(clippy::else_if_without_else)]
#![allow(clippy::unreadable_literal)]
#![allow(clippy::redundant_else)]
#![allow(clippy::field_reassign_with_default)]
#![allow(clippy::min_ident_chars)]
//!
//! This example demonstrates the comprehensive serialization system including:
//! - Game state serialization and deserialization
//! - Multiple serialization formats (JSON, Binary, RON)
//! - Configuration management and persistence
//! - Save file management with metadata
//! - Version compatibility checking
//! - Compression support

use tiles_tools::serialization::*;

fn main() {
  println!("💾 Serialization System Demonstration");
  println!("=====================================");

  // === BASIC SERIALIZATION ===
  println!("\n📄 Basic Game State Serialization");
  println!("----------------------------------");

  // Create a basic game state
  let mut game_state = GameStateSerializer::create_basic_game_state("My First Save".to_string());
  
  // Add some custom data
  game_state.progress.level = 5;
  game_state.progress.experience = 2500;
  game_state.progress.playtime_seconds = 3600; // 1 hour
  game_state.progress.levels_completed.push("tutorial".to_string());
  game_state.progress.levels_completed.push("forest_1".to_string());
  
  // Add an achievement
  game_state.progress.achievements.push(Achievement {
  id: "first_level".to_string(),
  name: "First Steps".to_string(),
  description: "Complete your first level".to_string(),
  unlocked_at: 1234567890,
  points: 50,
  });

  // Update game statistics
  game_state.progress.statistics.entities_defeated = 25;
  game_state.progress.statistics.distance_moved = 1500.0;
  game_state.progress.statistics.items_collected = 12;

  // Add custom metadata tags
  game_state.metadata = game_state.metadata
  .with_tag("demo".to_string())
  .with_tag("tutorial_complete".to_string())
  .with_custom("difficulty".to_string(), "normal".to_string())
  .with_custom("character_class".to_string(), "warrior".to_string());

  println!("Created game state:");
  println!("  Player Level: {}", game_state.progress.level);
  println!("  Experience: {}", game_state.progress.experience);
  println!("  Playtime: {}h {}m", 
  game_state.progress.playtime_seconds / 3600, 
  (game_state.progress.playtime_seconds % 3600) / 60);
  println!("  Achievements: {}", game_state.progress.achievements.len());
  println!("  Levels Completed: {}", game_state.progress.levels_completed.len());

  // === MULTIPLE FORMATS DEMONSTRATION ===
  println!("\n🔄 Multiple Serialization Formats");
  println!("----------------------------------");

  // Test JSON serialization
  let json_serializer = GameStateSerializer::new()
  .with_format(SerializationFormat::Json);

  let json_data = json_serializer.serialize_game_state(&game_state)
  .expect("Failed to serialize to JSON");
  println!("JSON serialization: {} bytes", json_data.len());

  // Test Binary serialization
  let binary_serializer = GameStateSerializer::new()
  .with_format(SerializationFormat::Binary);

  let binary_data = binary_serializer.serialize_game_state(&game_state)
  .expect("Failed to serialize to binary");
  println!("Binary serialization: {} bytes", binary_data.len());

  // Test RON serialization
  let ron_serializer = GameStateSerializer::new()
  .with_format(SerializationFormat::Ron);

  let ron_data = ron_serializer.serialize_game_state(&game_state)
  .expect("Failed to serialize to RON");
  println!("RON serialization: {} bytes", ron_data.len());

  // Verify deserialization works
  let json_restored = json_serializer.deserialize_game_state(&json_data)
  .expect("Failed to deserialize JSON");
  let binary_restored = binary_serializer.deserialize_game_state(&binary_data)
  .expect("Failed to deserialize binary");
  let ron_restored = ron_serializer.deserialize_game_state(&ron_data)
  .expect("Failed to deserialize RON");

  println!("✅ All formats successfully roundtrip serialized");
  println!("  JSON player level: {}", json_restored.progress.level);
  println!("  Binary player level: {}", binary_restored.progress.level);
  println!("  RON player level: {}", ron_restored.progress.level);

  // === COMPRESSION DEMONSTRATION ===
  println!("\n🗜️ Compression");
  println!("--------------");

  let uncompressed_serializer = GameStateSerializer::new()
  .with_compression(false);
  let compressed_serializer = GameStateSerializer::new()
  .with_compression(true);

  let uncompressed = uncompressed_serializer.serialize_game_state(&game_state)
  .expect("Failed to serialize uncompressed");
  let compressed = compressed_serializer.serialize_game_state(&game_state)
  .expect("Failed to serialize compressed");

  println!("Uncompressed size: {} bytes", uncompressed.len());
  println!("Compressed size: {} bytes", compressed.len());
  let ratio = if compressed.len() < uncompressed.len() {
  ((uncompressed.len() - compressed.len()) as f64 / uncompressed.len() as f64) * 100.0
  } else {
  // No compression achieved (mock compression adds overhead)
  -((compressed.len() - uncompressed.len()) as f64 / uncompressed.len() as f64) * 100.0
  };
  println!("Compression ratio: {:.1}%", ratio);

  // Verify compressed data can be decompressed
  let decompressed = compressed_serializer.deserialize_game_state(&compressed)
  .expect("Failed to decompress data");
  println!("✅ Compression/decompression successful");
  println!("  Restored player level: {}", decompressed.progress.level);

  // === SAVE MANAGER DEMONSTRATION ===
  println!("\n💾 Save Manager");
  println!("---------------");

  // Create a temporary directory for saves (in real usage, this would be a persistent directory)
  let temp_dir = std::env::temp_dir().join("tiles_tools_demo_saves");
  std::fs::create_dir_all(&temp_dir).expect("Failed to create saves directory");

  let save_manager = SaveManager::new(&temp_dir)
  .with_serializer(GameStateSerializer::new().with_compression(true));

  // Save the game state
  save_manager.save_game_state("demo_save", &game_state)
  .expect("Failed to save game state");
  println!("✅ Game saved as 'demo_save'");

  // Create additional saves with different states
  let mut quick_save = game_state.clone();
  quick_save.metadata.description = "Quick Save - Before Boss Fight".to_string();
  quick_save.progress.level = 6;
  quick_save.progress.experience = 3000;
  
  save_manager.save_game_state("quick_save", &quick_save)
  .expect("Failed to save quick save");

  let mut checkpoint = game_state.clone();
  checkpoint.metadata.description = "Checkpoint - Forest Entry".to_string();
  checkpoint.progress.level = 4;
  checkpoint.progress.experience = 1800;
  checkpoint.metadata = checkpoint.metadata.with_tag("checkpoint".to_string());

  save_manager.save_game_state("checkpoint_1", &checkpoint)
  .expect("Failed to save checkpoint");

  // List all saves
  println!("\n📂 Available Saves:");
  let saves = save_manager.list_saves()
  .expect("Failed to list saves");
  for save_name in &saves {
  println!("  - {}", save_name);
  }

  // Get detailed save information
  println!("\n📊 Save Information:");
  let saves_info = save_manager.get_saves_info()
  .expect("Failed to get saves info");
  
  for (name, metadata) in &saves_info {
  let _created_time = std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(metadata.created_at);
  println!("  Save: {}", name);
  println!("    Description: {}", metadata.description);
  println!("    Size: {} bytes", metadata.size_bytes);
  println!("    Version: {}.{}.{}", metadata.version.major, metadata.version.minor, metadata.version.patch);
  println!("    Compressed: {}", metadata.compressed);
  println!("    Tags: {:?}", metadata.tags);
  if !metadata.custom.is_empty() {
    println!("    Custom data: {:?}", metadata.custom);
  }
  println!();
  }

  // Load a specific save
  println!("🔄 Loading save 'demo_save'...");
  let loaded_state = save_manager.load_game_state("demo_save")
  .expect("Failed to load save");
  
  println!("✅ Save loaded successfully:");
  println!("  Player Level: {}", loaded_state.progress.level);
  println!("  Experience: {}", loaded_state.progress.experience);
  println!("  Description: {}", loaded_state.metadata.description);
  println!("  Achievements: {}", loaded_state.progress.achievements.len());

  // === VERSION COMPATIBILITY ===
  println!("\n🔄 Version Compatibility");
  println!("------------------------");

  let current_version = SaveVersion::current();
  let older_version = SaveVersion::new(1, 0, 0);
  let newer_version = SaveVersion::new(1, 1, 0);
  let incompatible_version = SaveVersion::new(2, 0, 0);

  println!("Current version: {}.{}.{}", current_version.major, current_version.minor, current_version.patch);
  println!("Older version compatibility: {}", current_version.is_compatible_with(&older_version));
  println!("Newer version compatibility: {}", older_version.is_compatible_with(&newer_version));
  println!("Incompatible version compatibility: {}", current_version.is_compatible_with(&incompatible_version));

  // === CONFIGURATION MANAGEMENT ===
  println!("\n⚙️ Configuration Management");
  println!("---------------------------");

  let config_path = temp_dir.join("game_config.json");
  let config_manager = ConfigManager::new(&config_path);

  // Create custom configuration
  let mut custom_config = GameConfig::default();
  custom_config.difficulty = 3;
  custom_config.graphics.resolution_width = 2560;
  custom_config.graphics.resolution_height = 1440;
  custom_config.graphics.quality_level = 3;
  custom_config.audio.master_volume = 0.8;
  custom_config.gameplay.auto_save_interval = 600; // 10 minutes
  
  // Add custom keybindings
  custom_config.controls.key_bindings.insert("sprint".to_string(), "Shift".to_string());
  custom_config.controls.key_bindings.insert("inventory".to_string(), "Tab".to_string());

  // Save configuration
  config_manager.save_config(&custom_config)
  .expect("Failed to save configuration");
  println!("✅ Configuration saved");

  // Load configuration
  let loaded_config = config_manager.load_config()
  .expect("Failed to load configuration");
  println!("✅ Configuration loaded:");
  println!("  Difficulty: {}", loaded_config.difficulty);
  println!("  Resolution: {}x{}", loaded_config.graphics.resolution_width, loaded_config.graphics.resolution_height);
  println!("  Master Volume: {}", loaded_config.audio.master_volume);
  println!("  Auto-save Interval: {}s", loaded_config.gameplay.auto_save_interval);
  println!("  Key bindings: {}", loaded_config.controls.key_bindings.len());

  // === PLAYER PROGRESS TRACKING ===
  println!("\n👤 Player Progress Tracking");
  println!("---------------------------");

  let mut progress = PlayerProgress::default();
  
  // Simulate some gameplay progress
  progress.level = 8;
  progress.experience = 5500;
  progress.playtime_seconds = 7200; // 2 hours
  
  // Add completed levels
  progress.levels_completed.extend([
  "tutorial".to_string(),
  "forest_1".to_string(),
  "forest_2".to_string(),
  "caves_1".to_string(),
  ]);

  // Add achievements
  progress.achievements.extend([
  Achievement {
    id: "level_5".to_string(),
    name: "Experienced".to_string(),
    description: "Reach level 5".to_string(),
    unlocked_at: 1234567890,
    points: 100,
  },
  Achievement {
    id: "cave_explorer".to_string(),
    name: "Cave Explorer".to_string(),
    description: "Complete the cave levels".to_string(),
    unlocked_at: 1234568000,
    points: 150,
  },
  ]);

  // Update statistics
  progress.statistics.entities_defeated = 150;
  progress.statistics.distance_moved = 5000.0;
  progress.statistics.items_collected = 45;
  progress.statistics.spells_cast = 80;
  progress.statistics.deaths = 3;
  progress.statistics.levels_completed_count = 4;

  // Serialize progress
  let _progress_json = serde_json::to_string_pretty(&progress)
  .expect("Failed to serialize progress");
  
  println!("Player Progress Summary:");
  println!("  Level: {}", progress.level);
  println!("  Experience: {}", progress.experience);
  println!("  Playtime: {}h {}m", progress.playtime_seconds / 3600, (progress.playtime_seconds % 3600) / 60);
  println!("  Levels Completed: {}", progress.levels_completed.len());
  println!("  Achievements: {} (total {} points)", 
  progress.achievements.len(),
  progress.achievements.iter().map(|a| a.points).sum::<u32>());
  println!("  Statistics:");
  println!("    Entities Defeated: {}", progress.statistics.entities_defeated);
  println!("    Distance Moved: {:.1}m", progress.statistics.distance_moved);
  println!("    Items Collected: {}", progress.statistics.items_collected);
  println!("    Spells Cast: {}", progress.statistics.spells_cast);
  println!("    Deaths: {}", progress.statistics.deaths);

  // === CLEANUP DEMONSTRATION ===
  println!("\n🧹 Cleanup");
  println!("----------");

  // Demonstrate save deletion
  save_manager.delete_save("checkpoint_1")
  .expect("Failed to delete save");
  println!("✅ Deleted checkpoint_1 save");

  let remaining_saves = save_manager.list_saves()
  .expect("Failed to list remaining saves");
  println!("Remaining saves: {:?}", remaining_saves);

  // Clean up temporary directory
  std::fs::remove_dir_all(&temp_dir).ok();
  println!("✅ Cleaned up temporary files");

  // === PERFORMANCE DEMONSTRATION ===
  println!("\n⚡ Performance Test");
  println!("------------------");

  let mut large_state = game_state.clone();
  
  // Add lots of custom data to simulate a large game state
  for i in 0..100 {
  large_state.custom_data.insert(
    format!("large_data_{}", i),
    vec![0u8; 1024] // 1KB per entry
  );
  }

  let start_time = std::time::Instant::now();
  let serialized_large = GameStateSerializer::new()
  .with_compression(true)
  .serialize_game_state(&large_state)
  .expect("Failed to serialize large state");
  let serialize_duration = start_time.elapsed();

  let start_time = std::time::Instant::now();
  let _deserialized_large = GameStateSerializer::new()
  .with_compression(true)
  .deserialize_game_state(&serialized_large)
  .expect("Failed to deserialize large state");
  let deserialize_duration = start_time.elapsed();

  println!("Large game state performance:");
  println!("  Size: {} KB", serialized_large.len() / 1024);
  println!("  Serialize time: {:.2}ms", serialize_duration.as_secs_f64() * 1000.0);
  println!("  Deserialize time: {:.2}ms", deserialize_duration.as_secs_f64() * 1000.0);

  println!("\n✨ Serialization Demo Complete!");
  println!("\nKey features demonstrated:");
  println!("• Multiple serialization formats (JSON, Binary, RON)");
  println!("• Compression support with size reduction");
  println!("• Save file management with metadata");
  println!("• Configuration persistence");
  println!("• Player progress tracking");
  println!("• Version compatibility checking");
  println!("• Error handling and recovery");
  println!("• Performance optimization");
}