/*-----------------------------------------------------------------------------
	Global Variables
-----------------------------------------------------------------------------*/
PVOID pOldSerializeObject;

/*-----------------------------------------------------------------------------
	DetourJump - Simple Thunktable detour
-----------------------------------------------------------------------------*/
void* DetourJump (void *orig, void *dest)
{
	DWORD oldprot;
	VirtualProtect(orig, 5, PAGE_EXECUTE_READWRITE, &oldprot);
	DWORD orgJmp = DWORD(*((void **) ((unsigned int) orig + 1))) + 5 + (unsigned int) orig;
	*((unsigned char *) orig ) = 0xE9; 
	*((void **) ((unsigned int) orig + 1)) = (void *) (((unsigned int) dest) - (((unsigned int) orig) + 5));
	VirtualProtect(orig, 5, oldprot, &oldprot);
	return (void*)orgJmp;
}

/*-----------------------------------------------------------------------------
	UuPackageMap::SerializeObject - Net compatible with v451b

	FInBunch << Object
	bit - dynamic/static
	int - actor channel idx or object idx
-----------------------------------------------------------------------------*/
UBOOL __fastcall udSerializeObject( UPackageMapLevel* udThis, DWORD dwDummy, FArchive& Ar, UClass* Class, UObject*& Object )
{
	__asm pushad
	guard(UuPackageMap::SerializeObject);

	GLog->Logf(TEXT("UuPackageMap::SerializeObject"));

	FInBunch& Bunch = (FInBunch&)Ar;
	GLog->Logf(TEXT("InBunch Size: %d - %d"), Bunch.GetPosBits(), Bunch.GetNumBits());

	DWORD Index = 0;
	if (Ar.IsLoading())					// ArIsLoading: 0x10
	{
		GLog->Logf(TEXT(">>> InBunch is loading"));

		BYTE B = 0;						// Byte size allocation on stack (BYTE PTR [EBP+B])
		Ar.SerializeBits(&B, 1);		// VFunc 0x8		
		
		if (B)
		{
			GLog->Logf(TEXT(">>> Object is dynamic"));

			// B == 1 => Dynamic
			// Get actor channel index
			Ar.SerializeInt(Index, UNetConnection::MAX_CHANNELS);	// MAX_CHANNELS = 0x3FF - VFunc 0xC

			GLog->Logf(TEXT(">>> Channel index: %d - 0x%03X"), Index, Index);
			
			if (Index == 0)
			{
				Object = NULL;
			}
			else
			{
				if (!Ar.IsError()									// ArIsError: 0x2C
					&& Index < UNetConnection::MAX_CHANNELS			// JNB 0x3FF
					&& udThis->Connection->Channels[Index]		// 0xE60 + EAX*4
					&& udThis->Connection->Channels[Index]->ChType == CHTYPE_Actor	// 0x44
					&& !udThis->Connection->Channels[Index]->Closing)				// 0x30
				{
					Object = ((UActorChannel*)udThis->Connection->Channels[Index])->GetActor();		// AActor* Actor; //	-- 0x64
				}
			}	

			GLog->Logf(TEXT(">>> Mapped to object: 0x%08X - %s"), Object, (Object ? Object->GetFullName() : TEXT("NONE")));
		}
		else
		{
			GLog->Logf(TEXT(">>> Object is static"));

			// 0x68 = second to last var in UPackageMap = MaxObjectIndex
			Ar.SerializeInt(Index, udThis->GetMaxObjectIndex());

			GLog->Logf(TEXT(">>> Object index: %d - 0x%03X"), Index, Index);

			if (!Ar.IsError())		// 0x2C
				Object = udThis->IndexToObject(Index, 1);		// VFUNC 0x64

			GLog->Logf(TEXT(">>> Mapped to object: 0x%08X - %s"), Object, (Object ? Object->GetFullName() : TEXT("NONE")));

				UClass* ActorClass = Cast<UClass>( Object );
				if (ActorClass)
				{
					GLog->Logf(TEXT(">>> ActorClass: %s"), ActorClass->GetFullName());

					FClassNetCache* ClassCache = udThis->GetClassNetCache(ActorClass);

					if (ClassCache)
					{	
						GLog->Logf(TEXT(">>> Found ClassCache"));
						/*TArray<FFieldNetCache>* Fields = (TArray<FFieldNetCache>*)( (DWORD)ClassCache + 0x1C );

						GLog->Logf(TEXT(">>> Rep fields in class cache: %d"), Fields->Num());

						for (INT i = 0; i < Fields->Num(); ++i)
						{
							GLog->Logf(TEXT(">>> --- %d: %d %s %d"), i, (*Fields)(i).ConditionIndex, (*Fields)(i).Field->GetFullName(), (*Fields)(i).FieldNetIndex);
						}*/

						for (INT i = 0; i < ClassCache->GetMaxIndex(); ++i)
						{
							FFieldNetCache* Field = ClassCache->GetFromIndex(i);
							GLog->Logf(TEXT(">>> --- %d: %d %s %d"), i, Field->ConditionIndex, Field->Field->GetFullName(), Field->FieldNetIndex);
						}
					}
				}
			}

		if( Object && !Object->IsA(Class) )
		{
			debugf(TEXT("Forged object: got %s, expecting %s"),*Object->GetFullName(),*Class->GetFullName());
			Object = NULL;
		}		
		__asm popad
		return 1;
	}
	else
	{
		GError->Logf(TEXT("UDEMO ERROR: Attempt to serialize to loaded FArchive: 0x%08X - %s"), Object, (Object ? Object->GetFullName() : TEXT("NONE")));
		__asm popad
		return 0;
	}
	
	unguard;	
}