The goal of this project is to create a database abstraction layer for Arma 3 (2 as well) to allow saving of objects from Arma 3 in a database with ease as well as loading those objects from that database and ultimately manipulating that data at the C# level.
Potential users may only need to write an apropriate data model in C# for their use case and make that compatible with an Arma3 script. Control over what fields are being considered is being facilitated by attributes.
The project consists of these major components:
- Modified version of Arma2Net: https://github.com/ScottNZ/Arma2NET
- Marshalling from a nested array generated by an Arma3 SQF-Script to a C# class hierachy
- Mapping of those objects to an Entity Framework 6 based data model (Mapping w/ AutoMapper: https://github.com/AutoMapper/AutoMapper) which takes care of the database operations
- Marshalling from the data model back to a nested array notation wrapped as a string ready for Arma3 to consume
- Generation/Consumption of nested SQF arrays within the game is done with heavily modified scripts originally created by aeroson (http://www.armaholic.com/page.php?id=18967). The modified and usually latest versions can be found here: https://github.com/Rusk85/A3Wasteland_CLA_basedOn_404.Chernarus
At this point input and output marshalling are functional which means a SQF-String is being consumed on the input side and marshalled into a class hierarchy representing a player with a complete loadout set. That hierachy is then mapped to the Entity Framework model layer - the same hierachy as DTOs essentially - which in turn saves that loadout to the underlying database. When requesting output the data layer delivers a particular loadout set which is then being mapped back to the player class hierachy and then marshalled into its original input representation. Input and Output strings are not fully equal but have minor deviations. This is by design and does not mean any loss of information.
This is what an example SQF-String at the input side looks like: static string test_target = @"[[""SAVE""],[""Rusk"",""76561197964280320""],[""srifle_DMR_01_MRCO_pointer_F"",[""Single""]],[[[""AssignableItem"",[""ItemMap""]],[""AssignableItem"",[""ItemCompass""]],[""AssignableItem"",[""ItemWatch""]],[""AssignableItem"",[""H_MilCap_mcamo""]],[""AssignableItem"",[""G_Tactical_Black""]]],[""srifle_DMR_01_MRCO_pointer_F"",["""",""acc_pointer_IR"",""optic_MRCO""],[""10Rnd_762x51_Mag"",10]],[""hgun_Rook40_snds_F"",[""muzzle_snds_L"","""",""""],[""16Rnd_9x21_Mag"",16]],[""launch_O_Titan_short_F"",["""","""",""""],[""Titan_AT"",1]],[""U_B_CombatUniform_mcam"",[[""Magazine"",[""10Rnd_762x51_Mag"",8]],[""Magazine"",[""16Rnd_9x21_Mag"",16]],[""Magazine"",[""16Rnd_9x21_Mag"",16]],[""Magazine"",[""10Rnd_762x51_Mag"",8]]]],[""V_BandollierB_rgr"",[""SmokeShellPurple""]],[""B_Carryall_cbr"",[[""Magazine"",[""Titan_AT"",1]]]]]]";
After storing and retrieving it from the database and bringing it back into its original form ready for Arma to consume this is what is looks like: [[],["Rusk","76561197964280320"],["srifle_DMR_01_MRCO_pointer_F",["Single"]],[[["AssignableItem",["ItemMap"]],["AssignableItem",["ItemCompass"]],["AssignableItem",["ItemWatch"]],["AssignableItem",["H_MilCap_mcamo"]],["AssignableItem",["G_Tactical_Black"]]],["srifle_DMR_01_MRCO_pointer_F",["acc_pointer_IR","optic_MRCO"],["Magazine",["10Rnd_762x51_Mag","10"]]],["hgun_Rook40_snds_F",["muzzle_snds_L"],["Magazine",["16Rnd_9x21_Mag","16"]]],["launch_O_Titan_short_F",[],["Magazine",["Titan_AT","1"]]],["U_B_CombatUniform_mcam",[["Magazine",["10Rnd_762x51_Mag","8"]],["Magazine",["16Rnd_9x21_Mag","16"]],["Magazine",["16Rnd_9x21_Mag","16"]],["Magazine",["10Rnd_762x51_Mag","8"]]]],["V_BandollierB_rgr",[["Item",["SmokeShellPurple"]]]],["B_Carryall_cbr",[["Magazine",["Titan_AT","1"]]]]]]