Update Connection.cpp
[KDIS.git] / KDIS / Examples / Extending / SetDataPDU / KDIS.cpp
blobe6adf43a2a496f85d92c2a553f003b663273d837
1 /**********************************************************************
2 The following UNLICENSE statement applies to this example.
4 This is free and unencumbered software released into the public domain.
6 Anyone is free to copy, modify, publish, use, compile, sell, or
7 distribute this software, either in source code form or as a compiled
8 binary, for any purpose, commercial or non-commercial, and by any
9 means.
11 In jurisdictions that recognize copyright laws, the author or authors
12 of this software dedicate any and all copyright interest in the
13 software to the public domain. We make this dedication for the benefit
14 of the public at large and to the detriment of our heirs and
15 successors. We intend this dedication to be an overt act of
16 relinquishment in perpetuity of all present and future rights to this
17 software under copyright law.
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 OTHER DEALINGS IN THE SOFTWARE.
27 For more information, please refer to <http://unlicense.org/>
28 *********************************************************************/
30 /*********************************************************************
31 For Further Information on KDIS:
32 http://p.sf.net/kdis/UserGuide
35 Example created by request: https://sourceforge.net/p/kdis/discussion/879756/thread/89a6e27d/
37 *********************************************************************/
39 #include <iostream>
40 #include "KDIS/Extras/PDU_Factory.h"
41 #include "KDIS/DataTypes/VariableDatum.h"
42 #include "KDIS/DataTypes/EntityIdentifier.h"
43 #include "KDIS/DataTypes/WorldCoordinates.h"
44 #include "KDIS/PDU/Simulation_Management/Set_Data_PDU.h"
46 using namespace std;
47 using namespace KDIS;
48 using namespace DATA_TYPE;
49 using namespace PDU;
50 using namespace UTILS;
52 // An example custom Variable Datum that contains a Entity ID and World Coordinates Record
53 class TargetPosition : public VariableDatum
55 private:
57 // Entity ID
58 EntityIdentifier m_EntID;
60 // Our target position
61 WorldCoordinates m_worldCoords;
63 KUINT16 m_ui16padding;
65 public:
67 // Ctor
68 TargetPosition( EntityIdentifier id, WorldCoordinates wc ) :
69 m_EntID( id ),
70 m_worldCoords( wc ),
71 m_ui16padding( 0 )
73 m_ui32DatumID = 12345; // Our DatumID. Pick something to use that is not already in the DatumID enum.
75 // Add the length of our fields on
76 m_ui32DatumLength = EntityIdentifier::ENTITY_IDENTIFER_SIZE * 8; // The Datum length is the size in BITS of our custom data
77 m_ui32DatumLength += WorldCoordinates::WORLD_COORDINATES_SIZE * 8;
80 // Ctor
81 TargetPosition( KDataStream & stream )
83 Decode( stream );
86 virtual ~TargetPosition()
90 virtual KString GetAsString() const
92 KStringStream ss;
94 ss << "This is our custom VariableDatum!!!!\n"
95 << m_EntID.GetAsString()
96 << m_worldCoords.GetAsString();
98 return ss.str();
101 // Our custom decode function.
102 virtual void Decode( KDataStream & stream )
104 // Decode the standard variable datum fields
105 stream >> m_ui32DatumID
106 >> m_ui32DatumLength;
108 // Now decode our 'extra' fields.
109 stream >> KDIS_STREAM m_EntID
110 >> KDIS_STREAM m_worldCoords
111 >> m_ui16padding; // The variable datum needs to be padded to a 64 bit boundary, with our 2 new fields the total size is 38 bytes, we need 2 more bytes to be on a 64 bit boundary(40).
114 virtual void Encode( KDataStream & stream ) const
116 // Encode the standard variable datum fields
117 stream << m_ui32DatumID
118 << m_ui32DatumLength;
120 // Now encode our 'extra' fields.
121 stream << KDIS_STREAM m_EntID
122 << KDIS_STREAM m_worldCoords
123 << m_ui16padding; // The variable datum needs to be padded to a 64 bit boundary, with our 2 new fields the total size is 38 bytes, we need 2 more bytes to be on a 64 bit boundary(40).
128 // Our decoder class. This tells KDIS how to decode a specific DatumID. So when the DatumID is 12345 we want to create a TargetPositionRecord
130 class TargetPositionDecoderClass : public FactoryDecoder<VariableDatum>
132 public:
134 TargetPositionDecoderClass(){};
136 ~TargetPositionDecoderClass(){};
138 // This is our factory decode function, we do the decoding for KDIS in here.
139 virtual VariableDatum * FactoryDecode( KINT32 EnumVal, KDataStream & stream )
141 // This should allways return a new data type, however you can return NULL.
142 if( EnumVal == 12345 )
144 return new TargetPosition( stream );
146 else return 0;
150 int main()
154 // 1
155 // Register our factory decode function, KDIS will use this decoder when it encounters a VariableDatum record that has this DatumID
156 VariableDatum::RegisterFactoryDecoder( 12345, VariableDatum::FacDecPtr( new TargetPositionDecoderClass ) );
158 // 2
159 // Create an instance of our data type.
160 TargetPosition * pTargetPos = new TargetPosition( EntityIdentifier( 1, 2, 3 ), WorldCoordinates( 3, 2, 1 ) );
162 // 3
163 // Now create a PDU that uses this data type and add it like normal.
164 Set_Data_PDU ourPDU;
165 ourPDU.AddVariableDatum( pTargetPos );
167 // 4
168 // Encode the PDU.
169 KDataStream stream = ourPDU.Encode();
171 // 5
172 // Lets skip actually sending this data over the network in order to keep things simple..
175 // 6
176 // Now decode the PDU as if we have just received it from the network.
177 PDU_Factory pduFact;
178 unique_ptr<Header> pdu = pduFact.Decode( stream );
180 if( pdu.get() )
182 // Here we should see that our variable datum has been correctly decoded.
183 cout << pdu->GetAsString() << endl;
185 // Lets get the decoded class
186 Set_Data_PDU * ourRecPDU = ( Set_Data_PDU * )pdu.get();
188 // Get the first and only item.
189 VarDtmPtr pVd = ourRecPDU->GetVariableDatum()[0];
191 // Now up cast so we get our data type.
192 TargetPosition * pMyRecvTargetPos = dynamic_cast<TargetPosition*>( ( VariableDatum * )pVd );
194 if( pMyRecvTargetPos )
196 cout << "Ta da!, we got the custom data class back out!" << endl;
199 else
201 cout << "Something went horribly wrong!" << endl;
204 catch( exception & e )
206 cout << e.what() << endl;
209 // 7
210 // Now we should clean up memory. Our decoder will not be deleted unless we call ClearFactoryDecoders.
211 VariableDatum::ClearFactoryDecoders();
213 return 0;