1/*
2 * Copyright 2018 Dan Field. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17import 'package:flat_buffers/flat_buffers.dart' as fb;
18import './monster_my_game.sample_generated.dart' as myGame;
19
20// Example how to use FlatBuffers to create and read binary buffers.
21
22void main() {
23  builderTest();
24  objectBuilderTest();
25}
26
27void builderTest() {
28  final builder = new fb.Builder(initialSize: 1024);
29  final int weaponOneName = builder.writeString("Sword");
30  final int weaponOneDamage = 3;
31
32  final int weaponTwoName = builder.writeString("Axe");
33  final int weaponTwoDamage = 5;
34
35  final swordBuilder = new myGame.WeaponBuilder(builder)
36    ..begin()
37    ..addNameOffset(weaponOneName)
38    ..addDamage(weaponOneDamage);
39  final int sword = swordBuilder.finish();
40
41  final axeBuilder = new myGame.WeaponBuilder(builder)
42    ..begin()
43    ..addNameOffset(weaponTwoName)
44    ..addDamage(weaponTwoDamage);
45  final int axe = axeBuilder.finish();
46
47  // Serialize a name for our monster, called "Orc".
48  final int name = builder.writeString('Orc');
49
50  // Create a list representing the inventory of the Orc. Each number
51  // could correspond to an item that can be claimed after he is slain.
52  final List<int> treasure = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
53  final inventory = builder.writeListUint8(treasure);
54  final weapons = builder.writeList([sword, axe]);
55
56  // Struct builders are very easy to reuse.
57  final vec3Builder = new myGame.Vec3Builder(builder);
58
59  vec3Builder.finish(4.0, 5.0, 6.0);
60  vec3Builder.finish(1.0, 2.0, 3.0);
61  // Set his hit points to 300 and his mana to 150.
62  final int hp = 300;
63  final int mana = 150;
64
65  final monster = new myGame.MonsterBuilder(builder)
66    ..begin()
67    ..addNameOffset(name)
68    ..addInventoryOffset(inventory)
69    ..addWeaponsOffset(weapons)
70    ..addEquippedType(myGame.EquipmentTypeId.Weapon)
71    ..addEquippedOffset(axe)
72    ..addHp(hp)
73    ..addMana(mana)
74    ..addPos(vec3Builder.finish(1.0, 2.0, 3.0))
75    ..addColor(myGame.Color.Red);
76
77  final int monsteroff = monster.finish();
78  final buffer = builder.finish(monsteroff);
79  if (verify(buffer)) {
80    print(
81        "The FlatBuffer was successfully created with a builder and verified!");
82  }
83}
84
85void objectBuilderTest() {
86  // Create the builder here so we can use it for both weapons and equipped
87  // the actual data will only be written to the buffer once.
88  var axe = new myGame.WeaponObjectBuilder(name: 'Axe', damage: 5);
89
90  var monsterBuilder = new myGame.MonsterObjectBuilder(
91    pos: new myGame.Vec3ObjectBuilder(x: 1.0, y: 2.0, z: 3.0),
92    mana: 150,
93    hp: 300,
94    name: 'Orc',
95    inventory: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
96    color: myGame.Color.Red,
97    weapons: [new myGame.WeaponObjectBuilder(name: 'Sword', damage: 3), axe],
98    equippedType: myGame.EquipmentTypeId.Weapon,
99    equipped: axe,
100  );
101
102  var buffer = monsterBuilder.toBytes();
103
104  // We now have a FlatBuffer we can store on disk or send over a network.
105
106  // ** file/network code goes here :) **
107
108  // Instead, we're going to access it right away (as if we just received it).
109  if (verify(buffer)) {
110    print(
111        "The FlatBuffer was successfully created with an object builder and verified!");
112  }
113}
114
115bool verify(List<int> buffer) {
116  // Get access to the root:
117  var monster = new myGame.Monster(buffer);
118
119  // Get and test some scalar types from the FlatBuffer.
120  assert(monster.hp == 80);
121  assert(monster.mana == 150); // default
122  assert(monster.name == "MyMonster");
123
124  // Get and test a field of the FlatBuffer's `struct`.
125  var pos = monster.pos;
126  assert(pos != null);
127  assert(pos.z == 3.0);
128
129  // Get a test an element from the `inventory` FlatBuffer's `vector`.
130  var inv = monster.inventory;
131  assert(inv != null);
132  assert(inv.length == 10);
133  assert(inv[9] == 9);
134
135  // Get and test the `weapons` FlatBuffers's `vector`.
136  var expected_weapon_names = ["Sword", "Axe"];
137  var expected_weapon_damages = [3, 5];
138  var weps = monster.weapons;
139  for (int i = 0; i < weps.length; i++) {
140    assert(weps[i].name == expected_weapon_names[i]);
141    assert(weps[i].damage == expected_weapon_damages[i]);
142  }
143
144  // Get and test the `Equipment` union (`equipped` field).
145  assert(monster.equippedType.value == myGame.EquipmentTypeId.Weapon.value);
146  assert(monster.equippedType == myGame.EquipmentTypeId.Weapon);
147
148  assert(monster.equipped is myGame.Weapon);
149  var equipped = monster.equipped as myGame.Weapon;
150  assert(equipped.name == "Axe");
151  assert(equipped.damage == 5);
152
153  print(monster);
154  return true;
155}
156