// NOTE Mrz 21, 2007: <pvl> might need to handle the params the way SetGrab() // does (separate param table for each of the grabbed objects). // UPDATE Mrz 26, 2007: <pvl> done bool CMultipleGrabHandler::SetDrop(SmartScriptTable &rParams) { SmartScriptTable dropParamsTable; if (rParams->GetValue("params",dropParamsTable)) { bool result = true; IScriptTable::Iterator iter = dropParamsTable->BeginIteration(); int numGrabHandlers = m_handlers.size(); for (int i=0; dropParamsTable->MoveNext(iter) && i < numGrabHandlers; ++i) { SmartScriptTable params; iter.value.CopyTo (params); result = m_handlers[i]->SetDrop(params) & result; } dropParamsTable->EndIteration(iter); return result; } else { bool result = true; std::vector <CAnimatedGrabHandler*>::iterator it = m_handlers.begin(); std::vector <CAnimatedGrabHandler*>::iterator end = m_handlers.end(); for ( ; it != end; ++it) result = (*it)->SetDrop(rParams) & result; return result; } }
// add a synch proxy table to an entity void CScriptRMI::AddSynchedTable( IScriptTable * pEntityTable, ScriptHandle id, const char * name, SmartScriptTable dispatchTable ) { SmartScriptTable synchedTable( pEntityTable->GetScriptSystem() ); SmartScriptTable hiddenTable( pEntityTable->GetScriptSystem() ); SmartScriptTable origTable; pEntityTable->GetValue( name, origTable ); hiddenTable->Clone( dispatchTable ); hiddenTable->SetValue( "__index", hiddenTable ); IScriptTable::Iterator iter = origTable->BeginIteration(); while (origTable->MoveNext(iter)) { if (iter.sKey) { if (hiddenTable->GetValueType( iter.sKey ) != svtNull) GameWarning( "Replacing non-null value %s", iter.sKey ); ScriptAnyValue value; origTable->GetValueAny( iter.sKey, value ); hiddenTable->SetValueAny( iter.sKey, value ); } } origTable->EndIteration(iter); synchedTable->Delegate( hiddenTable ); synchedTable->SetValue( ID_FIELD, id ); synchedTable->SetValue( HIDDEN_FIELD, hiddenTable ); pEntityTable->SetValue( name, synchedTable ); }
bool CMultipleGrabHandler::SetGrab(SmartScriptTable &rParams) { // NOTE Mrz 20, 2007: <pvl> if we don't find 'params' param in the table, // we assume that this is an old-style grab param table that's not aware of // the possibility of multiple objects grabbed simultaneously. SmartScriptTable grabParamsTable; if (rParams->GetValue("params",grabParamsTable)) { bool result = true; IScriptTable::Iterator iter = grabParamsTable->BeginIteration(); while(grabParamsTable->MoveNext(iter)) { CAnimatedGrabHandler * handler = new CAnimatedGrabHandler (m_pActor); SmartScriptTable params; iter.value.CopyTo (params); result = handler->SetGrab(params) & result; m_handlers.push_back (handler); } grabParamsTable->EndIteration(iter); return result; } else { CAnimatedGrabHandler * handler = new CAnimatedGrabHandler (m_pActor); m_handlers.push_back (handler); return handler->SetGrab(rParams); } }
//------------------------------------------------------------------------ int CScriptBind_Actor::CheckVirtualInventoryRestrictions(IFunctionHandler *pH, SmartScriptTable inventory, const char *itemClassName) { CActor *pActor = GetActor(pH); if (!pActor) return pH->EndFunction(); static std::vector<string> virtualInventory; virtualInventory.reserve(inventory->Count()); IScriptTable::Iterator it=inventory->BeginIteration(); while(inventory->MoveNext(it)) { const char *itemClass=0; it.value.CopyTo(itemClass); if (itemClass && itemClass[0]) virtualInventory.push_back(itemClass); } inventory->EndIteration(it); bool result=pActor->CheckVirtualInventoryRestrictions(virtualInventory, itemClassName); virtualInventory.resize(0); if (result) return pH->EndFunction(1); return pH->EndFunction(); }
bool CAnimatedGrabHandler::SetGrab(SmartScriptTable &rParams) { // NOTE Aug 16, 2007: <pvl> if there's another grab action under way, this one fails // first the cheaper check (should also cover the case when output is not yet set because of longer transition time) if (m_grabStats.IKActive == true) return false; // then the more expensive check if (IAnimationGraphState* pAGState = m_pActor->GetAnimationGraphState()) { const char* grabActive = pAGState->QueryOutput("GrabActive"); if (grabActive != NULL && grabActive[0] != 0) return false; } if (m_grabStats.grabId > 0) Reset(); m_grabStats.useIKRotation = false; rParams->GetValue("useIKRotation",m_grabStats.useIKRotation); m_grabStats.limbNum = 0; SmartScriptTable limbsTable; if (rParams->GetValue("limbs",limbsTable)) { IScriptTable::Iterator iter = limbsTable->BeginIteration(); while(limbsTable->MoveNext(iter)) { const char *pLimb; iter.value.CopyTo(pLimb); int limbIdx = m_pActor->GetIKLimbIndex(pLimb); if (limbIdx > -1 && m_grabStats.limbNum<GRAB_MAXLIMBS) m_grabStats.limbId[m_grabStats.limbNum++] = limbIdx; } limbsTable->EndIteration(iter); } m_grabStats.usingAnimation = false; const char * pCarryAnimGraphInput = 0; if (rParams->GetValue("carryAnimGraphInput",pCarryAnimGraphInput)) { const int maxNameLen = SGrabStats::s_maxAGInputNameLen; strncpy(m_grabStats.carryAnimGraphInput,pCarryAnimGraphInput,maxNameLen); m_grabStats.carryAnimGraphInput[maxNameLen-1] = 0; } SmartScriptTable animationTable; if (rParams->GetValue("animation",animationTable)) { const char *pAnimGraphSignal = NULL; if (animationTable->GetValue("animGraphSignal",pAnimGraphSignal)) { const int maxNameLen = SGrabStats::s_maxAGInputNameLen; strncpy(m_grabStats.grabAnimGraphSignal,pAnimGraphSignal,maxNameLen); m_grabStats.grabAnimGraphSignal[maxNameLen-1] = 0; } // TODO Dez 15, 2006: <pvl> if there's no graph signal, consider // returning false - won't work without graph signal anyway if (pAnimGraphSignal) { m_grabStats.usingAnimation = true; m_grabStats.usingAnimationForDrop = true; m_grabStats.usingAnimationForGrab = true; } if (animationTable->GetValue("forceThrow",m_grabStats.throwDelay)) { //m_grabStats.grabDelay = 0.0f; m_grabStats.maxDelay = m_grabStats.throwDelay; } m_grabStats.grabbedObjOfs.zero(); animationTable->GetValue("grabbedObjOfs",m_grabStats.grabbedObjOfs); m_grabStats.releaseIKTime = 0.0f; animationTable->GetValue("releaseIKTime",m_grabStats.releaseIKTime); } else { if (rParams->GetValue("grabAnim",animationTable)) { m_grabStats.usingAnimationForGrab = true; m_grabStats.releaseIKTime = 0.0f; animationTable->GetValue("releaseIKTime",m_grabStats.releaseIKTime); m_grabStats.grabbedObjOfs.zero(); animationTable->GetValue("grabbedObjOfs",m_grabStats.grabbedObjOfs); const char *pAnimGraphSignal = NULL; if (animationTable->GetValue("animGraphSignal",pAnimGraphSignal)) { const int maxNameLen = SGrabStats::s_maxAGInputNameLen; strncpy(m_grabStats.grabAnimGraphSignal,pAnimGraphSignal,maxNameLen); m_grabStats.grabAnimGraphSignal[maxNameLen-1] = 0; } } if (rParams->GetValue("dropAnim",animationTable)) { m_grabStats.usingAnimationForDrop = true; // NOTE Feb 10, 2007: <pvl> this is just to get around the // condition in CBaseGrabHandler::SetDrop(). If we don't set // throwDelay to something bigger than zero SetDrop() executes // StartDrop() immediately. // All of this stuff around maxDelay, throwDelay etc. should be // rewritten but in a way that doesn't break existing behaviour. m_grabStats.throwDelay = 1000.0f; const char *pAnimGraphSignal = NULL; if (animationTable->GetValue("animGraphSignal",pAnimGraphSignal)) { const int maxNameLen = SGrabStats::s_maxAGInputNameLen; strncpy(m_grabStats.dropAnimGraphSignal,pAnimGraphSignal,SGrabStats::s_maxAGInputNameLen); m_grabStats.dropAnimGraphSignal[maxNameLen-1] = 0; } } m_grabStats.usingAnimation = m_grabStats.usingAnimationForDrop || m_grabStats.usingAnimationForGrab; } m_grabStats.followBoneID = -1; const char *followBone; if (rParams->GetValue("followBone",followBone)) { ICharacterInstance *pCharacter = m_pActor->GetEntity()->GetCharacter(0); if (pCharacter) m_grabStats.followBoneID = pCharacter->GetISkeletonPose()->GetJointIDByName(followBone); } // TODO Dez 15, 2006: <pvl> consider returning false if bone ID is -1 // at this point - it won't work anyway without bone ID //FIXME:remove this garbage when the grabbing setup is refactored too float savedThrowDelay(m_grabStats.throwDelay); if ( ! CBaseGrabHandler::SetGrab(rParams)) return false; m_grabStats.additionalRotation.SetIdentity(); m_grabStats.origRotation.SetIdentity(); if (m_grabStats.carryAnimGraphInput[0]) { m_pActor->SetAnimationInput("CarryItem",m_grabStats.carryAnimGraphInput); } if (m_grabStats.grabAnimGraphSignal[0]) { m_pActor->SetAnimationInput("Signal",m_grabStats.grabAnimGraphSignal); } if ( ! m_grabStats.usingAnimationForGrab) { StartGrab(); } m_grabStats.maxDelay = m_grabStats.throwDelay = savedThrowDelay; return true; }
// one-time validation of entity tables bool CScriptRMI::ValidateDispatchTable( const char * clazz, SmartScriptTable dispatch, SmartScriptTable methods, bool bServerTable ) { CryAutoCriticalSection lkDispatch(m_dispatchMutex); std::map<string,size_t>::iterator iterN = m_entityClassToEntityTypeID.lower_bound(clazz); if (iterN == m_entityClassToEntityTypeID.end() || iterN->first != clazz) { iterN = m_entityClassToEntityTypeID.insert( iterN, std::make_pair(clazz, m_entityClassToEntityTypeID.size()) ); CRY_ASSERT(iterN->second == m_dispatch.size()); m_dispatch.push_back(SDispatch()); } SDispatch& dispatchTblCont = m_dispatch[iterN->second]; SFunctionDispatchTable& dispatchTbl = bServerTable ? dispatchTblCont.server : dispatchTblCont.client; IScriptTable::Iterator iter = dispatch->BeginIteration(); while (dispatch->MoveNext(iter)) { if (iter.sKey) { if (iter.sKey[0] == '_' && iter.sKey[1] == '_') continue; ScriptVarType type = methods->GetValueType( iter.sKey ); if (type != svtFunction) { GameWarning( "In class %s: function %s is exposed but not defined", clazz, iter.sKey ); dispatch->EndIteration(iter); return false; } } else { int id = iter.nKey; CRY_ASSERT(id>0); id--; if (id >= dispatchTbl.size()) dispatchTbl.resize(id+1); SFunctionDispatch& dt = dispatchTbl[id]; if (iter.value.GetVarType() != svtString) { GameWarning("Expected a string in dispatch table, got type %d", iter.value.GetVarType()); dispatch->EndIteration(iter); return false; } const char * funcData = iter.value.str; const char * colon = strchr(funcData, ':'); if (colon == NULL) { dispatch->EndIteration(iter); return false; } if (colon - funcData > MaxSynchedPropertyNameLength) { dispatch->EndIteration(iter); return false; } memcpy( dt.name, funcData, colon-funcData ); dt.name[colon-funcData] = 0; strcpy(dt.format, colon + 1); } } dispatch->EndIteration(iter); dispatch->SetValue( VALIDATED_FIELD, true ); if (bServerTable) { dispatchTblCont.m_serverDispatchScriptTable = dispatch; } else { dispatchTblCont.m_clientDispatchScriptTable = dispatch; } return true; }
// setup the meta-table for synched variables bool CScriptRMI::BuildSynchTable( SmartScriptTable vars, SmartScriptTable cls, const char * name ) { IScriptSystem * pSS = vars->GetScriptSystem(); SmartScriptTable synched( pSS ); SmartScriptTable defaultValues( pSS ); // TODO: Improve IScriptTable::SUserFunctionDesc fd; fd.pFunctor = functor_ret( SynchedNewIndexFunction ); fd.sFunctionName = "__newindex"; fd.sGlobalName = "<net-dispatch>"; fd.sFunctionParams = "(...)"; synched->AddFunction( fd ); std::vector<SSynchedPropertyInfo> properties; IScriptTable::Iterator iter = vars->BeginIteration(); while (vars->MoveNext(iter)) { if (iter.sKey) { int type; if (!vars->GetValue(iter.sKey, type)) { vars->EndIteration(iter); pSS->RaiseError( "No type for %s", iter.sKey ); return false; } size_t len = strlen(iter.sKey); if (len > MaxSynchedPropertyNameLength) { vars->EndIteration(iter); pSS->RaiseError( "Synched var name '%s' too long (max is %d)", iter.sKey, (int)MaxSynchedPropertyNameLength ); return false; } SSynchedPropertyInfo info; strcpy( info.name, iter.sKey ); info.type = (EScriptSerializeType) type; properties.push_back( info ); if (info.type == eSST_String) defaultValues->SetValue( iter.sKey, "" ); else defaultValues->SetValue( iter.sKey, 0 ); } } vars->EndIteration( iter ); if (properties.empty()) return true; fd.pFunctor = NULL; fd.pUserDataFunc = SerializeFunction; fd.nDataSize = sizeof(SSynchedPropertyInfo) * properties.size(); fd.pDataBuffer = &properties[0]; fd.sFunctionName = SERIALIZE_FUNCTION; fd.sFunctionParams = "(...)"; fd.sGlobalName = "<net-dispatch>"; synched->AddFunction( fd ); cls->SetValue( SERVER_SYNCHED_FIELD, synched ); cls->SetValue( "synched", defaultValues ); return true; }
// build a script dispatch table - this table is the metatable for all // dispatch proxy tables used (onClient, allClients, otherClients) bool CScriptRMI::BuildDispatchTable( SmartScriptTable methods, SmartScriptTable classMethodTable, SmartScriptTable cls, const char * name ) { IScriptSystem * pSS = methods->GetScriptSystem(); SmartScriptTable dispatch( pSS ); uint8 funcID = 0; IScriptTable::SUserFunctionDesc fd; SFunctionInfo info; IScriptTable::Iterator iter = methods->BeginIteration(); while (methods->MoveNext(iter)) { if (iter.sKey) { const char * function = iter.sKey; if (strlen(function)>=2 && function[0] == '_' && function[1] == '_') { methods->EndIteration(iter); pSS->RaiseError( "In Net.Expose: can't expose functions beginning with '__' (function was %s)", function ); return false; } SmartScriptTable specTable; if (!methods->GetValue(function, specTable)) { methods->EndIteration(iter); pSS->RaiseError( "In Net.Expose: function %s entry is not a table (in %s)", function, name ); return false; } // fetch format int count = specTable->Count(); if (count < 1) { methods->EndIteration(iter); pSS->RaiseError( "In Net.Expose: function %s entry is an empty table (in %s)", function, name ); return false; } else if (count-1 > MaxRMIParameters) { methods->EndIteration(iter); pSS->RaiseError( "In Net.Expose: function %s has too many parameters (%d) (in %s)", function, count-1, name ); return false; } int tempReliability; if (!specTable->GetAt(1, tempReliability) || tempReliability < 0 || tempReliability >= eNRT_NumReliabilityTypes) { methods->EndIteration(iter); pSS->RaiseError( "In Net.Expose: function %s has invalid reliability type %d (in %s)", function, tempReliability, name ); return false; } ENetReliabilityType reliability = (ENetReliabilityType) tempReliability; if (!specTable->GetAt(2, tempReliability) || tempReliability < 0 || tempReliability >= eRAT_NumAttachmentTypes) { methods->EndIteration(iter); pSS->RaiseError( "In Net.Expose: function %s has invalid attachment type %d (in %s)", function, tempReliability, name ); } ERMIAttachmentType attachment = (ERMIAttachmentType) tempReliability; string format; format.reserve(count-1); for (int i=3; i<=count; i++) { int type = 666; if (!specTable->GetAt( i, type ) || type<-128 || type>127) { methods->EndIteration(iter); pSS->RaiseError( "In Net.Expose: function %s has invalid serialization policy %d at %d (in %s)", function, type, i, name ); return false; } format.push_back( (char) type ); } CRY_ASSERT( format.length() <= MaxRMIParameters ); strcpy( info.format, format.c_str() ); info.funcID = funcID; info.reliability = reliability; info.attachment = attachment; fd.pUserDataFunc = ProxyFunction; fd.sFunctionName = function; fd.nDataSize = sizeof(SFunctionInfo); fd.pDataBuffer = &info; fd.sGlobalName = "<net-dispatch>"; fd.sFunctionParams = "(...)"; dispatch->AddFunction( fd ); string lookupData = function; lookupData += ":"; lookupData += format; dispatch->SetAt( funcID+1, lookupData.c_str() ); funcID ++; if (funcID == 0) { funcID--; methods->EndIteration(iter); pSS->RaiseError( "Too many functions... max is %d", funcID ); return false; } } else { GameWarning( "In Net.Expose: non-string key ignored" ); } } methods->EndIteration(iter); dispatch->SetValue( VALIDATED_FIELD, false ); cls->SetValue( name, dispatch ); return true; }