CustomType problem

xuelihong797998
edited September 2013 in Native
I have defined a CustomType like demo advanced:

[code2=cpp]class ctVector3fFactory : public ExitGames::Common::CustomTypeFactory<1>
{
public:
ExitGames::Common::CustomTypeFactory<1>* copyFactory(void) const;
void destroyFactory(void);

ExitGames::Common::CustomType<1>* create(short amount) const;
ExitGames::Common::CustomType<1>* copy(const ExitGames::Common::CustomType<1>* pToCopy, short amount) const;
void destroy(const ExitGames::Common::CustomType<1>* pToDestroy) const;
unsigned int sizeOf(void) const;
};[/code2]

[code2=cpp]class ctVector3f : public ExitGames::Common::CustomType<1>
{
typedef ExitGames::Common::CustomType<1> super;

public:
ctVector3f(void);
ctVector3f(float fx, float fy, float fz);
ctVector3f(const ctVector3f& toCopy);
~ctVector3f(void);
ctVector3f& operator=(const ctVector3f& toCopy);

void cleanup(void);
bool compare(const ExitGames::Common::CustomTypeBase& other) const;
void duplicate(ExitGames::Common::CustomTypeBase* const retVal) const;
void deserialize(const nByte* const pData, short length);
short serialize(nByte* const retVal) const;
ExitGames::Common::JString& toString(ExitGames::Common::JString& retStr, bool withTypes=false) const;

protected:
float x;
float y;
float z;
};[/code2]

[code2=cpp]ExitGames::Common::CustomTypeFactory<1>* ctVector3fFactory::copyFactory(void) const
{
return new ctVector3fFactory(*this);
}
void ctVector3fFactory::destroyFactory(void)
{
delete this;
}
ExitGames::Common::CustomType<1>* ctVector3fFactory::create(short amount) const
{
return new ctVector3f[amount];
}
ExitGames::Common::CustomType<1>* ctVector3fFactory::copy(const ExitGames::Common::CustomType<1>* pToCopy, short amount) const
{
ctVector3f* pRetVal = static_cast<ctVector3f*>(create(amount));
for(short i=0; i<amount; i++)
pRetVal = static_cast<const ctVector3f*>(pToCopy);
return pRetVal;
}
void ctVector3fFactory::destroy(const ExitGames::Common::CustomType<1>* pToDestroy) const
{
delete[] (ctVector3f*)pToDestroy;
}
unsigned int ctVector3fFactory::sizeOf(void) const
{
return sizeof(ctVector3f);
}[/code2]

[code2=cpp]ctVector3f::ctVector3f(void)
{
}
ctVector3f::ctVector3f(float fx, float fy, float fz)
{
x = fx;
y = fy;
z = fz;
}
ctVector3f::ctVector3f(const ctVector3f& toCopy)
: super()
{
x = toCopy.x;
y = toCopy.y;
z = toCopy.z;
}
ctVector3f::~ctVector3f(void)
{
}
ctVector3f& ctVector3f::operator=(const ctVector3f& toCopy)
{
x = toCopy.x;
y = toCopy.y;
z = toCopy.z;
return *this;
}
void ctVector3f::cleanup(void)
{
}
bool ctVector3f::compare(const ExitGames::Common::CustomTypeBase& other) const
{
return typeid(*this) == typeid(other) && x == ((ctVector3f&)other).x && y == ((ctVector3f&)other).y && z == ((ctVector3f&)other).z;
}
void ctVector3f::duplicate(ExitGames::Common::CustomTypeBase* const pRetVal) const
{
*reinterpret_cast<ctVector3f*>(pRetVal) = *this;
}
void ctVector3f::deserialize(const nByte* const pData, short length)
{
if(length!=12)
return; // something went wrong
const float* pfData = (float*)pData;
x = pData[0];
y = pData[1];
z = pData[2];
}
short ctVector3f::serialize(nByte* const pRetVal) const
{
if(pRetVal)
{
float* pfRetVal = (float*)pRetVal;
pfRetVal[0] = this->x;
pfRetVal[1] = this->y;
pfRetVal[2] = this->z;
}
return 12;
}
ExitGames::Common::JString& ctVector3f::toString(ExitGames::Common::JString& retStr, bool withTypes) const
{
return retStr = ExitGames::Common::JString(L"<") + (withTypes?L"("+EG_STR_FLOAT+L")":L"") + x + L", " + (withTypes?L"("+EG_STR_FLOAT+L")":L"") + y + L", " + (withTypes?L"("+EG_STR_FLOAT+L")":L"") + z + L">";
}[/code2]

Then I send a ctVector3f object to server, the code like:

[code2=cpp]ctVector3f pos(posTo.x,posTo.y,posTo.z);

OperationRequestParameters params;
params.put( static_cast<const nByte>(Robot::ParameterCode::Position), ValueObject<ctVector3f>(pos) );
params.put( static_cast<const nByte>(Robot::ParameterCode::MovingState), ValueObject<byte>(moveState) );
if ( direction != 0.f )
params.put( static_cast<const nByte>(Robot::ParameterCode::Direction), ValueObject<float>(direction) );

OperationRequest opRequest(OperationCode_CMG::PlayerMoveStateChange);
opRequest.setParameters( params );

m_LitePeer->opCustom( opRequest, sendReliable );[/code2]

Then the server report an error:
2013-08-23 14:17:53,790 [10] WARN Photon.SocketServer.PeerBase - Disconnecting peer 11: Unexpected data received

When the client send the ctVector3f object, I find the function ctVector3f::serialize has been called three time, first and second called that the param of pRetVa is 0, the third call than is not 0.

Comments

  • I have edited your post to surround the code with code2=cpp tags for better readability.

    serialize() will not only get called for actual serialization, but also to determine how big the serialization-result will be. For that purpose it is called with a NULL-pointer as argument, so that the serialize()-implementation know, that it only should return the size and doesn't have to do the actual work (depending on the complexity of the custom type this may make a huge difference in how expensive that call to serialize() is).

    Have you also implemented that custom type on the server side? If not, then you can only use it for operations in which the server does not attempt to deserialize it, otherwise it will stumble across an unknown custom type and throw an unexpected data exception.

    You also have to register the custom type, that you have implemented on the client side, prior to using it:
    In the constructor of the class, of which m_LitePeer is a member, you should add these lines:
    [code2=cpp]ctVector3fFactory customTypeFactory;
    ctVector3f::constructClass(customTypeFactory);[/code2]
    and in the destructor you should add:
    [code2=cpp]ctVector3f::deconstructClass();[/code2]
  • I have registered the ctVector3f already, but the result have not change.
    I forget tell that the server is designed by C# and Photon.The server have a Vector3f class:
    [code2=csharp]public class Vector3f
    {
    public float x { get; set; }
    public float y { get; set; }
    public float z { get; set; }
    }[/code2]
    And in the application initialize function, they have registered the Vector3f by "Photon.SocketServer.Protocol.TryRegisterCustomType" function.
  • I have just tested your custom type implementation by sending it with opRaiseEvent() from one client to another in demo_advanced (I have changed its typecode from 1 to 2 to not let it collide with SampleCustomType) and it works just fine for me after I have also added the code from my my previous post (ctVector3fFactory customTypeFactory; ctVector3f::constructClass(customTypeFactory);).
    The only issue, that I have had with your ctVector3f implementation, is, that it has a bug in deserialize():
    [code2=cpp]const float* pfData = (float*)pData;
    x = pData[0];
    y = pData[1];
    z = pData[2];[/code2]
    That code accesses pData, but should of course instead access pfData.

    Aside from that minor bug its working like a charm for me.

    Does it work for you, if you send the custom type with opRaiseEvent()? If yes, then it has to be an issue with the server side code.
    Could you share your related server side code, please?
  • Yes, please let us see the server side code.

    You need to write a Serialize / Deserialize method, which is passed into "TryRegisterCustomType", like in the code below.

    [code2=csharp]public class MyApplication : ApplicationBase
    {
    private byte myCustomTypeCode = 1;

    private void MySetup()
    {
    Protocol.TryRegisterCustomType(typeof(MyCustomType), myCustomTypeCode, MyCustomType.Serialize, MyCustomType.Deserialize);
    }
    }[/code2]

    [code2=csharp]public class MyCustomType
    {
    public byte Id { get; set; }

    public static object Deserialize(byte[] data)
    {
    var result = new MyCustomType();
    result.Id = data[0];
    return result;
    }

    public static byte[] Serialize(object customType)
    {
    var c = (MyCustomType)customType;
    return new byte[] { c.Id };
    }
    }[/code2]
  • the problen has been solved.The bug is that the typeCode of ctVector3f is 1, but our server TryRegisterCustomType the param typeCode is 'v'.
  • Great you have found it. Thanks for letting us know.