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 );
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.