Jump to content

Modloader System by madex


yoya99

Recommended Posts

Good day,

I am currently resorting on the moddownloader created by xXMADEXx in order to load large sized vehicle replacments. The problem I want to face up to is that every server player needs to activate the replacements with a command /mods (a gui opens up). I would like to modify this, resulting in making the mods useable automatically right after every single one is downloaded. For example: I have currenty one car mod. After it finished downloading, I need to type the comman /mods to enable the replacement over the GUI. Can' t it just activate itself without typing any command?

Thanks in advance for hints

 

Link to comment

I understand that, but how to adapt these function into the moddownloader system made by xxxmadexx

 

Downloader = { }
Downloader.Mods = { }
Downloader.Files = { }
Downloader.isRenderText = false;
Downloader.gotResponse = false;

-- Downloader Constructor
function Downloader:Downloader ( )

end 

-- Downloader:RequestList -> Used to request vehicle mod list from server
function Downloader:RequestList ( )
	triggerServerEvent ( "ModDownloader:RequestFilesFromServer", localPlayer, localPlayer );
end 

-- Downloader:GetList -> Used to get the mods list downloaded from server
function Downloader:GetList ( )
	return Downloader.Mods;
end 

-- Downloader:HandleRequest -> Used to handle response from the server for the mod list
function Downloader.HandleResponse ( list )
	Downloader.gotResponse = true;
	Downloader.Mods = list;
	Mods:PhraseList ( );
end 
addEvent ( "ModDownloader:OnServerSendClientModList", true );
addEventHandler ( "ModDownloader:OnServerSendClientModList", root, Downloader.HandleResponse );


function Downloader:AddDownload ( src )
	if ( Downloader.Files [ src ] ) then 
		return false;
	end 
	
	Downloader.Files [ src ] = true;
	
	if ( not Downloader.isRenderText ) then 
		Downloader.isRenderText = true;
		addEventHandler ( "onClientRender", root, Downloader.onClientRender );
	end 
	
	local b = downloadFile ( src )
	if ( not b ) then 
		Downloader.onFinish ( src, false );
	end 
	
	return b
end 

function Downloader:GetDownloads ( )
	return Downloader.Files;
end

function Downloader.onFinish ( file, success )
	if ( Downloader.Files [ file ] ) then 
		Downloader.Files [ file ] = nil;
	end 
	
	if ( success ) then 
		outputDebugString ( file.." has been downloaded!" );
	else 
		outputDebugString ( file .." has failed to download!" );
		outputChatBox ( "Failed to download file '"..tostring(file).."'", 255, 0, 0 );
	end
	
	if ( table.len ( Downloader:GetDownloads ( ) ) == 0 and Downloader.isRenderText ) then 
		Downloader.isRenderText = false;
		removeEventHandler ( "onClientRender", root, Downloader.onClientRender );
	end
end 
addEventHandler ( "onClientFileDownloadComplete", root, Downloader.onFinish );

local sx, sy = guiGetScreenSize ( );
function Downloader.onClientRender ( )
	dxDrawText ( "Downloading "..tostring ( table.len(Downloader:GetDownloads()) ).." files...", 0, 0, sx/1.1+2, sy/1.1+2, tocolor ( 0, 0, 0, 200 ), 2, "default-bold", "right", "bottom" );
	dxDrawText ( "Downloading "..tostring ( table.len(Downloader:GetDownloads()) ).." files...", 0, 0, sx/1.1, sy/1.1, tocolor ( 0, 255, 255, 200 ), 2, "default-bold", "right", "bottom" );
end 
function table.len ( tb )
	local l = 0;
	for _ in pairs ( tb ) do 
		l = l + 1;
	end 
	return l;
end 

local __outputDebugString = _G['outputDebugString'];
function outputDebugString ( msg, r, g, b )
	if not r then r = 0 end 
	if not g then g = 255 end
	if not b then b = 0 end 
	__outputDebugString ( msg, 0, r, g, b );
end 
local sx, sy = guiGetScreenSize ( );

Inter = { };
Inter.btn = { };
Inter.grid = { };

Inter.window = guiCreateWindow((sx/2)-333, (sy/2)-333, 666, 510, "Mod Downloader Interface", false)
guiWindowSetSizable(Inter.window, false)
Inter.window.visible = false;
Inter.grid.list = guiCreateGridList(9, 24, 643, 364, false, Inter.window)
guiGridListAddColumn(Inter.grid.list, "Replace", 0.3)
guiGridListAddColumn(Inter.grid.list, "New", 0.35)
guiGridListAddColumn(Inter.grid.list, "Enabled", 0.15)
guiGridListAddColumn(Inter.grid.list, "Status", 0.15)
guiGridListSetSortingEnabled ( Inter.grid.list, false );
Inter.btn.enable = guiCreateButton(13, 397, 136, 39, "Enable", false, Inter.window)
Inter.btn.enableAll = guiCreateButton(13, 446, 136, 39, "Enable All", false, Inter.window)
Inter.btn.disable = guiCreateButton(159, 397, 136, 39, "Disable", false, Inter.window)
Inter.btn.disableAll = guiCreateButton(159, 446, 136, 39, "Disable All", false, Inter.window)
Inter.btn.refresh = guiCreateButton(516, 397, 136, 39, "Refresh", false, Inter.window)
Inter.btn.close = guiCreateButton(516, 446, 136, 39, "Exit", false, Inter.window)

function Inter.open ( b )
	if ( b == Inter.window.visible ) then return false; end
	
	Inter.window.visible = b;
	showCursor ( b );
	
	if ( b ) then 
		Inter.btn.enable.enabled = false;
		Inter.btn.disable.enabled = false;
		
		Inter.refresh ( );
		addEventHandler ( "onClientGUIClick", root, Inter.onEvent );
	else 
		removeEventHandler ( "onClientGUIClick", root, Inter.onEvent );
	end 
end 

function Inter.onEvent ( )

		if ( source == Inter.btn.close ) then 
			Inter.open ( false );
		elseif ( source == Inter.btn.refresh ) then 
			Inter.refresh ( );
		elseif ( source == Inter.grid.list ) then 
			local row, _ = guiGridListGetSelectedItem ( Inter.grid.list );
			Inter.btn.enable.enabled = ( ( row ~= -1 ) and ( guiGridListGetItemText( Inter.grid.list, row, 3 ) == "No" ) );
			Inter.btn.disable.enabled = ( ( row ~= -1 ) and ( guiGridListGetItemText( Inter.grid.list, row, 3 ) == "Yes" ) );
		elseif ( source == Inter.btn.enableAll or source == Inter.btn.disableAll ) then 
			if ( localPlayer:getOccupiedVehicle ( ) ) then 
				return outputChatBox ( "Please exit your vehicle before enabling or disabling mods", 255, 255, 0 );
			end
			
			for i, v in pairs ( Downloader.Mods ) do 
				Mods.SetModEnabled ( i, source == Inter.btn.enableAll );
			end 
			
			Inter.refresh ( );
		
		elseif ( source == Inter.btn.enable or source == Inter.btn.disable ) then 
			if ( localPlayer:getOccupiedVehicle ( ) ) then 
				return outputChatBox ( "Please exit your vehicle before enabling or disabling mods", 255, 255, 0 );
			end
			
			local row, _ = guiGridListGetSelectedItem ( Inter.grid.list );
			if ( row == - 1 ) then return end 
			Mods.SetModEnabled ( guiGridListGetItemText ( Inter.grid.list, row, 2 ), source == Inter.btn.enable  );
			Inter.refresh ( );
		end 
		
	--end 
end 

function Inter.refresh ( )
	local _row, col = guiGridListGetSelectedItem ( Inter.grid.list );

	guiGridListClear ( Inter.grid.list );
	
	local t = Downloader.Mods;
	local skins = { }
	local vehs = { }
	local weaps = { }
	
	-- Loop the downloaded mods and seperate mod types
	for index, var in pairs ( t ) do 
		local t = tostring ( var.type ):lower ( );
		if ( t ==  "skins" ) then
			table.insert ( skins, var )
		elseif ( t == "vehicles" ) then 
			table.insert ( vehs, var ) 
		elseif ( t == "weapons" ) then
			table.insert ( weaps, var ) 
		end
	end 
	
	guiGridListSetItemText ( Inter.grid.list, guiGridListAddRow ( Inter.grid.list ), 1, "Vehicle Mods", true, true )
	
	for i, v in pairs ( vehs ) do
		local r, g, b = 0, 255, 0 -- Assume its downloaded and ready
		local enabled = v.enabled or false 
		local status = "Ready";
		if ( not enabled ) then 
			r, g, b = 255, 0, 0
			enabled = "No";
		else 
			enabled = "Yes";
		end 
		
		if ( not File.exists ( v.txd ) or not File.exists ( v.dff ) ) then
			status = "Downloading";
			r, g, b = 255, 255, 0
		end 
		
		local row = guiGridListAddRow ( Inter.grid.list );
		guiGridListSetItemText ( Inter.grid.list, row, 1, getVehicleNameFromModel ( v.replace ), false, false );
		guiGridListSetItemText ( Inter.grid.list, row, 2, tostring ( v.name ), false, false );
		guiGridListSetItemText ( Inter.grid.list, row, 3, tostring ( enabled ), false, false );
		guiGridListSetItemText ( Inter.grid.list, row, 4, tostring ( status ), false, false );
		for i = 1, 4  do 
			guiGridListSetItemColor ( Inter.grid.list, row, i, r, g, b );
		end 
		
		if ( row == _row )then 
			guiGridListSetSelectedItem ( Inter.grid.list, row, col );
			triggerEvent ( "onClientGUIClick", Inter.grid.list );
		end 
	end 
	
	
	guiGridListSetItemText ( Inter.grid.list, guiGridListAddRow ( Inter.grid.list ), 1, "Weapon Mods", true, true )
		
	for i, v in pairs ( weaps ) do
		local r, g, b = 0, 255, 0 -- Assume its downloaded and ready
		local enabled = v.enabled or false 
		local status = "Ready";
		
		if ( not enabled ) then 
			r, g, b = 255, 0, 0
			enabled = "No";
		else 
			enabled = "Yes";
		end 
		
		if ( not File.exists ( v.txd ) or not File.exists ( v.dff ) ) then
			status = "Downloading";
			r, g, b = 255, 255, 0
		end 
		
		local row = guiGridListAddRow ( Inter.grid.list );
		guiGridListSetItemText ( Inter.grid.list, row, 1, engineGetModelNameFromID ( v.replace ) or tostring ( v.replace ), false, false );
		guiGridListSetItemText ( Inter.grid.list, row, 2, tostring ( v.name ), false, false );
		guiGridListSetItemText ( Inter.grid.list, row, 3, tostring ( enabled ), false, false );
		guiGridListSetItemText ( Inter.grid.list, row, 4, tostring ( status ), false, false );
		for i = 1, 4  do 
			guiGridListSetItemColor ( Inter.grid.list, row, i, r, g, b );
		end 
		
		if ( row == _row )then 
			guiGridListSetSelectedItem ( Inter.grid.list, row, col );
			triggerEvent ( "onClientGUIClick", Inter.grid.list );
		end 
	end 
	
	
	guiGridListSetItemText ( Inter.grid.list, guiGridListAddRow ( Inter.grid.list ), 1, "Skin Mods", true, true )
		
	for i, v in pairs ( skins ) do
		local r, g, b = 0, 255, 0 -- Assume its downloaded and ready
		local enabled = v.enabled or false 
		local status = "Ready";
		
		if ( not enabled ) then 
			r, g, b = 255, 0, 0
			enabled = "No";
		else 
			enabled = "Yes";
		end 
		
		if ( not File.exists ( v.txd ) or not File.exists ( v.dff ) ) then
			status = "Downloading";
			r, g, b = 255, 255, 0
		end 
		
		local row = guiGridListAddRow ( Inter.grid.list );
		guiGridListSetItemText ( Inter.grid.list, row, 1, tostring ( v.replace ), false, false );
		guiGridListSetItemText ( Inter.grid.list, row, 2, tostring ( v.name ), false, false );
		guiGridListSetItemText ( Inter.grid.list, row, 3, tostring ( enabled ), false, false );
		guiGridListSetItemText ( Inter.grid.list, row, 4, tostring ( status ), false, false );
		for i = 1, 4  do 
			guiGridListSetItemColor ( Inter.grid.list, row, i, r, g, b );
		end 
		
		if ( row == _row )then 
			guiGridListSetSelectedItem ( Inter.grid.list, row, col );
			triggerEvent ( "onClientGUIClick", Inter.grid.list );
		end 
	end 
end 

addCommandHandler ( "mods", function ( )
	if ( not Downloader.gotResponse ) then 
		outputChatBox ( "We're still waiting for the server to accept our request. Please wait", 255, 255, 0 );
		return false;
	end

	Inter.open ( not Inter.window.visible );
end );
-- Don't store txd and dff files in the XML - Prevent hackers from changing file names


Mods = { };
Mods.FromXML = { };

-- Mods Constructor
function Mods:Mods ( )
	Mods:PhraseXML ( );
	
	if ( isTimer ( checkServerTimer ) ) then 
		killTimer ( checkServerTimer );
	end 
	
	setTimer ( function ( )	-- Did the server have time to load the list??
		Downloader:RequestList ( ); -- Get list from server
	end, 500, 1 );
end 

function Mods:PhraseXML ( )
	-- Create the user cmods.xml for saving of enabled/disabled
	
	-- Create if it doesn't exist
	if ( not File.exists ( "@cmods.xml" ) ) then 
		local t = File.new ( "@cmods.xml" );
		t:write ( "<mods></mods>" );
		t:close ( );
	end 
	
	-- Attempt to load XML file
	local xml = XML.load ( "@cmods.xml" );
	
	-- if XML failed to load, delete it and try again 
	if ( not xml ) then 
		File.delete ( "@cmods.xml" );
		Mods:Mods ( );
		return
	end 
	
	-- If it exists, loop the children and collect info 
	for index, child in pairs ( xml.children ) do 
		-- Is it a mod child?
		if ( child.name == "mod" ) then 
			
			local name = child:getAttribute ( "name" );
			local enabled = child:getAttribute ( "enabled" );
			-- Do all of our attributes exist?
			if ( name and enabled ) then 
				-- Was this already loaded?
				if ( not Mods.FromXML [ name ] ) then 
					Mods.FromXML [ name ] = ( tostring ( enabled ):lower ( ) == "true" );
				else 
					child:destroy ( );
				end 
			else 
				child:destroy ( );
			end
		end 
	end
	
	-- Save and unload xml file
	xmlSaveFile ( xml );
	xmlUnloadFile ( xml );
end 

function Mods.SaveXML ( )
	if ( File.exists ( "@cmods.xml" ) ) then 
		File.delete ( "@cmods.xml" );
	end 
	
	local str= "<mods>\n	<!-- It's suggested to not edit this file -->\n %s \n</mods>";
	local _str = "";
	for i, v in pairs ( Downloader.Mods ) do 
		_str = _str .. "\n" .. string.format ( '<mod name="%s" enabled="%s" />', i, tostring ( v.enabled ) );
	end 
	
	local f = File.new ( "@cmods.xml" );
	f:write ( str:format ( _str ) );
	f:close ( );
	
end 
setTimer ( Mods.SaveXML, 5000000, 0 );
addEventHandler ( "onClientResourceStop", resourceRoot, Mods.SaveXML );


-- Mods:PhraseList -> Used to check mods list for enabled mods
function Mods:PhraseList ( )
	--Downloader.Mods = { }
	-- Loop through the list and find completed downloaded files
	for name, mod in pairs ( Downloader.Mods ) do 
		local txd = mod.txd;
		local dff = mod.dff;
		local replace = mod.replace;
		
		Downloader.Mods [ name ].enabled = false;
		
		-- Check if the txd file is downloaded
		local bothExist = false;
		if ( File.exists ( tostring ( txd ) ) ) then 
			-- if so, load it
			local temp = File( txd, true );
			-- is it out-dated?
			
			doDelete = ( tostring ( md5 ( temp:read ( temp.size ) ) ):lower ( ) ~= tostring ( mod.txd_hash ):lower( ) );
			temp:close ( );
			-- if outdated, then delete
			if ( doDelete ) then 
				File.delete ( txd );
				outputDebugString ( txd.." was deleted - hash doesn't match with server" );
				bothExist = false;
			else
				outputDebugString ( txd.." has been successfully listed" );
				bothExist = true;
			end 
		else 
			outputDebugString ( tostring ( txd ).. " not present - beginning download" );
			Downloader:AddDownload ( tostring ( txd ) );
		end 
		

		-- Check if the dff file is downloaded
		if ( File.exists ( tostring ( dff ) ) ) then 

			-- if so, load it
			local temp = File( dff, true );
			-- is it out-dated?
			doDelete = (  md5 ( temp:read ( temp.size ) ):lower() ~= mod.dff_hash:lower() );
			temp:close ( );
			-- if outdated, then delete
			if ( doDelete ) then 
				File.delete ( dff );
				outputDebugString ( dff.." was deleted - hash doesn't match with server" );
				bothExist = false;
			else 
				outputDebugString ( dff.." has been successfully listed" );
				if ( bothExist ) then 
					bothExist = true;
				end 
			end 
		else 
			outputDebugString ( tostring ( dff ).. " not present - beginning download" );
			Downloader:AddDownload ( tostring ( dff ) );
		end 
		
		if ( bothExist  ) then 
			--outputDebugString ( name.." - both files loaded. Enabled: "..tostring ( Mods.FromXML [ name ] ) );
			if ( Mods.FromXML [ name ] ) then 
				Mods.SetModEnabled ( name, true );
			end 
		end 
		
	end 
end 


function Mods.SetModEnabled ( mod, enabled )
	if ( not Downloader.Mods [ mod ] ) then 
		return outputDebugString ( string.format ( "Attempted to enable mod '%s' - doesn't exist in Downloader.Mods", mod ), 255, 0,  0 );
	end 
	
	if ( 
		( enabled and Downloader.Mods [ mod ].enabled ) or 
		( not enabled and not Downloader.Mods [ mod ].enabled ) 
	) then 
		-- check current state
		return false; -- cancel if is already current state 
	end 
	
	Downloader.Mods [ mod ].enabled = enabled;
	
	if ( enabled ) then 
		if ( 
			File.exists ( Downloader.Mods [ mod ].dff ) and 
			File.exists ( Downloader.Mods [ mod ].txd ) 
		) then 
		
			local txd = engineLoadTXD ( Downloader.Mods [ mod ].txd )
			engineImportTXD ( txd, Downloader.Mods [ mod ].replace )
			local dff = engineLoadDFF ( Downloader.Mods [ mod ].dff, 0 )
			engineReplaceModel ( dff, Downloader.Mods [ mod ].replace )
		
		end 
	else 
		engineRestoreModel ( Downloader.Mods [ mod ].replace );
	end 
	
end 



--addEventHandler ( "onClientResourceStart", resourceRoot, Mods.Mods );
addEvent ( "ModLoader:OnServerReadyAccepts", true );
addEventHandler ( "ModLoader:OnServerReadyAccepts", root, Mods.Mods );

checkServerTimer = setTimer ( function ( )
	outputDebugString ( "Sending server request" );
	triggerServerEvent ( "ModDownloader:TestServerReadyForClient", localPlayer );
end, 2000, 0 )

these above are client files

 

these are server side files:

Loader = { }
local mods = { }
local isReady = false;

--[[
Format:
mods['New Mod Name'] = {
	name = "New Mod Name",
	dff = "file_to_dff.dff",
	txd = "file_to_txd.txd",
	replace = vehicle_replace_id,
	dff_hash = MD5_of_dff_file,
	txd_hash = MD5_of_txd_file
}
]]

-- Loader Constructor 
function Loader:Loader ( )
	mods = { }
	if ( not ( File.exists ( "smods.xml" ) ) ) then 
		-- File functions are a lot easier to use than XML functions
		
		-- smods.xml doesnt exist - create new
		local t = File.new ( "smods.xml" );
		local str = [[
<mods>
    
    <!-- 
		
		ADDING CUSTOM VEHICLES
		-----------------------------------------------------------------------------------
		This is the mod list file.
		This file is used to get the modded files for the clients
		Add your mod by adding:
		<mod name="Modded Vehicle Name" txd="path to txd file" dff="path to dff file" replace="replace vehicle id" />
		
		name: This is the name of the new vehicle, the name that the clients will see
		txd: This is the load path for the modded (don't include "mods/vehicles") skin txd file inside mods folder 
		dff: This is the load path for the modded (don't include "mods/vehicles") skin dff file inside mods folder
		replace: The vehicle replace ID. Find GTA SA vehicle ids @ https://wiki.multitheftauto.com/wiki/Vehicle_IDs 
		-----------------------------------------------------------------------------------
	
	
    <vehicles>
        <!-- Examples (Won't work because you don't have the txd/dff files) 
         <mod name="Alpha123" txd="alpha.txd" dff="alpha.dff" replace="602" />
		
    </vehicles>

    
    <!-- 
		
		ADDING CUSTOM SKINS
		-----------------------------------------------------------------------------------
		This is the mod list file.
		This file is used to get the modded files for the clients
		Add your mod by adding:
		<mod name="Modded Skin Name" txd="path to txd file" dff="path to dff file" replace="replace skin id" />
		
		name: This is the name of the new skin, the name that the clients will see
		txd: This is the load path for the modded (don't include "mods/skins") skin txd file inside mods folder 
		dff: This is the load path for the modded (don't include "mods/skins") skin dff file inside mods folder
		replace: The skin replace ID. Find GTA SA skin ids @ https://wiki.sa-mp.com/wiki/Skins:All
		-----------------------------------------------------------------------------------
		
	-->
    <skins>
        <!-- Examples (Won't work because you don't have the txd/dff files)
        <mod name="Kokoro Arsenal Clothes" txd="hfyri.txd" dff="hfyri.dff" replace="40" /> -->
		
    </skins>
    
    
    <!-- 
		
		ADDING CUSTOM WEAPONS
		-----------------------------------------------------------------------------------
		This is the mod list file.
		This file is used to get the modded files for the clients
		Add your mod by adding:
		<mod name="Modded Weapon Name" txd="path to txd file" dff="path to dff file" replace="replace weapon model" />
		
		name: This is the name of the new weapon, the name that the clients will see
		txd: This is the load path for the modded (don't include "mods/weapons") weapon txd file inside mods folder 
		dff: This is the load path for the modded (don't include "mods/weapons") weapon dff file inside mods folder
		replace: The weapon replace Model (NOT ID!!!!). Find GTA SA weapon models @ https://wiki.sa-mp.com/wiki/Weapons
		-----------------------------------------------------------------------------------
		
	-->
    <weapons>
        <!-- Examples (Won't work because you don't have the txd/dff files)
        <mod name="Improved Fire Extinguisher" txd="366.txd" dff="366.dff" replace="366" /> -->
		
    </weapons>
    
</mods>
]]
		t:write ( str );
		t:close ( );
		t = nil;
		
		outputDebugString ( "smods.xml wasn't detected, but has been created!" );
		
	end 
	
	local metaFiles = { }
	local meta = XML.load ( "meta.xml" );
	
	for i, v in pairs ( meta.children ) do 
		if ( v.name == "file" and v:getAttribute ( "src" ) ) then 
			metaFiles [ v:getAttribute ( "src" ) ] = true;
		end 
	end 
	
	
	-- Load server-side mod list file (smods.xml)
	local xml = XML.load ( "smods.xml" );
	
	-- Check to make sure the XML was successfully loaded, if not delete & retry
	if ( not xml ) then 
		File.delete ( "smods.xml" );
		Loader:Loader ( );
		outputDebugString ( "smods.xml was unable to be loaded. Deleted file, retrying." );
		return;
	end 
	
	-- Loop all the "mod" children 
	local changesMade = false;
	for _index, _childNode in pairs ( xml.children ) do 

		for findex, childNode in pairs ( _childNode.children ) do
			
			local index = _index..":"..findex;
			
			local category = tostring ( childNode.parent.name ):lower();

			-- Confirm it's a "mod" child
			if ( childNode.name == "mod" ) then 
				-- Check if it has all the attributes
				local temp = { }
				temp.name = childNode:getAttribute ( "name" );
				temp.txd = childNode:getAttribute ( "txd" );
				temp.dff = childNode:getAttribute ( "dff" );
				temp.replace = childNode:getAttribute ( "replace" );
				temp.type = category;
				
				if ( temp.type == "skins" or temp.type == "vehicles" or temp.type == "weapons" ) then
					if ( temp.name and temp.txd and temp.dff and temp.replace ) then 
						-- confirm txd file exists 
						if ( File.exists ( "mods/" .. category .. "/" .. temp.txd ) ) then 
							temp.txd = "mods/" .. category .."/".. temp.txd;
							-- confirm dff file exists 
							if ( File.exists ( "mods/" .. category .. "/".. temp.dff ) ) then
								temp.dff =  "mods/" .. category .."/".. temp.dff;
								-- confirm replace is an integer, and a valid vehicle model 
								temp.replace = tonumber ( temp.replace );
								
								if ( 
									( temp.type == "vehicles" and 
									temp.replace and 
									math.floor ( temp.replace ) == temp.replace and 
									temp.replace >= 400 and 
									temp.replace <= 611 ) 
								or ( 
									temp.type == "skins" and 
									temp.replace and 
									math.floor ( temp.replace ) == temp.replace and 
									temp.replace >= 0 and 
									temp.replace <= 311 )
								or ( 
									temp.type == "weapons" and 
									temp.replace and 
									math.floor ( temp.replace ) == temp.replace and 
									temp.replace >= 321 and 
									temp.replace <= 372 )
								) then 
									
									
									-- Confirm there's actually a name 
									if ( temp.name:gsub ( " ", "" ) ~= "" ) then 
										-- Confirm name isn't already in use 
										if ( not mods [ temp.name ] ) then
											-- all checks are OK -- Encrypt and add to mod list 
											local tmp = File( temp.txd, true );
											temp.txd_hash = md5 ( tmp:read ( tmp.size ) );
											tmp:close ( );
											
											local tmp = File( temp.dff, true );
											temp.dff_hash = md5 ( tmp:read ( tmp.size ) );
											tmp:close ( );
											
											tmp = nil;
											
											if ( not metaFiles [ temp.txd ] ) then 
												outputDebugString ( temp.txd.. " not found in meta -- adding now" );
												
												local c = meta:createChild ( "file" );
												c:setAttribute ( 'src', temp.txd );
												c:setAttribute ( "download", "false" );
												changesMade = true;
											end 
											
											if ( not metaFiles [ temp.dff ] ) then 
												outputDebugString ( temp.dff.. " not found in meta -- adding now" );
												
												local c = meta:createChild ( "file" );
												c:setAttribute ( 'src', temp.dff );
												c:setAttribute ( "download", "false" );
												changesMade = true;
											end 
											
											
											outputDebugString ( "Successfully loaded mod #"..tostring(index).." - "..tostring ( temp.name ).. "!" );
											
											mods [ temp.name ] = temp;
										else 
											outputDebugString ( "Failed to load #"..tostring(index).." ("..tostring(temp.name)..") - Mod name already used" );
										end
											
									else
										outputDebugString ( "Failed to load #"..tostring(index).." ("..tostring(temp.name)..") - Invalid name" );
									end 
								else 
									if ( temp.type == "vehicles" ) then
										outputDebugString ( "Failed to load #"..tostring(index).." ("..tostring(temp.name)..") - replace must be an integer from 400-611" );
									elseif ( temp.type == "skins" ) then
										outputDebugString ( "Failed to load #"..tostring(index).." ("..tostring(temp.name)..") - replace must be an integer from 0-311" );
									elseif ( temp.type == "weapons" ) then
										outputDebugString ( "Failed to load #"..tostring(index).." ("..tostring(temp.name)..") - replace must be an integer from 331-371" );
									end
								end 
							else
								outputDebugString ( "Failed to load #"..tostring(index).." ("..tostring(temp.name)..") - dff file not found on server" );
							end 
						else 
							outputDebugString ( "Failed to load #"..tostring(index).." ("..tostring(temp.name)..") - txd file not found on server" );
						end 
					else 
						outputDebugString ( "Failed to load #"..tostring(index).." ("..tostring(temp.name)..") - not all attributes found" );
					end 
				else 
					outputDebugString ( "Failed to load #"..tostring(index).." ("..tostring(temp.name)..") - Unknown mod type, valid: skins, vehicles, weapons" );
				end 
			end 
		
		end
		
	end 
	
	
	xmlSaveFile( meta );
	xmlUnloadFile ( meta );
	
	xmlSaveFile ( xml );
	xmlUnloadFile ( xml );
	
	if ( changesMade ) then 
		outputDebugString ( "CHANGES HAVE BEEN MADE TO META.XML! RESTARTING RESOURCE...", 0, 255, 255, 255 );
		restartResource ( getThisResource ( ) );
		return;
	end 
	
	isReady = true;
	
	
end 

setTimer ( Loader.Loader, 2000, 1 );

-- Loader:HandleRequest -> Handles request of mod files from client
-- Sends client new mod list
function Loader:HandleRequest ( plr )
	triggerClientEvent ( source, "ModDownloader:OnServerSendClientModList", source, mods );
end 
addEvent ( "ModDownloader:RequestFilesFromServer", true );
addEventHandler ( "ModDownloader:RequestFilesFromServer", root, Loader.HandleRequest );

--addEventHandler ( "onResourceStart", resourceRoot, Loader.Loader );

addEvent ( "ModDownloader:TestServerReadyForClient", true );
addEventHandler ( "ModDownloader:TestServerReadyForClient", root, function ( )
	if ( not isReady ) then return; end -- Make sure we're ready for a connection
	triggerClientEvent ( source, "ModLoader:OnServerReadyAccepts", source );
end );
Quote

Updater = { }

function Updater.Notify ( msg )
	outputDebugString ( msg );
end 

function Updater.Check  ( )
	Updater.Notify ( "Checking for Mod Downloader updates ");
	local called = callRemote("https://community.multitheftauto.com/mta/resources.php", function(_, version) 
		if ( md5 ( tostring ( version ) ) ~= md5 ( getResourceInfo ( getThisResource(), "version" ) ) ) then 
			Updater.Notify ( "====================================" );
			Updater.Notify ( "= ModDownloader version doesn't match community" );
			Updater.Notify ( "====================================" );
			Updater.Notify ( "= Your version: ".. getResourceInfo ( getThisResource(), "version" ) )
			Updater.Notify ( "= Current version: ".. version )
			Updater.Notify ( "= View https://forum.multitheftauto.com/viewtopic.php?f=108&t=86587" );
			Updater.Notify ( "====================================" ); 
		end 
	end, "version", "moddownloader" )
	
	if not called then
		outputDebugString ( "FAILED TO CHECK VERSION UPDATE! PLEASE ALLOW ".. getResourceName(getThisResource()) .." ACCESS TO function.callRemote", 1 );
	end
end

Updater.Check ( );
setTimer ( Updater.Check, 1000000, 0 );

 

I really would appreciate your support. I would be willing to pay a little as a sign of my gratitude for your work.

Please help me.

 

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...