@@ -397,161 +397,3 @@ mod tests {
397397}
398398```
399399
400- ### Testing Traits and Methods
401-
402- ``` cairo
403- #[test]
404- fn test_is_rare() {
405- let mut potion = PotionTrait::new_potion(1);
406-
407- potion.rarity = Rarity::VeryRare;
408- assert_eq!(potion.is_rare(), true, "VeryRare should return true");
409-
410- potion.rarity = Rarity::Rare;
411- assert_eq!(potion.is_rare(), true, "Rare should return true");
412-
413- potion.rarity = Rarity::Uncommon;
414- assert_eq!(potion.is_rare(), false, "Uncommon should return false");
415- }
416- ```
417-
418- ## Special Model Patterns
419-
420- ### Game Settings with Constant Keys
421-
422- For global values or settings:
423-
424- ``` cairo
425- const GAME_SETTINGS_ID: u32 = 9999999999999;
426-
427- #[derive(Copy, Drop, Serde)]
428- #[dojo::model]
429- struct GameSettings {
430- #[key]
431- game_settings_id: u32,
432- combat_cool_down: u32,
433- }
434-
435- // Usage:
436- world.read_model(GAME_SETTINGS_ID);
437- ```
438-
439- ### Type-Safe Entity IDs
440-
441- To avoid ID collisions:
442-
443- ``` cairo
444- const HUMAN: felt252 = 'HUMAN';
445- const GOBLIN: felt252 = 'GOBLIN';
446-
447- // Create unique IDs:
448- let human_id = poseidon_hash_span([id, HUMAN].span());
449- let goblin_id = poseidon_hash_span([goblin_count, GOBLIN].span());
450- ```
451-
452- ## Upgrading Models and Data Migration
453-
454- Upgrading models is safe as long as changes don't affect the existing data layout and schema.
455-
456- ### Safe Upgrades
457-
458- Adding a new field without modifying existing ones:
459-
460- ``` cairo
461- // Original model
462- #[dojo::model]
463- struct Player {
464- #[key]
465- player_id: u64,
466- username: String,
467- score: u32,
468- }
469-
470- // Upgraded model (safe)
471- #[dojo::model]
472- struct Player {
473- #[key]
474- player_id: u64,
475- username: String,
476- score: u32,
477- level: u8, // New field
478- }
479- ```
480-
481- ### Incompatible Upgrades
482-
483- Changes that alter the existing layout will fail:
484- - Removing or reordering fields
485- - Changing field types
486- - Changing key structure
487-
488- ## Best Practices for Model Design
489-
490- ### Keep Models Small and Focused
491-
492- Follow ECS principles by keeping models small and focused on a single aspect of an entity:
493-
494- ``` cairo
495- // Good: Separate models for different aspects
496- #[dojo::model]
497- struct Health {
498- #[key]
499- id: u32,
500- health: u8,
501- }
502-
503- #[dojo::model]
504- struct Position {
505- #[key]
506- id: u32,
507- x: u32,
508- y: u32
509- }
510-
511- // Avoid: Large monolithic models
512- #[dojo::model]
513- struct Character {
514- #[key]
515- id: u32,
516- health: u8,
517- max_health: u8,
518- mana: u8,
519- max_mana: u8,
520- x: u32,
521- y: u32,
522- inventory_slots: u8,
523- // ... many more fields
524- }
525- ```
526-
527- ### Use Appropriate Types
528-
529- Choose types based on data needs:
530- - ` u8 ` for small integers (0-255)
531- - ` u16 ` , ` u32 ` , etc. for larger integers
532- - ` felt252 ` for names and identifiers
533- - Custom structs and enums for complex data
534-
535- ### Implement Validation Logic
536-
537- Use traits and assertions to validate model state:
538-
539- ``` cairo
540- fn assert_valid_health(self: @Health) {
541- assert(self.health > 0, 'Health must be positive');
542- assert(self.health <= self.max_health, 'Health cannot exceed max');
543- }
544- ```
545-
546- ### Plan for Upgrades
547-
548- Design models with future upgrades in mind:
549- - Consider which fields might need to change
550- - Use ` IntrospectPacked ` only when necessary
551- - Document expected upgrade paths
552-
553- ## Conclusion
554-
555- Models are the core of game state management in Dojo Engine, defining how data is structured and stored on Starknet. By combining models with ** entities** and ** systems** in the ** ECS** pattern, you can build dynamic, decentralized games.
556-
557- Use the examples and patterns in this guide as a starting point for your own model designs, and experiment with the different approaches to find what works best for your game's needs.
0 commit comments