Пример #1
0
void ItemAttributeMgr::_SendAttributeChange(Attr attr, PyRep *oldValue, PyRep *newValue) {
    if(GetNotify() == false)
        return;

    Client *c = m_factory.entity_list.FindCharacter( item().ownerID() );
    if(c != NULL)
    {
        Notify_OnModuleAttributeChange omac;
        omac.ownerID = m_item.ownerID();
        omac.itemKey = m_item.itemID();
        omac.attributeID = attr;
        omac.time = Win32TimeNow();
        omac.oldValue = oldValue;
        omac.newValue = newValue;

        PyTuple* tmp = omac.Encode();
        c->QueueDestinyEvent(&tmp);
    }
    else
    {
        // delete the reps
        PyDecRef( oldValue );
        PyDecRef( newValue );
    }
}
Пример #2
0
bool PyCachedCall::Decode(PySubStream **in_ss)
{
    PySubStream *ss = *in_ss;    //consume
    *in_ss = NULL;

    PySafeDecRef( result );

    ss->DecodeData();
    if(ss->decoded() == NULL) {
        SysLog::Error("PyCachedCall","Unable to decode initial stream for PyCachedCall");
        PyDecRef( ss );
        return false;
    }

    if(!ss->decoded()->IsDict()) {
        SysLog::Error("PyCachedCall","Cached call substream does not contain a dict: %s", ss->decoded()->TypeString());
        PyDecRef( ss );
        return false;
    }
    PyDict *po = (PyDict *) ss->decoded();

    PyDict::const_iterator cur, end;
    cur = po->begin();
    end = po->end();
    for(; cur != end; cur++) {
        if(!cur->first->IsString())
            continue;
        PyString *key = (PyString *) cur->first;
        if( key->content() == "lret" )
            result = cur->second->Clone();
    }

    PyDecRef( ss );
    return(result != NULL);
}
Пример #3
0
void TestMarshal( const Seperator& cmd )
{
    const char* cmdName = cmd.arg( 0 ).c_str();

    DBRowDescriptor *header = new DBRowDescriptor;
    // Fill header:
    header->AddColumn( "historyDate", DBTYPE_FILETIME );
    header->AddColumn( "lowPrice", DBTYPE_CY );
    header->AddColumn( "highPrice", DBTYPE_CY );
    header->AddColumn( "avgPrice", DBTYPE_CY );
    header->AddColumn( "volume", DBTYPE_I8 );
    header->AddColumn( "orders", DBTYPE_I4 );

    CRowSet* rs = new CRowSet( &header );

    PyPackedRow* row = rs->NewRow();
    row->SetField( "historyDate", new PyLong( Win32TimeNow() ) );
    row->SetField( "lowPrice", new PyLong( 18000 ) );
    row->SetField( "highPrice", new PyLong( 19000 ) );
    row->SetField( "avgPrice", new PyLong( 18400 ) );
    row->SetField( "volume", new PyLong( 5463586 ) );
    row->SetField( "orders", new PyInt( 254 ) );

    sLog.Log( cmdName, "Marshaling..." );

    Buffer marshaled;
    bool res = MarshalDeflate( rs, marshaled );
    PyDecRef( rs );

    if( !res )
    {
        sLog.Error( cmdName, "Failed to marshal Python object." );
        return;
    }

    sLog.Log( cmdName, "Unmarshaling..." );

    PyRep* rep = InflateUnmarshal( marshaled );
    if( NULL == rep )
    {
        sLog.Error( cmdName, "Failed to unmarshal Python object." );
        return;
    }

    sLog.Success( cmdName, "Final:" );
    rep->Dump( stdout, "    " );

    PyDecRef( rep );
}
Пример #4
0
//in theory this could be written in therms of the more generic
//MulticastTarget function, but this is much more efficient.
void EntityList::Multicast( const char* notifyType, const char* idType, PyTuple** payload, NotificationDestination target, uint32 target_id, bool seq )
{
    PyTuple* p = *payload;
    *payload = NULL;

	std::list<Client*>::const_iterator cur, end;
	cur = m_clients.begin();
	end = m_clients.end();
	for(; cur != end; cur++)
    {
		switch( target )
        {
		case NOTIF_DEST__LOCATION:
			if( (*cur)->GetLocationID() != target_id )
				continue;
			break;
		case NOTIF_DEST__CORPORATION:
			if( (*cur)->GetCorporationID() != target_id )
				continue;
			break;
		}

		PyTuple* temp = new PyTuple( *p );
		(*cur)->SendNotification( notifyType, idType, &temp, seq );
	}

    PyDecRef( p );
}
Пример #5
0
PySubStream* CachedObjectMgr::LoadCachedFile(const char *obj_name)
{
    PyString *oname_str = new PyString(obj_name);
    PySubStream* ret = LoadCachedFile(oname_str, obj_name);
    PyDecRef(oname_str);
    return ret;
}
Пример #6
0
//this is sub-optimal, but it keeps things more consistent (in case StringCollapseVisitor ever gets more complicated)
bool CachedObjectMgr::SaveCachedToFile(const std::string &cacheDir, const std::string &objectID) const
{
    PyString *str = new PyString(objectID);
    bool ret = SaveCachedToFile(cacheDir, str);
    PyDecRef(str);
    return ret;
}
Пример #7
0
void UnmarshalLogText( const Seperator& cmd )
{
    const char* cmdName = cmd.arg( 0 ).c_str();

    if( 1 == cmd.argCount() )
    {
        sLog.Error( cmdName, "Usage: %s marshal-binary [marshal-binary] ...", cmdName );
        return;
    }

    for( size_t i = 1; i < cmd.argCount(); ++i )
    {
        const std::string& marshalBinaryStr = cmd.arg( i );

        Buffer marshalBinary;
        if( !PyDecodeEscape( marshalBinaryStr.c_str(), marshalBinary ) )
        {
            sLog.Error( cmdName, "Failed to decode string into binary." );
            continue;
        }

        PyRep* r = InflateUnmarshal( marshalBinary );
        if( NULL == r )
            sLog.Error( cmdName, "Failed to unmarshal binary." );
        else
        {
            sLog.Success( cmdName, "Result:" );
            r->Dump( stdout, "    " );

            PyDecRef( r );
        }
    }
}
Пример #8
0
/**
 * this function isn't used.
 */
void DBResultToIntIntlistDict( DBQueryResult &result, std::map<int32, PyRep *> &into ) {
    /* this builds a map from the int in result[0], to a list of each result[1]
     * which is has the same result[0]. This function assumes the result is
     * ORDER BY result[0]
     */
    uint32 last_key = 0xFFFFFFFF;

    PyList *l = NULL;

    DBResultRow row;
    while( result.GetRow( row ) )
    {
        uint32 k = row.GetUInt(0);
        if( k != last_key )
        {
            //watch for overwrite, no guarantee we are dealing with a key.
            std::map<int32, PyRep *>::iterator res = into.find(k);
            if( res != into.end() )
                //log an error or warning?
                PyDecRef( res->second );

            into[k] = l = new PyList();
            last_key = k;
        }

        l->AddItemInt( row.GetInt( 1 ) );
    }
}
Пример #9
0
bool CachedObjectMgr::LoadCachedFromFile(const std::string &cacheDir, const std::string &objectID)
{
    //this is sub-optimal, but it keeps things more consistent (in case StringCollapseVisitor ever gets more complicated)
    PyString *str = new PyString(objectID);
    bool ret = LoadCachedFromFile(cacheDir, str);
    PyDecRef(str);
    return ret;
}
Пример #10
0
PyObject *CachedObjectMgr::GetCachedObject(const std::string &objectID)
{
    //this is sub-optimal, but it keeps things more consistent (in case StringCollapseVisitor ever gets more complicated)
    PyString *str = new PyString( objectID );
    PyObject* obj = GetCachedObject(str);
    PyDecRef(str);
    return obj;
}
Пример #11
0
uint32 DBRowDescriptor::FindColumn( const char* name ) const
{
	uint32 cc = ColumnCount();
    PyString* stringName = new PyString( name );
    
	for( uint32 i = 0; i < cc; i++ )
    {
		if( stringName->hash() == GetColumnName( i )->hash() )
        {
            PyDecRef( stringName );
			return i;
        }
    }

    PyDecRef( stringName );
	return cc;
}
Пример #12
0
bool CachedObjectMgr::HaveCached(const std::string &objectID) const
{
    //this is very sub-optimal, but it keeps things more consistent (in case StringCollapseVisitor ever gets more complicated)
    PyString *str = new PyString( objectID );
    bool ret = HaveCached(str);
    PyDecRef(str);
    return ret;
}
Пример #13
0
PyPacket* EVEClientSession::_HandleCommand( PyRep* rep )
{
    //check if it actually is tuple
    if( !rep->IsTuple() )
    {
        sLog.Error("Network", "%s: Invalid packet during waiting for command (tuple expected).", GetAddress().c_str());
    }
    // decode
    else if( rep->AsTuple()->size() == 2 )
    {
        //QC = Queue Check
        NetCommand_QC cmd;
        if( !cmd.Decode( &rep ) )
        {
            sLog.Error("Network", "%s: Failed to decode 2-arg command.", GetAddress().c_str());
        }
        else
        {
            sLog.Debug("Network", "%s: Got Queue Check command.", GetAddress().c_str());

            //they return position in queue
            PyRep* rsp = new PyInt( _GetQueuePosition() );
            mNet->QueueRep( rsp );
            PyDecRef( rsp );

            //now reset connection
            Reset();
        }
    }
    else if( rep->AsTuple()->size() == 3 )
    {
        //this is sent when client is logging in
        NetCommand_VK cmd;
        if( !cmd.Decode( &rep ) )
        {
            sLog.Error("Network", "%s: Failed to decode 3-arg command.", GetAddress().c_str());
        }
        else
        {
            sLog.Debug("Network", "%s: Got VK command, vipKey=%s.", GetAddress().c_str(), cmd.vipKey.c_str());

            if( _VerifyVIPKey( cmd.vipKey ) )
                mPacketHandler = &EVEClientSession::_HandleCrypto;
        }
    }
    else
    {
        _log(NET__PRES_ERROR, "%s: Received invalid command packet:", GetAddress().c_str());
        rep->Dump(NET__PRES_ERROR, "  ");
    }

    // recurse
    return PopPacket();
}
Пример #14
0
void ObjCacheService::PrimeCache()
{
    CacheKeysMapConstItr cur, end;
    cur = m_cacheKeys.begin();
    end = m_cacheKeys.end();
    for(; cur != end; cur++)
    {
        PyString* str = new PyString( cur->first );
        _LoadCachableObject( str );
        PyDecRef( str );
    }
}
Пример #15
0
/*
 * EVEAdvancedAttributeMgr
 */
void EVEAdvancedAttributeMgr::EncodeAttributes(std::map<int32, PyRep *> &into) const {
    // integers first
    {
        std::map<Attr, int_t>::const_iterator cur, end;
        cur = m_ints.begin();
        end = m_ints.end();
        for(; cur != end; cur++) {
            if(into.find(cur->first) != into.end())
                PyDecRef( into[cur->first] );
            into[cur->first] = PyGet(cur->first);
        }
    }
    // then reals
    {
        std::map<Attr, real_t>::const_iterator cur, end;
        cur = m_reals.begin();
        end = m_reals.end();
        for(; cur != end; cur++) {
            if(into.find(cur->first) != into.end())
                PyDecRef( into[cur->first] );
            into[cur->first] = PyGet(cur->first);
        }
    }
}
Пример #16
0
void CachedObjectMgr::UpdateCacheFromSS(const std::string &objectID, PySubStream **in_cached_data) {
    PyCachedObjectDecoder cache;
    if(!cache.Decode(in_cached_data)) {
        _log(SERVICE__ERROR, "Failed to decode cache stream");
        return;
    }

    PyString* str = new PyString( objectID );

    PyBuffer* buf = cache.cache->data();
    PyIncRef( buf );

    _UpdateCache(str, &buf);

    PyDecRef( str );
}
Пример #17
0
PyDict *DBResultToPackedRowDict( DBQueryResult &result, uint32 key_index )
{
    DBRowDescriptor *header = new DBRowDescriptor( result );

    PyDict *res = new PyDict();

    DBResultRow row;
    for( uint32 i = 0; result.GetRow( row ); i++ )
    {
        res->SetItem( DBColumnToPyRep(row, key_index), CreatePackedRow( row, header ) );
        PyIncRef( header );
    }

    PyDecRef( header );
    return res;
}
Пример #18
0
PyList *DBResultToPackedRowList( DBQueryResult &result )
{
    DBRowDescriptor *header = new DBRowDescriptor( result );

    PyList *res = new PyList( result.GetRowCount() );

    DBResultRow row;
    for( uint32 i = 0; result.GetRow( row ); i++ )
    {
        res->SetItem( i, CreatePackedRow( row, header ) );
        PyIncRef( header );
    }

    PyDecRef( header );
    return res;
}
Пример #19
0
void EntityList::Multicast(const char *notifyType, const char *idType, PyTuple **in_payload, const MulticastTarget &mcset, bool seq)
{
	// consume payload
	PyTuple *payload = *in_payload;
	*in_payload = NULL;

	//cache all these locally to avoid calling empty all the time.
	const bool chars_empty = mcset.characters.empty();
	const bool locs_empty = mcset.locations.empty();
	const bool corps_empty = mcset.corporations.empty();

	if( !chars_empty || !locs_empty || !corps_empty )
	{
		std::list<Client *>::const_iterator cur, end;
		cur = m_clients.begin();
		end = m_clients.end();
		for(; cur != end; cur++)
		{
			if(	  !chars_empty
			     && mcset.characters.find((*cur)->GetCharacterID()) != mcset.characters.end() )
			{
				//found, carry on...
			}
			else if(   !locs_empty
					  && mcset.locations.find((*cur)->GetLocationID()) != mcset.locations.end() )
			{
				//found, carry on...
			}
			else if(   !corps_empty
					  && mcset.corporations.find((*cur)->GetCorporationID()) != mcset.corporations.end() )
			{
				//found, carry on...
			}
			else
			{
				//not found in any of the above sets.
				continue;
			}

			PyTuple *temp = new PyTuple( *payload );
			(*cur)->SendNotification( notifyType, idType, &temp, seq );
			
		}
	}

	PyDecRef( payload );
}
Пример #20
0
void EVEClientSession::FastQueuePacket( PyPacket** p )
{
    if(p == NULL || *p == NULL)
        return;

    PyRep* r = (*p)->Encode();
    // maybe change PyPacket to a object with a reference..
    SafeDelete( *p );
    if( r == NULL )
    {
        sLog.Error("Network", "%s: Failed to encode a Fast queue packet???", GetAddress().c_str());
        return;
    }

    mNet->QueueRep( r );
    PyDecRef( r );
}
Пример #21
0
void EVEClientSession::Reset()
{
    mPacketHandler = NULL;

    if( GetState() != TCPConnection::STATE_CONNECTED )
        // Connection has been lost, there's no point in reset
        return;

    VersionExchangeServer version;
    _GetVersion( version );

    PyRep* r = version.Encode();
    mNet->QueueRep( r );
    PyDecRef( r );

    mPacketHandler = &EVEClientSession::_HandleVersion;
}
Пример #22
0
void ObjCacheService::InsertCacheHints(hintSet hset, PyDict *into) {
    const char *const *objects = NULL;
    uint32 object_count = 0;
    switch(hset) {
    case hLoginCachables:
        objects = LoginCachableObjects;
        object_count = LoginCachableObjectCount;
        break;
    case hCharCreateCachables:
        objects = CharCreateCachableObjects;
        object_count = CharCreateCachableObjectCount;
        break;
    case hAppearanceCachables:
        objects = AppearanceCachableObjects;
        object_count = AppearanceCachableObjectCount;
        break;
    case hCharCreateNewExtraCachables:
        objects = CharCreateNewExtraCachableObjects;
        object_count = CharCreateNewExtraCachableObjectCount;
        break;
    }
    if(objects == NULL)
        return;
    uint32 r;
    std::map<std::string, std::string>::const_iterator res;
    for(r = 0; r < object_count; r++) {
        //find the dict key to use for this object
        res = m_cacheKeys.find(objects[r]);
        if(res == m_cacheKeys.end()) {
            _log(SERVICE__ERROR, "Unable to find cache key for object ID '%s', skipping.", objects[r]);
            continue;
        }

        //get the hint
        PyString* str = new PyString( objects[r] );
        PyRep *cache_hint = GetCacheHint( str );
        PyDecRef( str );

        if(cache_hint == NULL)
            continue;	//print already done.

        into->SetItemString(res->second.c_str(), cache_hint);
    }
}
Пример #23
0
void TargetManager::QueueTBDestinyUpdate( PyTuple** up_in ) const
{
    PyTuple* up = *up_in;
    *up_in = NULL;    //could optimize out one of the Clones in here...

    PyTuple* up_dup = NULL;

    std::map<SystemEntity*, TargetedByEntry*>::const_iterator cur, end;
    cur = m_targetedBy.begin();
    end = m_targetedBy.end();
    for(; cur != end; ++cur)
    {
        if( NULL == up_dup )
            up_dup = new PyTuple( *up );

        cur->first->QueueDestinyUpdate( &up_dup );
        //they may not have consumed it (NPCs for example), so dont re-dup it in that case.
    }

    PySafeDecRef( up_dup );
    PyDecRef( up );
}
Пример #24
0
void ClientSession::_Set( const char* name, PyRep* value )
{
    PyTuple* v = _GetValueTuple( name );
    if( v == NULL )
    {
        v = new PyTuple( 2 );
        v->SetItem( 0, new PyNone );
        v->SetItem( 1, new PyNone );
        mSession->SetItemString( name, v );
    }

    PyRep* current = v->GetItem( 1 );
    if( value->hash() != current->hash() )
    {
        v->SetItem( 1, value );

        mDirty = true;
    }
    else
    {
        PyDecRef( value );
    }
}
Пример #25
0
//send a destiny event to everybody in the bubble.
//assume that static entities are also not interested in destiny updates.
void SystemBubble::BubblecastDestinyEvent( PyTuple** payload, const char* desc ) const
{
    PyTuple* up = *payload;
    *payload = NULL;	//could optimize out one of the Clones in here...

    PyTuple* up_dup = NULL;

    std::set<SystemEntity *>::const_iterator cur, end, tmp;
    cur = m_dynamicEntities.begin();
    end = m_dynamicEntities.end();
    for(; cur != end; ++cur)
    {
        if( NULL == up_dup )
            up_dup = new PyTuple( *up );

        _log( DESTINY__BUBBLE_TRACE, "Bubblecast %s event to %s (%u)", desc, (*cur)->GetName(), (*cur)->GetID() );
        (*cur)->QueueDestinyEvent( &up_dup );
        //they may not have consumed it (NPCs for example), so dont re-dup it in that case.
    }

    PySafeDecRef( up_dup );
    PyDecRef( up );
}
Пример #26
0
void CachedObjectMgr::UpdateCache(const PyRep *objectID, PyRep **in_cached_data)
{
    PyRep *cached_data = *in_cached_data;
    *in_cached_data = NULL;

    //if(is_log_enabled(SERVICE__CACHE_DUMP)) {
      //  PyLogsysDump dumper(SERVICE__CACHE_DUMP, SERVICE__CACHE_DUMP, false, true);
        //cached_data->visit(&dumper, 0);
    //}

    Buffer* data = new Buffer;
    bool res = MarshalDeflate( cached_data, *data );
	PyDecRef( cached_data );

    if( res ) {
	    PyBuffer* buf = new PyBuffer( &data );
        _UpdateCache( objectID, &buf );
    } else {
        sLog.Error( "Cached Obj Mgr", "Failed to marshal or deflate new cache object." );
    }

    SafeDelete( data );
}
Пример #27
0
ObjectCachedSessionMethodID::~ObjectCachedSessionMethodID()
{
    PyDecRef( objectID );
}
Пример #28
0
ObjectCachedMethodID::~ObjectCachedMethodID()
{
    PyDecRef( objectID );
}
Пример #29
0
PyRep *MarketDB::GetOrders( uint32 regionID, uint32 typeID )
{
    DBQueryResult res;

    PyList* tup = new PyList();

    /*DBColumnTypeMap colmap;
    colmap["volRemaining"] = DBTYPE_R8;
    colmap["price"] = DBTYPE_CY;
    colmap["issued"] = DBTYPE_FILETIME;

    colmap["orderID"] = DBTYPE_I4;
    colmap["volEntered"] = DBTYPE_I4;
    colmap["minVolume"] = DBTYPE_I4;
    colmap["stationID"] = DBTYPE_I4;
    colmap["regionID"] = DBTYPE_I4;
    colmap["solarSystemID"] = DBTYPE_I4;
    colmap["jumps"] = DBTYPE_I4;

    colmap["duration"] = DBTYPE_I2;
    colmap["typeID"] = DBTYPE_I2;
    colmap["range"] = DBTYPE_I2;

    colmap["bid"] = DBTYPE_BOOL;

    //ordering: (painstakingly determined from packets)
    DBColumnOrdering ordering;
    ordering.push_back("price");
    ordering.push_back("volRemaining");
    ordering.push_back("issued");
    ordering.push_back("orderID");
    ordering.push_back("volEntered");
    ordering.push_back("minVolume");
    ordering.push_back("stationID");
    ordering.push_back("regionID");
    ordering.push_back("solarSystemID");
    ordering.push_back("jumps");    //not working right...
    ordering.push_back("typeID");
    ordering.push_back("range");
    ordering.push_back("duration");
    ordering.push_back("bid");*/

    //query sell orders
    //TODO: consider the `jumps` field... is it actually used? might be a pain in the ass if we need to actually populate it based on each queryier's location
    if(!sDatabase.RunQuery(res,
        "SELECT"
        "    price, volRemaining, typeID, `range`, orderID,"
        "   volEntered, minVolume, bid, issued as issueDate, duration,"
        "   stationID, regionID, solarSystemID, jumps"
        " FROM market_orders "
        " WHERE regionID=%u AND typeID=%u AND bid=%d", regionID, typeID, TransactionTypeSell))
    {
        codelog( MARKET__ERROR, "Error in query: %s", res.error.c_str() );

        PyDecRef( tup );
        return NULL;
    }
    sLog.Debug("MarketDB::GetOrders", "Fetched %d sell orders for type %d", res.GetRowCount(), typeID);

    //this is wrong.
    tup->AddItem( DBResultToCRowset( res ) );

    //query buy orders
    if(!sDatabase.RunQuery(res,
        "SELECT"
        "    price, volRemaining, typeID, `range`, orderID,"
        "   volEntered, minVolume, bid, issued as issueDate, duration,"
        "   stationID, regionID, solarSystemID, jumps"
        " FROM market_orders "
        " WHERE regionID=%u AND typeID=%u AND bid=%d", regionID, typeID, TransactionTypeBuy))
    {
        codelog( MARKET__ERROR, "Error in query: %s", res.error.c_str() );

        PyDecRef( tup );
        return NULL;
    }
    sLog.Debug("MarketDB::GetOrders", "Fetched %d buy orders for type %d", res.GetRowCount(), typeID);

    //this is wrong.
    tup->AddItem( DBResultToCRowset( res ) );

    return tup;
}
Пример #30
0
bool PyCachedObjectDecoder::Decode(PySubStream **in_ss)
{
    PySubStream *ss = *in_ss;    //consume
    *in_ss = NULL;

    PySafeDecRef( cache );
    PySafeDecRef( objectID );

    ss->DecodeData();
    if(ss->decoded() == NULL) {
		sLog.Error("PyCachedObjectDecoder","Unable to decode initial stream for PycachedObject");

        PyDecRef( ss );
        return false;
    }

    if(!ss->decoded()->IsObject()) {
		sLog.Error("PyCachedObjectDecoder","Cache substream does not contain an object: %s", ss->decoded()->TypeString());

        PyDecRef( ss );
        return false;
    }
    PyObject *po = (PyObject *) ss->decoded();
    //TODO: could check type string, dont care... (should be objectCaching.CachedObject)

    if(!po->arguments()->IsTuple()) {
		sLog.Error("PyCachedObjectDecoder","Cache object's args is not a tuple: %s", po->arguments()->TypeString());

        PyDecRef( ss );
        return false;
    }
    PyTuple *args = (PyTuple *) po->arguments();

    if(args->items.size() != 7) {
		sLog.Error("PyCachedObjectDecoder","Cache object's args tuple has %lu elements instead of 7", args->items.size());

        PyDecRef( ss );
        return false;
    }

    if(!args->items[0]->IsTuple()) {
		sLog.Error("PyCachedObjectDecoder","Cache object's arg %d is not a Tuple: %s", 0, args->items[0]->TypeString());

        PyDecRef( ss );
        return false;
    }
    //ignore unknown [1]
    /*if(!args->items[1]->IsInt()) {
        _log(CLIENT__ERROR, "Cache object's arg %d is not a None: %s", 1, args->items[1]->TypeString());

        PyDecRef( ss );
        return false;
    }*/
    if(!args->items[2]->IsInt()) {
		sLog.Error("PyCachedObjectDecoder","Cache object's arg %d is not an Integer: %s", 2, args->items[2]->TypeString());
        PyDecRef( ss );
        return false;
    }

    if(!args->items[3]->IsInt()) {
		sLog.Error("PyCachedObjectDecoder","Cache object's arg %d is not an Integer: %s", 3, args->items[3]->TypeString());
        PyDecRef( ss );
        return false;
    }

    if(!args->items[5]->IsInt()) {
		sLog.Error("PyCachedObjectDecoder","Cache object's arg %d is not a : %s", 5, args->items[5]->TypeString());
        PyDecRef( ss );
        return false;
    }

    PyTuple *objVt = (PyTuple *) args->items[0];
    if(!objVt->items[0]->IsInt()) {
		sLog.Error("PyCachedObjectDecoder","Cache object's version tuple %d is not an Integer: %s", 0, objVt->items[0]->TypeString());
        PyDecRef( ss );
        return false;
    }

    if(!objVt->items[1]->IsInt()) {
		sLog.Error("PyCachedObjectDecoder","Cache object's version tuple %d is not an Integer: %s", 1, objVt->items[1]->TypeString());
        PyDecRef( ss );
        return false;
    }

    PyInt *nodeidr = (PyInt *) args->items[2];
    PyInt *sharedr = (PyInt *) args->items[3];
    PyInt *compressedr = (PyInt *) args->items[5];
    PyInt *timer = (PyInt *) objVt->items[0];
    PyInt *versionr = (PyInt *) objVt->items[1];

    timestamp = timer->value();
    version = versionr->value();
    nodeID = nodeidr->value();
    shared = ( sharedr->value() != 0 );
    compressed = ( compressedr->value() != 0 );

    //content (do this as the last thing, since its the heavy lifting):
    if(args->items[4]->IsSubStream()) {
        cache = (PySubStream *) args->items[4];
        //take it
        args->items[4] = NULL;
    } else if(args->items[4]->IsBuffer()) {
        //this is a data buffer, likely compressed.
        PyBuffer* buf = args->items[4]->AsBuffer();

        PyIncRef( buf );
		cache = new PySubStream( buf );
    } else if(args->items[4]->IsString()) {
        //this is a data buffer, likely compressed, not sure why it comes through as a string...
        PyString* str = args->items[4]->AsString();

        cache = new PySubStream( new PyBuffer( *str ) );
    } else {
		sLog.Error("PyCachedObjectMgr", "Cache object's arg %d is not a substream or buffer: %s", 4, args->items[4]->TypeString());
        PyDecRef( ss );
        return false;
    }

    objectID = args->items[6]; PyIncRef(objectID);

    PyDecRef( ss );
    return true;
}