void CElement::DeleteCustomData ( const char* szName ) { // Grab the old variable SCustomData * pData = m_pCustomData->Get ( szName ); if ( pData ) { CLuaArgument oldVariable; oldVariable = pData->Variable; // Delete the custom data m_pCustomData->Delete ( szName ); // Trigger the onElementDataChange event on us CLuaArguments Arguments; Arguments.PushString ( szName ); Arguments.PushArgument ( oldVariable ); Arguments.PushArgument ( CLuaArgument() ); // Use nil as the new value to indicate the data has been removed CallEvent ( "onElementDataChange", Arguments ); } }
void CElement::SetCustomData ( const char* szName, const CLuaArgument& Variable, CLuaMain* pLuaMain, bool bSynchronized ) { assert ( szName ); // Grab the old variable CLuaArgument oldVariable; const SCustomData * pData = m_pCustomData->Get ( szName ); if ( pData ) { oldVariable = pData->Variable; } // Set the new data m_pCustomData->Set ( szName, Variable, pLuaMain, bSynchronized ); // Trigger the onElementDataChange event on us CLuaArguments Arguments; Arguments.PushString ( szName ); Arguments.PushArgument ( oldVariable ); CallEvent ( "onElementDataChange", Arguments ); }
void CClientEntity::SetCustomData ( const char* szName, const CLuaArgument& Variable, CLuaMain* pLuaMain ) { assert ( szName ); // Grab the old variable CLuaArgument oldVariable; SCustomData * pData = m_pCustomData->Get ( szName ); if ( pData ) { oldVariable = pData->Variable; } // Set the new data m_pCustomData->Set ( szName, Variable, pLuaMain ); // Trigger the onClientElementDataChange event on us CLuaArguments Arguments; Arguments.PushString ( szName ); Arguments.PushArgument ( oldVariable ); CallEvent ( "onClientElementDataChange", Arguments, true ); }
int CLuaFunctionDefs::GetBrowserSource ( lua_State* luaVM ) { // bool getBrowserSource ( function callback ) CClientWebBrowser* pWebBrowser; CLuaFunctionRef callbackFunction; CScriptArgReader argStream ( luaVM ); argStream.ReadUserData ( pWebBrowser ); argStream.ReadFunction ( callbackFunction ); argStream.ReadFunctionComplete (); if ( !argStream.HasErrors () ) { CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine ( luaVM ); if ( pLuaMain && VERIFY_FUNCTION ( callbackFunction ) ) { pWebBrowser->GetSourceCode ( [callbackFunction, pLuaMain]( const std::string& code ) { /* This function should not be called when the resource is about to stop as stopping the resource destroys the browser element and thus cancels the CefStringVisitor callback class (see CWebView::GetSourceCode::MyStringVisitor) */ if ( VERIFY_FUNCTION ( callbackFunction ) ) { CLuaArguments arguments; // TODO: Use SCharStringRef/direct string access instead of copying strings around arguments.PushString ( code ); arguments.Call ( pLuaMain, callbackFunction ); } }); lua_pushboolean ( luaVM, true ); return 1; } } else m_pScriptDebugging->LogCustom ( luaVM, argStream.GetFullErrorMessage () ); lua_pushboolean ( luaVM, false ); return 1; }
void CElementDeleter::Delete ( class CElement* pElement, bool bUnlink, bool bUpdatePerPlayerEntities, CResource* pDebugResource, const char* szDebugText ) { if ( pElement ) { if ( !IsBeingDeleted ( pElement ) ) { // Before we do anything, fire the on-destroy event CLuaArguments Arguments; if ( pDebugResource ) Arguments.PushResource( pDebugResource ); else Arguments.PushNil(); Arguments.PushString( szDebugText ); pElement->CallEvent ( "onElementDestroy", Arguments ); // Add it to our list if ( !pElement->IsBeingDeleted () ) { m_List.push_back ( pElement ); } // Flag it as being deleted and unlink it from the tree/managers pElement->SetIsBeingDeleted ( true ); pElement->ClearChildren (); pElement->SetParentObject ( NULL, bUpdatePerPlayerEntities ); if ( bUnlink ) pElement->Unlink (); } else { if ( pElement->GetType ( ) == CElement::PLAYER ) { // Tell the console CLogger::LogPrint ( "URGENT: Report this error on bugs.mtasa.com error code: 6930-1\n" ); } } } }
void CElement::ReadCustomData ( CLuaMain* pLuaMain, CEvents* pEvents ) { assert ( pLuaMain ); assert ( pEvents ); // Got an XML node? if ( m_pXMLNode ) { // Iterate the attributes of our XML node CXMLAttributes* pAttributes = &(m_pXMLNode->GetAttributes ()); unsigned int uiAttributeCount = pAttributes->Count (); for ( unsigned int uiIndex = 0; uiIndex < uiAttributeCount; uiIndex++ ) { // Grab the node (we can assume it exists here) CXMLAttribute* pAttribute = pAttributes->Get ( uiIndex ); // Make a lua argument from it and set the content CLuaArguments args; if ( !args.ReadFromJSONString ( pAttribute->GetValue ().c_str() ) ) args.PushString ( pAttribute->GetValue ().c_str () ); SetCustomData ( pAttribute->GetName ().c_str (), *args[0], pLuaMain ); } } }
ResponseCode CResourceHTMLItem::Request ( HttpRequest * ipoHttpRequest, HttpResponse * ipoHttpResponse, CAccount * account ) { if ( !m_pVM ) Start (); if ( m_bIsBeingRequested ) { ipoHttpResponse->SetBody ( "Busy!", strlen("Busy!") ); return HTTPRESPONSECODE_500_INTERNALSERVERERROR; } m_bIsBeingRequested = true; m_responseCode = HTTPRESPONSECODE_200_OK; if ( !m_bIsRaw ) { ipoHttpResponse->oResponseHeaders [ "content-type" ] = m_strMime; CLuaArguments formData; for ( FormValueMap::iterator iter = ipoHttpRequest->oFormValueMap.begin(); iter != ipoHttpRequest->oFormValueMap.end(); iter++ ) { formData.PushString ( (*iter).first.c_str() ); formData.PushString ( ((FormValue)(*iter).second).sBody.c_str() ); } CLuaArguments cookies; for ( CookieMap::iterator iter = ipoHttpRequest->oCookieMap.begin(); iter != ipoHttpRequest->oCookieMap.end(); iter++ ) { cookies.PushString ( (*iter).first.c_str() ); cookies.PushString ( (*iter).second.c_str() ); } CLuaArguments headers; for ( StringMap::iterator iter = ipoHttpRequest->oRequestHeaders.begin(); iter != ipoHttpRequest->oRequestHeaders.end(); iter++ ) { headers.PushString ( (*iter).first.c_str() ); headers.PushString ( (*iter).second.c_str() ); } m_currentResponse = ipoHttpResponse; CLuaArguments querystring ( formData ); CLuaArguments args; args.PushTable ( &headers ); // requestHeaders args.PushTable ( &formData ); // form args.PushTable ( &cookies ); // cookies args.PushString ( ipoHttpRequest->GetAddress().c_str() ); // hostname args.PushString ( ipoHttpRequest->sOriginalUri.c_str() ); // url args.PushTable ( &querystring ); // querystring args.PushAccount ( account ); // g_pGame->Lock(); // get the mutex (blocking) args.CallGlobal ( m_pVM, "renderPage" ); // g_pGame->Unlock(); // release the mutex ipoHttpResponse->SetBody ( m_strPageBuffer.c_str (), m_strPageBuffer.size () ); m_strPageBuffer.clear (); } else { // its a raw page FILE * file = fopen ( m_strResourceFileName.c_str (), "rb" ); if ( file ) { fseek ( file, 0, SEEK_END ); long lBufferLength = ftell ( file ); char* pBuffer = new char [ lBufferLength ]; rewind ( file ); fread ( pBuffer, 1, lBufferLength, file ); fclose ( file ); ipoHttpResponse->oResponseHeaders [ "content-type" ] = m_strMime; ipoHttpResponse->SetBody ( pBuffer, lBufferLength ); delete[] pBuffer; } else { ipoHttpResponse->SetBody ( "Can't read file!", strlen("Can't read file!") ); } } m_bIsBeingRequested = false; return m_responseCode; }
bool CConsole::HandleInput ( const char* szCommand, CClient* pClient, CClient* pEchoClient ) { // Copy it char szCommandBuffer [256]; szCommandBuffer [255] = 0; strncpy ( szCommandBuffer, szCommand, 255 ); stripControlCodes ( szCommandBuffer ); // Split it into two parts: Key and argument char* szKey = strtok ( szCommandBuffer, " " ); char* szArguments = strtok ( NULL, "\0" ); // Does the key exist? if ( szKey && szKey [0] != 0 ) { CConsoleCommand* pCommand = GetCommand ( szKey ); if ( pCommand ) { // Can this user use this command? if ( m_pACLManager->CanObjectUseRight ( pClient->GetAccount ()->GetName ().c_str (), CAccessControlListGroupObject::OBJECT_TYPE_USER, szKey, CAccessControlListRight::RIGHT_TYPE_COMMAND, !pCommand->IsRestricted () ) ) { return (*pCommand)( this, szArguments, pClient, pEchoClient ); } // Not enough access, tell the console CLogger::LogPrintf ( "DENIED: Denied '%s' access to command '%s'\n", pClient->GetNick (), szKey ); // Tell the client char szBuffer [128]; _snprintf ( szBuffer, sizeof(szBuffer), "ACL: Access denied for '%s'", szKey ); szBuffer[sizeof(szBuffer)-1] = '\0'; pClient->SendEcho ( szBuffer ); return false; } // Let the script handle it int iClientType = pClient->GetClientType (); switch ( iClientType ) { case CClient::CLIENT_PLAYER: { // See if any registered command can process it CPlayer* pPlayer = static_cast < CPlayer* > ( pClient ); m_pRegisteredCommands->ProcessCommand ( szKey, szArguments, pClient ); // HACK: if the client gets destroyed before here, dont continue if ( m_pPlayerManager->Exists ( pPlayer ) ) { // Call the console event CLuaArguments Arguments; Arguments.PushString ( szCommand ); pPlayer->CallEvent ( "onConsole", Arguments ); } break; } case CClient::CLIENT_CONSOLE: { // See if any registered command can process it CConsoleClient* pConsole = static_cast < CConsoleClient* > ( pClient ); m_pRegisteredCommands->ProcessCommand ( szKey, szArguments, pClient ); // Call the console event CLuaArguments Arguments; Arguments.PushString ( szCommand ); pConsole->CallEvent ( "onConsole", Arguments ); break; } default: break; } } // Doesn't exist return false; }
void CScriptDebugging::LogString ( const char* szPrePend, lua_State * luaVM, const char* szMessage, unsigned int uiMinimumDebugLevel, unsigned char ucRed, unsigned char ucGreen, unsigned char ucBlue ) { SString strText; lua_Debug debugInfo; // Initialize values for onDebugMessage SString strMsg = szMessage; SString strFile = ""; int iLine = -1; // Get a VM from somewhere if ( !luaVM && !m_LuaMainStack.empty () ) luaVM = m_LuaMainStack.back ()->GetVM (); for ( int level = 1; level < 3; level++ ) { if ( luaVM && lua_getstack ( luaVM, level, &debugInfo ) ) { lua_getinfo ( luaVM, "nlS", &debugInfo ); // Make sure this function isn't defined in a string (eg: from runcode) if ( debugInfo.source[0] == '@' ) { // Get and store the location of the debug message strFile = debugInfo.source + 1; iLine = debugInfo.currentline; // Populate a message to print/send (unless "info" type) if ( uiMinimumDebugLevel < 3 ) strText = SString ( "%s%s:%d: %s", szPrePend, strFile.c_str (), debugInfo.currentline, szMessage ); // if the file isn't empty, stop trying any other levels break; } else { strFile = debugInfo.short_src; if ( uiMinimumDebugLevel < 3 ) strText = SString ( "%s%s %s", szPrePend, szMessage, strFile.c_str () ); if ( strFile != "[string \"?\"]" ) // if the file isn't empty, stop trying any other levels break; } } else { strText = SString ( "%s%s%s", szPrePend, m_strLineAndFile.c_str(), szMessage ); // no point in trying other levels break; } } // Create a different message if type is "INFO" if ( uiMinimumDebugLevel > 2 ) strText = SString ( "%s%s", szPrePend, szMessage ); // Check whether onDebugMessage is currently being triggered if ( !m_bTriggeringOnDebugMessage ) { // Make sure the state of onDebugMessage being triggered can be retrieved later m_bTriggeringOnDebugMessage = true; // Prepare onDebugMessage CLuaArguments Arguments; Arguments.PushString ( strMsg.c_str ( ) ); Arguments.PushNumber ( uiMinimumDebugLevel ); // Push the file name (if any) if ( strFile.length ( ) > 0 ) Arguments.PushString ( strFile.c_str ( ) ); else Arguments.PushNil ( ); // Push the line (if any) if ( iLine > -1 ) Arguments.PushNumber ( iLine ); else Arguments.PushNil ( ); // Call onDebugMessage g_pGame->GetMapManager ( )->GetRootElement ( )->CallEvent ( "onDebugMessage", Arguments ); // Reset trigger state, so onDebugMessage can be called again at a later moment m_bTriggeringOnDebugMessage = false; } // Log it to the file if enough level if ( m_uiLogFileLevel >= uiMinimumDebugLevel ) { PrintLog ( strText ); } // Log to console CLogger::LogPrintf( "%s\n", strText.c_str () ); // Not sure what this is for, seems pretty useless if ( m_uiHtmlLogLevel >= uiMinimumDebugLevel ) { if ( luaVM ) { CLuaMain* pLuaMain = g_pGame->GetLuaManager()->GetVirtualMachine ( luaVM ); if ( pLuaMain ) { CResourceFile * file = pLuaMain->GetResourceFile(); if ( file && file->GetType() == CResourceHTMLItem::RESOURCE_FILE_TYPE_HTML ) { CResourceHTMLItem * html = (CResourceHTMLItem *)file; html->AppendToPageBuffer ( strText ); html->AppendToPageBuffer ( "<br/>" ); } } } } // Tell the players Broadcast ( CDebugEchoPacket ( strText, uiMinimumDebugLevel, ucRed, ucGreen, ucBlue ), uiMinimumDebugLevel ); }
void CClientWebBrowser::Events_OnTooltip ( const SString& strTooltip ) { CLuaArguments Arguments; Arguments.PushString ( strTooltip ); CallEvent ( "onClientBrowserTooltip", Arguments, false ); }
void CClientWebBrowser::Events_OnDocumentReady ( const SString& strURL ) { CLuaArguments Arguments; Arguments.PushString ( strURL ); CallEvent ( "onClientBrowserDocumentReady", Arguments, false ); }
// Set ( resource requesting the query, setting name, content ) bool CSettings::Set(const char *szLocalResource, const char *szSetting, const char *szContent) { CXMLNode * pNode; CResource * pResource; CXMLAttributes *pAttributes; char szBuffer[MAX_SETTINGS_LENGTH] = {0}; char szQueryResource[MAX_RESOURCE_LENGTH] = {0}; SettingStatus eStatus; bool bDeleteNode, bExists; SString strOldValue; // Check for empty strings if (strlen(szSetting) < 1) return false; // Get the actual resource name from the specified setting, and get the resource class if (!GetResourceName(szSetting, szQueryResource, MAX_RESOURCE_LENGTH - 1)) { // No name was specified, so use the local resource pResource = m_pResourceManager->GetResource(szLocalResource); } else pResource = m_pResourceManager->GetResource(szQueryResource); // If we have a valid resource if (pResource) { CXMLNode *pSource = pResource->GetSettingsNode(); // Check whether the setting exists in the settings registry pNode = Get(m_pNodeGlobalSettings, NULL, "", szLocalResource, szSetting, bDeleteNode, eStatus); bExists = true; // Default value // Try to get the value for the appropriate setting from the resource's meta XML file if (eStatus == NotFound && pSource) { pNode = Get(pSource, NULL, pResource->GetName().c_str(), szLocalResource, szSetting, bDeleteNode, eStatus); bExists = false; // There's no node in the settings registry, so we create one } // See if we have access if (eStatus != NoAccess) { // See if we have a prefix bool bPrefix = HasPrefix(szSetting[0]); // If no resource name was specified, use the local resource name if (!HasResourceName(szSetting)) { // If we have a prefix, move it from szSetting and put it at the beginning if (bPrefix) snprintf(szBuffer, MAX_SETTINGS_LENGTH - 1, "%c%s.%s", szSetting[0], szLocalResource, szSetting + 1); else snprintf(szBuffer, MAX_SETTINGS_LENGTH - 1, "%s.%s", szLocalResource, szSetting); } else { // If we have a prefix, move it from szSetting and put it at the beginning if (bPrefix) snprintf(szBuffer, MAX_SETTINGS_LENGTH - 1, "%c%s", szSetting[0], szSetting + 1); else strncpy(szBuffer, szSetting, MAX_SETTINGS_LENGTH - 1); } if (!bExists || !pNode) { // No existing settings registry entry, so create a new setting CreateSetting(m_pNodeGlobalSettings, szBuffer, szContent); } else { // Existing settings registry entry // Get the attributes pAttributes = &(pNode->GetAttributes()); // Abort if this value isnt public (but protected or private), and if the local resource // (doing the query) doesn't equal the setting's resource name if (GetAccessType(pAttributes->Find("name")->GetValue()[0]) != CSettings::Public && stricmp(pResource->GetName().c_str(), szLocalResource) != 0) return false; // Get the node's current value strOldValue = pAttributes->Find("value")->GetValue(); // Set the node's value pAttributes->Find("value")->SetValue(szContent); // If a prefix was given, set the node's name (to override any access operators) if (bPrefix) pAttributes->Find("name")->SetValue(szBuffer); } // Trigger onSettingChange CLuaArguments Arguments; Arguments.PushString(szSetting); if (strOldValue.length() > 0) Arguments.PushString(strOldValue.c_str()); else Arguments.PushNil(); Arguments.PushString(szContent); g_pGame->GetMapManager()->GetRootElement()->CallEvent("onSettingChange", Arguments); // Save the XML file if (m_pFile->Write()) return true; CLogger::ErrorPrintf("Error saving '%s'\n", FILENAME_SETTINGS); } } return false; }
bool COMMAND_Executed(const char* szCommand, const char* szArguments, bool bHandleRemotely, bool bHandled, bool bIsScriptedBind) { // Has the core already handled this command? if (!bHandled) { const char* szCommandBufferPointer = szCommand; if (!bHandleRemotely) { // Is the command "say" and the arguments start with '/' ? (command comes from the chatbox) if (stricmp(szCommand, "chatboxsay") == 0) { szCommandBufferPointer = "say"; } } // Toss them together so we can send it to the server SString strClumpedCommand; if (szArguments && szArguments[0]) strClumpedCommand.Format("%s %s", szCommandBufferPointer, szArguments); else strClumpedCommand = szCommandBufferPointer; // Convert to Unicode, and clamp it to a maximum command length std::wstring strClumpedCommandUTF = MbUTF8ToUTF16(strClumpedCommand.c_str()); strClumpedCommandUTF = strClumpedCommandUTF.substr(0, MAX_COMMAND_LENGTH); strClumpedCommand = UTF16ToMbUTF8(strClumpedCommandUTF); g_pClientGame->GetRegisteredCommands()->ProcessCommand(szCommandBufferPointer, szArguments); // Call the onClientConsole event auto pLocalPlayer = g_pClientGame->GetLocalPlayer(); if (pLocalPlayer) { CLuaArguments Arguments; // Censor input for /login command if (!stricmp(szCommandBufferPointer, "login")) { Arguments.PushString(SString("%s ***", szCommandBufferPointer)); } else { Arguments.PushString(strClumpedCommand); } pLocalPlayer->CallEvent("onClientConsole", Arguments, true); } // Write the chatlength and the content NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); if (!pBitStream) return false; // Write it to the bitstream pBitStream->Write(strClumpedCommand.c_str(), static_cast<int>(strlen(strClumpedCommand.c_str()))); // Send the packet to the server and free it g_pNet->SendPacket(PACKET_ID_COMMAND, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED, PACKET_ORDERING_CHAT); g_pNet->DeallocateNetBitStream(pBitStream); return true; } else { // Call our comand-handlers for core-executed commands too g_pClientGame->GetRegisteredCommands()->ProcessCommand(szCommand, szArguments); } return false; }
bool COMMAND_Executed ( const char* szCommand, const char* szArguments, bool bHandleRemotely, bool bHandled, bool bIsScriptedBind ) { // Has the core already handled this command? if ( !bHandled ) { //char szBuffer [256]; CLuaArguments Arguments; const char* szCommandBufferPointer = szCommand; if ( !bHandleRemotely ) { // Is the command "say" and the arguments start with '/' ? (command comes from the chatbox) if ( stricmp ( szCommand, "chatboxsay" ) == 0 ) { /* This code seems redundant, the chatbox now properly simulates commands. // His line starts with '/'? if ( *szArguments == '/' ) { // Copy the characters after the slash to the 0 terminator to a seperate buffer strncpy ( szBuffer, &szArguments [ 1 ], 256 ); szBuffer [ 255 ] = 0; // Split it into command and arguments char* szNewCommand = strtok ( szBuffer, " " ); char* szNewArguments = strtok ( NULL, "\0" ); if ( szNewCommand ) { // Execute it as another command if ( szNewArguments ) { g_pCore->GetCommands ()->Execute ( szNewCommand, szNewArguments ); } else { g_pCore->GetCommands ()->Execute ( szNewCommand, "" ); } return true; } } */ szCommandBufferPointer = "say"; } } // Toss them together so we can send it to the server SString strClumpedCommand; if ( szArguments && szArguments [ 0 ] ) strClumpedCommand.Format ( "%s %s", szCommandBufferPointer, szArguments ); else strClumpedCommand = szCommandBufferPointer; // Convert to Unicode, and clamp it to a maximum command length std::wstring strClumpedCommandUTF = MbUTF8ToUTF16(strClumpedCommand.c_str()); strClumpedCommandUTF = strClumpedCommandUTF.substr(0,MAX_COMMAND_LENGTH); strClumpedCommand = UTF16ToMbUTF8(strClumpedCommandUTF); g_pClientGame->GetRegisteredCommands ()->ProcessCommand ( szCommandBufferPointer, szArguments ); // Call the onClientConsole event Arguments.PushString ( strClumpedCommand ); // Call the event on the local player's onClientConsole first if ( g_pClientGame->GetLocalPlayer () ) g_pClientGame->GetLocalPlayer ()->CallEvent ( "onClientConsole", Arguments, true ); // Write the chatlength and the content NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream (); if ( !pBitStream ) return false; // Write it to the bitstream pBitStream->Write ( strClumpedCommand.c_str(), static_cast < int > ( strlen ( strClumpedCommand.c_str() ) ) ); // Send the packet to the server and free it g_pNet->SendPacket ( PACKET_ID_COMMAND, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED, PACKET_ORDERING_CHAT ); g_pNet->DeallocateNetBitStream ( pBitStream ); return true; } else { // Call our comand-handlers for core-executed commands too g_pClientGame->GetRegisteredCommands ()->ProcessCommand ( szCommand, szArguments ); } return false; }
int CLuaFunctionDefs::SetBrowserAjaxHandler ( lua_State* luaVM ) { // bool setBrowserAjaxHandler ( browser browser, string URL[, function callback] ) CClientWebBrowser* pWebBrowser; SString strURL; CLuaFunctionRef callbackFunction; CScriptArgReader argStream ( luaVM ); argStream.ReadUserData ( pWebBrowser ); argStream.ReadString ( strURL ); if ( argStream.NextIsNil () || argStream.NextIsNone () ) { if ( !argStream.HasErrors () ) { lua_pushboolean ( luaVM, pWebBrowser->RemoveAjaxHandler ( strURL ) ); return 1; } else m_pScriptDebugging->LogCustom ( luaVM, argStream.GetFullErrorMessage () ); } else { argStream.ReadFunction ( callbackFunction ); argStream.ReadFunctionComplete (); if ( !argStream.HasErrors () ) { CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine ( luaVM ); if ( pLuaMain && VERIFY_FUNCTION ( callbackFunction ) ) { CResource* pResource = pLuaMain->GetResource (); CResourceManager * pResourceManager = m_pResourceManager; auto netId = pResource->GetNetID (); bool bResult = pWebBrowser->AddAjaxHandler ( strURL, [=] ( std::vector<SString>& vecGet, std::vector<SString>& vecPost ) -> const SString { // Make sure the resource is still running if ( !pResourceManager->Exists ( pResource ) || pResource->GetNetID() != netId ) { return ""; } // Make sure the function is valid if ( VERIFY_FUNCTION ( callbackFunction ) ) { CLuaArguments arguments; CLuaArguments getArguments; CLuaArguments postArguments; for ( auto&& param : vecGet ) getArguments.PushString ( param ); for ( auto&& param : vecPost ) postArguments.PushString ( param ); arguments.PushTable ( &getArguments ); arguments.PushTable ( &postArguments ); CLuaArguments result; arguments.Call ( pLuaMain, callbackFunction, &result ); if ( result.Count () == 0 ) return ""; CLuaArgument* returnedValue = *result.IterBegin (); if ( returnedValue->GetType () == LUA_TSTRING ) return returnedValue->GetString (); else return ""; } else return ""; } ); lua_pushboolean ( luaVM, bResult ); return 1; } } else m_pScriptDebugging->LogCustom ( luaVM, argStream.GetFullErrorMessage () ); } lua_pushboolean ( luaVM, false ); return 1; }
//////////////////////////////////////////////////////////// // // CClientSound::Process3D // // Update position and velocity and pass on the BASS for processing. // m_pAudio->DoPulse needs to be called for non-3D sounds also. // //////////////////////////////////////////////////////////// void CClientSound::Process3D ( const CVector& vecPlayerPosition, const CVector& vecCameraPosition, const CVector& vecLookAt ) { // Update 3D things if required if ( m_b3D ) { // Update our position and velocity if we're attached CClientEntity* pAttachedToEntity = GetAttachedTo (); if ( pAttachedToEntity ) { GetPosition( m_vecPosition ); DoAttaching (); CVector vecVelocity; if ( CStaticFunctionDefinitions::GetElementVelocity ( *pAttachedToEntity, vecVelocity ) ) SetVelocity ( vecVelocity ); // Update our spatial data position UpdateSpatialData (); } } // If the sound isn't active, we don't need to process it // Moved after 3D updating as the streamer didn't know the position changed if a sound isn't streamed in when attached. if ( !m_pAudio ) return; m_pAudio->DoPulse ( vecPlayerPosition, vecCameraPosition, vecLookAt ); // Trigger script events for things SSoundEventInfo eventInfo; while ( m_pAudio->GetQueuedEvent ( eventInfo ) ) { if ( eventInfo.type == SOUND_EVENT_FINISHED_DOWNLOAD ) { CLuaArguments Arguments; Arguments.PushNumber ( eventInfo.dNumber ); CallEvent ( "onClientSoundFinishedDownload", Arguments, true ); OutputDebugLine ( SString ( "[ClientSound] onClientSoundFinishedDownload %f", eventInfo.dNumber ) ); } else if ( eventInfo.type == SOUND_EVENT_CHANGED_META ) { CLuaArguments Arguments; Arguments.PushString ( eventInfo.strString ); CallEvent ( "onClientSoundChangedMeta", Arguments, true ); OutputDebugLine ( SString ( "[ClientSound] onClientSoundChangedMeta %s", *eventInfo.strString ) ); } else if ( eventInfo.type == SOUND_EVENT_STREAM_RESULT ) { // Call onClientSoundStream LUA event CLuaArguments Arguments; Arguments.PushBoolean ( eventInfo.bBool ); Arguments.PushNumber ( eventInfo.dNumber ); if ( !eventInfo.strString.empty () ) Arguments.PushString ( eventInfo.strString ); CallEvent ( "onClientSoundStream", Arguments, true ); OutputDebugLine ( SString ( "[ClientSound] onClientSoundStream %d %f %s", eventInfo.bBool, eventInfo.dNumber, *eventInfo.strString ) ); } else if ( eventInfo.type == SOUND_EVENT_BEAT ) { CLuaArguments Arguments; Arguments.PushNumber ( eventInfo.dNumber ); CallEvent ( "onClientSoundBeat", Arguments, true ); } } }
void CScriptDebugging::LogString ( const char* szPrePend, lua_State* luaVM, const char* szMessage, unsigned int uiMinimumDebugLevel, unsigned char ucRed, unsigned char ucGreen, unsigned char ucBlue ) { SString strText; lua_Debug debugInfo; // Initialize values for onClientDebugMessage SString strMsg = szMessage; SString strFile = ""; int iLine = -1; // Get a VM from somewhere if ( !luaVM && !m_LuaMainStack.empty () ) luaVM = m_LuaMainStack.back ()->GetVM (); for ( int level = 1; level < 3; level++ ) { if ( luaVM && lua_getstack ( luaVM, level, &debugInfo ) ) { lua_getinfo ( luaVM, "nlS", &debugInfo ); // Make sure this function isn't defined in a string (eg: from runcode) if ( debugInfo.source[0] == '@' ) { // Get and store the location of the debug message strFile = debugInfo.source + 1; iLine = debugInfo.currentline; // Populate a message to print/send (unless "info" type) if ( uiMinimumDebugLevel < 3 ) strText = SString ( "%s%s:%d: %s", szPrePend, strFile.c_str (), debugInfo.currentline, szMessage ); // if the file isn't empty, stop trying any other levels break; } else { strFile = debugInfo.short_src; if ( uiMinimumDebugLevel < 3 ) strText = SString ( "%s%s %s", szPrePend, szMessage, strFile.c_str () ); if ( strFile != "[string \"?\"]" ) // if the file isn't empty, stop trying any other levels break; } } else { strText = SString ( "%s%s", szPrePend, szMessage ); // no point in trying other levels break; } } // Create a different message if type is "INFO" if ( uiMinimumDebugLevel > 2 ) strText = SString ( "%s%s", szPrePend, szMessage ); if ( !m_bTriggeringOnClientDebugMessage ) { m_bTriggeringOnClientDebugMessage = true; // Prepare onClientDebugMessage CLuaArguments Arguments; Arguments.PushString ( strMsg.c_str ( ) ); Arguments.PushNumber ( uiMinimumDebugLevel ); // Push the file name (if any) if ( strFile.length ( ) > 0 ) Arguments.PushString ( strFile.c_str ( ) ); else Arguments.PushNil ( ); // Push the line (if any) if ( iLine > -1 ) Arguments.PushNumber ( iLine ); else Arguments.PushNil ( ); // Call onClientDebugMessage g_pClientGame->GetRootEntity ( )->CallEvent ( "onClientDebugMessage", Arguments, false ); m_bTriggeringOnClientDebugMessage = false; } // Log it to the file if enough level if ( m_uiLogFileLevel >= uiMinimumDebugLevel ) { PrintLog ( strText ); } switch ( uiMinimumDebugLevel ) { case 1: ucRed = 255, ucGreen = 0, ucBlue = 0; break; case 2: ucRed = 255, ucGreen = 128, ucBlue = 0; break; case 3: ucRed = 0, ucGreen = 255, ucBlue = 0; break; } #ifdef MTA_DEBUG if ( !g_pCore->IsDebugVisible () ) return; #endif g_pCore->DebugEchoColor ( strText, ucRed, ucGreen, ucBlue ); }
int CLuaFunctionDefs::GetCTime ( lua_State* luaVM ) { // table getRealTime( [int seconds = current], bool localTime = true ) time_t timer; time ( &timer ); bool bLocalTime = true; CScriptArgReader argStream ( luaVM ); if ( argStream.NextCouldBeNumber () ) { argStream.ReadNumber ( timer ); if ( timer < 0 ) { argStream.SetCustomError ( "seconds cannot be negative" ); } } if ( argStream.NextIsBool () ) argStream.ReadBool ( bLocalTime ); tm * time; if ( bLocalTime ) time = localtime ( &timer ); else time = gmtime ( &timer ); if ( time == NULL ) argStream.SetCustomError ( "seconds is out of range" ); if ( argStream.HasErrors () ) { m_pScriptDebugging->LogCustom ( luaVM, argStream.GetFullErrorMessage () ); lua_pushboolean ( luaVM, false ); return 1; } CLuaArguments ret; ret.PushString ( "second" ); ret.PushNumber ( time->tm_sec ); ret.PushString ( "minute" ); ret.PushNumber ( time->tm_min ); ret.PushString ( "hour" ); ret.PushNumber ( time->tm_hour ); ret.PushString ( "monthday" ); ret.PushNumber ( time->tm_mday ); ret.PushString ( "month" ); ret.PushNumber ( time->tm_mon ); ret.PushString ( "year" ); ret.PushNumber ( time->tm_year ); ret.PushString ( "weekday" ); ret.PushNumber ( time->tm_wday ); ret.PushString ( "yearday" ); ret.PushNumber ( time->tm_yday ); ret.PushString ( "isdst" ); ret.PushNumber ( time->tm_isdst ); ret.PushString ( "timestamp" ); ret.PushNumber ( (double) timer ); ret.PushAsTable ( luaVM ); return 1; }
void CScriptDebugging::LogString ( const char* szPrePend, const SLuaDebugInfo& luaDebugInfo, const char* szMessage, unsigned int uiMinimumDebugLevel, unsigned char ucRed, unsigned char ucGreen, unsigned char ucBlue ) { SString strText = ComposeErrorMessage( szPrePend, luaDebugInfo, szMessage ); // Create a different message if type is "INFO" if ( uiMinimumDebugLevel > 2 ) strText = SString ( "%s%s", szPrePend, szMessage ); // Check whether onDebugMessage is currently being triggered if ( !m_bTriggeringOnDebugMessage ) { // Make sure the state of onDebugMessage being triggered can be retrieved later m_bTriggeringOnDebugMessage = true; // Prepare onDebugMessage CLuaArguments Arguments; Arguments.PushString ( szMessage ); Arguments.PushNumber ( uiMinimumDebugLevel ); // Push the file name (if any) if ( !luaDebugInfo.strFile.empty() ) Arguments.PushString ( luaDebugInfo.strFile ); else Arguments.PushNil ( ); // Push the line (if any) if ( luaDebugInfo.iLine != INVALID_LINE_NUMBER ) Arguments.PushNumber ( luaDebugInfo.iLine ); else Arguments.PushNil ( ); // Call onDebugMessage g_pGame->GetMapManager ( )->GetRootElement ( )->CallEvent ( "onDebugMessage", Arguments ); // Reset trigger state, so onDebugMessage can be called again at a later moment m_bTriggeringOnDebugMessage = false; } // Log it to the file if enough level if ( m_uiLogFileLevel >= uiMinimumDebugLevel ) { PrintLog ( strText ); } // Log to console CLogger::LogPrintf( "%s\n", strText.c_str () ); #if 0 // Not sure what this is for, seems pretty useless if ( m_uiHtmlLogLevel >= uiMinimumDebugLevel ) { if ( luaVM ) { CLuaMain* pLuaMain = g_pGame->GetLuaManager()->GetVirtualMachine ( luaVM ); if ( pLuaMain ) { CResourceFile * file = pLuaMain->GetResourceFile(); if ( file && file->GetType() == CResourceHTMLItem::RESOURCE_FILE_TYPE_HTML ) { CResourceHTMLItem * html = (CResourceHTMLItem *)file; html->AppendToPageBuffer ( strText ); html->AppendToPageBuffer ( "<br/>" ); } } } } #endif // Tell the players Broadcast ( CDebugEchoPacket ( strText, uiMinimumDebugLevel, ucRed, ucGreen, ucBlue ), uiMinimumDebugLevel ); }
int CLuaFunctionDefs::Get ( lua_State* luaVM ) { CResource* pResource = m_pLuaManager->GetVirtualMachine ( luaVM )->GetResource (); SString strSetting; CLuaArguments Args; CScriptArgReader argStream ( luaVM ); argStream.ReadString ( strSetting ); if ( !argStream.HasErrors () ) { unsigned int uiIndex = 0; bool bDeleteNode; // Extract attribute name if setting to be gotten has three parts i.e. resname.settingname.attributename SString strAttribute = "value"; vector < SString > Result; strSetting.Split ( ".", Result ); if ( Result.size () == 3 && Result[2].length () ) { strAttribute = Result[2]; } // Get the setting CXMLNode *pSubNode, *pNode = g_pGame->GetSettings ()->Get ( pResource->GetName ().c_str (), strSetting.c_str (), bDeleteNode ); // Only proceed if we have a valid node if ( pNode ) { // Argument count unsigned int uiArgCount = 1; // See if we need to return a table with single or multiple entries if ( pNode->GetSubNodeCount () == 0 ) { // See if required attribute exists CXMLAttribute *pAttribute = pNode->GetAttributes ().Find ( strAttribute.c_str () ); if ( !pAttribute ) { if ( bDeleteNode ) delete pNode; lua_pushboolean ( luaVM, false ); return 1; } // We only have a single entry for a specific setting, so output a string const std::string& strDataValue = pAttribute->GetValue (); if ( !Args.ReadFromJSONString ( strDataValue.c_str () ) ) { // No valid JSON? Parse as plain text Args.PushString ( strDataValue ); } Args.PushArguments ( luaVM ); uiArgCount = Args.Count (); /* Don't output a table because although it is more consistent with the multiple values output below, ** due to lua's implementation of associative arrays (assuming we use the "setting-name", "value" key-value pairs) ** it would require the scripter to walk through an array that only has a single entry which is a Bad Thing, performance wise. ** PUSH_SETTING ( pNode ); Args.PushAsTable ( luaVM ); **/ } else { // We need to return multiply entries, so push all subnodes while ( ( pSubNode = pNode->FindSubNode ( "setting", uiIndex++ ) ) ) { CXMLAttributes& attributes = pSubNode->GetAttributes (); Args.PushString ( attributes.Find ( "name" )->GetValue () ); const std::string& strDataValue = attributes.Find ( "value" )->GetValue (); if ( !Args.ReadFromJSONString ( strDataValue.c_str () ) ) { Args.PushString ( strDataValue ); } } // Push a table and return Args.PushAsTable ( luaVM ); } // Check if we have to delete the node if ( bDeleteNode ) delete pNode; return uiArgCount; } } else m_pScriptDebugging->LogCustom ( luaVM, argStream.GetFullErrorMessage () ); lua_pushboolean ( luaVM, false ); return 1; }
void CRPCFunctions::CursorEvent ( NetBitStreamInterface & bitStream ) { SMouseButtonSync button; unsigned char ucButton; CVector2D vecCursorPosition; unsigned short usX; unsigned short usY; SPositionSync position ( false ); CVector vecPosition; bool bHasCollisionElement; ElementID elementID; if ( bitStream.Read ( &button ) && bitStream.ReadCompressed ( usX ) && bitStream.ReadCompressed ( usY ) && bitStream.Read ( &position ) && bitStream.ReadBit ( bHasCollisionElement ) && ( !bHasCollisionElement || bitStream.ReadCompressed ( elementID ) ) ) { ucButton = button.data.ucButton; vecCursorPosition.fX = static_cast < float > ( usX ); vecCursorPosition.fY = static_cast < float > ( usY ); vecPosition = position.data.vecPosition; if ( !bHasCollisionElement ) elementID = INVALID_ELEMENT_ID; } else return; if ( m_pSourcePlayer->IsJoined () ) { // Get the button and state const char* szButton = NULL; const char* szState = NULL; switch ( ucButton ) { case 0: szButton = "left"; szState = "down"; break; case 1: szButton = "left"; szState = "up"; break; case 2: szButton = "middle"; szState = "down"; break; case 3: szButton = "middle"; szState = "up"; break; case 4: szButton = "right"; szState = "down"; break; case 5: szButton = "right"; szState = "up"; break; } if ( szButton && szState ) { CElement* pElement = CElementIDs::GetElement ( elementID ); if ( pElement ) { // Call the onElementClicked event CLuaArguments Arguments; Arguments.PushString ( szButton ); Arguments.PushString ( szState ); Arguments.PushElement ( m_pSourcePlayer ); Arguments.PushNumber ( vecPosition.fX ); Arguments.PushNumber ( vecPosition.fY ); Arguments.PushNumber ( vecPosition.fZ ); pElement->CallEvent ( "onElementClicked", Arguments ); } // Call the onPlayerClick event CLuaArguments Arguments; Arguments.PushString ( szButton ); Arguments.PushString ( szState ); if ( pElement ) Arguments.PushElement ( pElement ); else Arguments.PushNil (); Arguments.PushNumber ( vecPosition.fX ); Arguments.PushNumber ( vecPosition.fY ); Arguments.PushNumber ( vecPosition.fZ ); Arguments.PushNumber ( vecCursorPosition.fX ); Arguments.PushNumber ( vecCursorPosition.fY ); m_pSourcePlayer->CallEvent ( "onPlayerClick", Arguments ); // TODO: iterate server-side element managers for the click events, eg: colshapes } } }