Skip to content

Chapter 6: Data Mapping

ketoo edited this page May 9, 2020 · 3 revisions

In NoahGameFrame's world, we have an advanced data mapping system which relates to the logic class. Do you remember these fields of the property system?

  • Id: The prop's name, for example, DogName and HP.
  • Cache: True: Save this prop into Redis
  • Desc: A short description for this prop, for the designer to easily remember the meaning of this prop.
  • Force:
  • Private: True: Update data to the client when property changed.
  • Public: True: Update data to the clients who near the object (in the view area) when the data changed.
  • Ref: True: Reference to another property (please set to false before you know NF deeply)
  • Save: True: Save this prop to Mysql or other databases.
  • Type: The type of this prop, such as int, float, string, object, vector2, vector3
  • Upload: Allow the client to upload prop's data to the server and override the server's data.

Yes, how we data mapping dependence these fields especial the fields Type, Private and Public.

Normally, all complex data struct come from the base data type such as int, float(double), string, vector2, and vector3. Of course, we added a class name NFGUID in NoahGameFrame as the object's identity.

So, we just support six types data as below:

////////////////////////BaseCommon/////////////////////////////
message PropertyInt//The base protocol can not be transfer directly
{ 
    required bytes     property_name = 1;
    required int64      data = 2;
}

message PropertyFloat//The base protocol cannot be transfer directly
{ 
    required bytes     property_name = 1;
    required float      data = 2;
}

message PropertyString//The base protocol cannot be transfer directly
{ 
    required bytes     property_name = 1;
    required bytes     data = 2;
}

message PropertyObject//The base protocol cannot be transfer directly
{ 
    required bytes     property_name = 1;
    required Ident      data = 2;
}

message PropertyVector2//The base protocol cannot be transfer directly
{ 
    required bytes     property_name = 1;
    required Vector2      data = 2;
}

message PropertyVector3//The base protocol cannot be transfer directly
{ 
    required bytes     property_name = 1;
    required Vector3      data = 2;
}

//////////////////

message ObjectPropertyInt
{
    required Ident  player_id = 1;
    repeated PropertyInt	property_list = 2;
} 

message ObjectPropertyFloat
{
    required Ident player_id = 1;
    repeated PropertyFloat property_list = 2;
} 

message ObjectPropertyString
{
    required Ident player_id = 1;
    repeated PropertyString property_list = 2;
} 

message ObjectPropertyObject
{
    required Ident player_id = 1;
    repeated PropertyObject property_list = 2;
}

message ObjectPropertyVector2
{
    required Ident player_id = 1;
    repeated PropertyVector2 property_list = 2;
}

message ObjectPropertyVector3
{
    required Ident player_id = 1;
    repeated PropertyVector3 property_list = 2;
}

Now we have the data struct designed by Protocol-buf, if we want to send some message we can send these structs to the clients. For example, we want to send the "Level" information to the client, below is the pseudocode:

  1. We would add the monitor/observer for the property named "Level"
bool NFHelloWorld2::AfterInit()
{
     NFIObject* pObject = new NFCObject(NFGUID(0, 1), pPluginManager);

    //add a property for this object, actually, this step will be done automatically by NoahGaneFrame
    pObject->GetPropertyManager()->AddProperty(pObject->Self(), "Level", TDATA_INT);
   
    //add a callback function for "Level" property
    pObject->AddPropertyCallBack("Level", this, &NFHelloWorld2::OnPropertyCallBackEvent);
    
    //set the "world" property value as 2222[than the function "HelloWorld2::OnPropertyCallBackEvent" will be called]
    pObject->SetPropertyInt("World", 2222);
}

int NFHelloWorld2::OnPropertyCallBackEvent( const NFGUID& self, const std::string& strProperty, const NFData& oldVar, const NFData& newVar)
{
    
    std::cout << "OnPropertyCallBackEvent Property: " << strProperty << " OldValue: " << oldVar.GetInt() << " NewValue: " << newVar.GetInt() << std::endl;

    return 0;
}
  1. We pack the message body as a string stream by Protocol-buf
int NFHelloWorld2::OnPropertyCallBackEvent( const NFGUID& self, const std::string& strProperty, const NFData& oldVar, const NFData& newVar)
{
    
    std::cout << "OnPropertyCallBackEvent Property: " << strProperty << " OldValue: " << oldVar.GetInt() << " NewValue: " << newVar.GetInt() << std::endl;

    NFMsg::MultiObjectPropertyList xPublicMsg;
    NFMsg::MultiObjectPropertyList xPrivateMsg;

    NFMsg::ObjectPropertyList* pPublicData = xPublicMsg.add_multi_player_property();
    NFMsg::ObjectPropertyList* pPrivateData = xPrivateMsg.add_multi_player_property();

    if (pPropertyInfo->GetPublic())
    {
        NFMsg::PropertyInt* pDataInt = pPublicData->add_property_int_list();
        pDataInt->set_property_name(pPropertyInfo->GetKey());
        pDataInt->set_data(pPropertyInfo->GetInt());
    }

    if (pPropertyInfo->GetPrivate())
    {
        NFMsg::PropertyInt* pDataInt = pPrivateData->add_property_int_list();
        pDataInt->set_property_name(pPropertyInfo->GetKey());
        pDataInt->set_data(pPropertyInfo->GetInt());
    }

    return 0;
}
  1. We send the string stream to the client by networking and the user's ID.
SendMsgPBToGate(NFMsg::EGMI_ACK_OBJECT_PROPERTY_ENTRY, xPrivateMsg, identOther);

Actually, we can add the observer for all props when a object has been created, then we just one module can help us to send the message to the clients, this data mapping.