LCOV - code coverage report
Current view: top level - lib/src - system.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 12 54 22.2 %
Date: 2022-01-24 13:22:55 Functions: 0 0 -

          Line data    Source code
       1             : import 'dart:async';
       2             : 
       3             : import 'package:uuid/uuid.dart';
       4             : 
       5             : import 'component.dart';
       6             : import 'entity.dart';
       7             : import 'extensions/extensions.dart';
       8             : import 'mixins.dart';
       9             : 
      10             : // A function that takes JSON data and returns a component.
      11             : typedef ComponentDeserializerFunction = Component? Function(Map<String, dynamic> data);
      12             : 
      13             : // A function that takes a component and returns JSON-esque data.
      14             : typedef ComponentSerializerFunction = Map<String, dynamic> Function(SerializableComponent component);
      15             : 
      16             : // A function that takes in an entity and returns JSON-esque data.
      17             : typedef EntityToJsonFunction = Map<String, dynamic> Function(Entity entity);
      18             : 
      19             : // A function that takes in JSON and returns an Entity;
      20             : typedef EntityFromJsonFunction = Entity Function(
      21             :   Map<String, dynamic> json,
      22             :   EntitySystem system,
      23             : );
      24             : 
      25             : /// This system is for keeping track of all created entities.
      26             : class EntitySystem {
      27             :   final uuid = const Uuid();
      28             : 
      29             :   // The listener that updates the public list of entities.
      30             :   late StreamSubscription _listener;
      31             : 
      32           1 :   EntitySystem() {
      33             :     // When entities updates, map over and update the public entity list.
      34           5 :     _listener = _entities.stream.listen((ents) {
      35           2 :       final list = ents.values.toList();
      36           2 :       entities.add(list);
      37             :     });
      38             :   }
      39             : 
      40             :   /// Call this to release resources and workers.
      41           0 :   void dispose() {
      42             :     /// Clear entities and cancel subscription.
      43           0 :     _listener.cancel();
      44           0 :     _entities.close();
      45           0 :     entities.close();
      46             :   }
      47             : 
      48             :   /// Remove all entities.
      49           0 :   void flush() {
      50           0 :     if (_entities.hasValue) {
      51           0 :       _entities.value.forEach((guid, e) => e.destroy());
      52           0 :       _entities.value.clear();
      53             :     }
      54             :   }
      55             : 
      56             :   /// A list of registered deserializer functions.
      57             :   List<ComponentDeserializerFunction> deserializers = [
      58             :     componentFromJson,
      59             :   ];
      60             : 
      61             :   /// A list of registered serializer functions.
      62             :   List<ComponentSerializerFunction> serializers = [
      63             :     componentToJson,
      64             :   ];
      65             : 
      66             :   /// The function called to turn an entity into JSON.
      67             :   EntityToJsonFunction entityToJsonFunction = defaultEntityToJsonFunction;
      68             : 
      69             :   /// The function called to turn JSON into an entity;
      70             :   EntityFromJsonFunction entityFromJsonFunction = defaultEntityFromJsonFunction;
      71             : 
      72             :   /// The internal registry of all created entities.
      73             :   final _entities = <String, Entity>{}.bs;
      74             : 
      75             :   /// An observable list of entities.
      76             :   final entities = <Entity>[].bs;
      77             : 
      78             :   /// Register a deserializer function.
      79           0 :   void registerDeserializer(ComponentDeserializerFunction deserializer) {
      80           0 :     if (!deserializers.contains(deserializer)) {
      81           0 :       deserializers.add(deserializer);
      82             :     }
      83             :   }
      84             : 
      85             :   /// Register a serializer function.
      86           0 :   void registerSerializer(ComponentSerializerFunction serializer) {
      87           0 :     if (!serializers.contains(serializer)) {
      88           0 :       serializers.add(serializer);
      89             :     }
      90             :   }
      91             : 
      92             :   /// The way a new entity should be created.
      93           1 :   Entity create() {
      94           3 :     final entity = Entity(uuid.v4(), this);
      95           1 :     return setEntity(entity);
      96             :   }
      97             : 
      98             :   /// Deserializing entities from JSON.
      99           0 :   Entity createFromJson(Map<String, dynamic> json) {
     100           0 :     final entity = entityFromJsonFunction(json, this);
     101           0 :     return setEntity(entity);
     102             :   }
     103             : 
     104           1 :   Entity setEntity(Entity entity) {
     105           2 :     final current = _entities.value;
     106           7 :     final newList = Map.fromIterables([...current.keys, entity.guid], [...current.values, entity]);
     107           2 :     _entities.add(newList);
     108             :     // Return the entity.
     109           4 :     return _entities.value[entity.guid]!;
     110             :   }
     111             : 
     112             :   /// Standard serializer that turns an entity into JSON.
     113           0 :   Map<String, dynamic> entityToJson(Entity entity) {
     114           0 :     return entityToJsonFunction(entity);
     115             :   }
     116             : 
     117             :   /// When an entity has been destroyed, we remove it from the list
     118             :   /// and that will automatically sync that to the observable list.
     119           0 :   void destroyed(Entity entity) {
     120           0 :     final current = _entities.value;
     121             :     // Drop the guid and remove the entity from the list.
     122           0 :     final newList = Map.fromIterables([...current.keys], [...current.values].where((e) => e != entity));
     123             :     // Set the new list.
     124           0 :     _entities.add(newList);
     125             :   }
     126             : }
     127             : 
     128             : /// Standard serializer that turns an entity into JSON.
     129           0 : Map<String, dynamic> defaultEntityToJsonFunction(Entity entity) {
     130           0 :   List<Map<String, dynamic>> componentData = [];
     131           0 :   entity.components().forEach(
     132           0 :     (type, component) {
     133           0 :       if (component is SerializableComponent) {
     134           0 :         componentData.add({'type': type.toString(), 'data': (component as SerializableComponent).toJson()});
     135             :       }
     136             :     },
     137             :   );
     138           0 :   return <String, dynamic>{
     139             :     'components': componentData,
     140             :   };
     141             : }
     142             : 
     143           0 : Entity defaultEntityFromJsonFunction(Map<String, dynamic> json, EntitySystem system) {
     144           0 :   var e = Entity(json['guid'], system);
     145           0 :   if (json['components'] != null) {
     146           0 :     final comps = json['components'] as List<dynamic>;
     147           0 :     for (var compData in comps) {
     148             :       final data = compData as Map<String, dynamic>;
     149           0 :       Component? c = componentFromJson(data);
     150             :       // if not contained in default system, check serializers.
     151             :       if (c == null) {
     152           0 :         for (var serializer in system.deserializers) {
     153           0 :           c = serializer.call(data);
     154             :         }
     155             :       }
     156             : 
     157             :       /// If we actually got a component, add it.
     158             :       if (c != null) {
     159           0 :         e += c;
     160             :       }
     161             :     }
     162             :   }
     163             : 
     164             :   return e;
     165             : }
     166             : 
     167             : /// A map of strings to types.
     168           0 : Component? componentFromJson(Map<String, dynamic> json) {
     169             :   return null;
     170             : }
     171             : 
     172           0 : Map<String, dynamic> componentToJson(SerializableComponent component) {
     173           0 :   return component.toJson();
     174             : }

Generated by: LCOV version 1.15