Skip to content

Commit

Permalink
Merge pull request #24 from Fernando-A-Rocha/2.0.1
Browse files Browse the repository at this point in the history
2.0.1
  • Loading branch information
Fernando-A-Rocha authored Jan 12, 2023
2 parents 0652c25 + 1cf0519 commit 6756a7d
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 81 deletions.
12 changes: 12 additions & 0 deletions newmodels/_config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ dataNames = {
-- useful for getting a vehicle's base model to fetch its original handling, etc
baseDataName = "baseID"

-- If you are 100% sure that the mods in mod_list.lua are valid, you can disable initial checks
-- for faster startup time
STARTUP_VERIFICATIONS = true

-- Newmodels will try to start these resources (identified by their names) after newmodels has started,
-- as well as stop them when newmodels is stopped
-- Usually these are resources that use newmodels and you want them to start only after newmodels,
-- and they can be stopped when newmodels stops
OTHER_RESOURCES = {
-- { name = "sampobj_reloaded", start = true, stop = true}
}

-- Mod file download feature
SHOW_DOWNLOADING = true -- display the downloading progress dxDraw
KICK_ON_DOWNLOAD_FAILS = true -- kick player if failed to download a file more than X times
Expand Down
25 changes: 24 additions & 1 deletion newmodels/client.lua
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,6 @@ function updateStreamedOutElement(source)
end
end
addEventHandler( "onClientElementStreamOut", root, function () updateStreamedOutElement(source) end)
addEventHandler( "onClientElementDestroy", root, function () updateStreamedOutElement(source) end) -- same behavior for stream out

-- (4) updateModelChangedElement
function updateModelChangedElement(source, oldModel, newModel)
Expand Down Expand Up @@ -686,6 +685,30 @@ function updateModelChangedElement(source, oldModel, newModel)
end
addEventHandler( "onClientElementModelChange", root, function (oldModel, newModel) updateModelChangedElement(source, oldModel, newModel) end)

function handleDestroyedElement()
if not received_modlist then return end
local et = getElementType(source)
if not isElementTypeSupported(et) then
return
end

local id = tonumber(getElementData(source, dataNames[et]))
if not (id) then return end -- doesn't have a custom model

if isCustomModID(id) then

local allocated_id = allocated_ids[id]
if not allocated_id then return end -- was not allocated

if not hasOtherElementsWithModel(source, id) then
freeElementCustomMod(id)
return
end
end
end
addEventHandler( "onClientElementDestroy", root, handleDestroyedElement)


-- Free waiting_queue memory when player leaves
addEventHandler( "onClientPlayerQuit", root,
function (reason)
Expand Down
12 changes: 6 additions & 6 deletions newmodels/meta.xml
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
<meta>
<!--
NEWMODELS VERSION 2.0
Enjoy <3
-->
<info author="Fernando" name="mta-add-models"
description="minimalistic library for adding new models to your server" version="2.0" type="script"/>
description="minimalistic library for adding new models to your server" version="2.0.1" type="script"/>

<!-- DOCUMENTATION:
https://github.com/Fernando-A-Rocha/mta-add-models
Expand Down Expand Up @@ -51,7 +47,6 @@
<script type="server" src="updater_s.lua"/>
<script type="server" src="mod_list.lua"/>
<script type="server" src="server.lua"/>
<script type="client" src="nando_decrypter"/>
<script type="client" src="client.lua"/>

<export type="shared" function="getModList"/>
Expand All @@ -62,6 +57,7 @@
<export type="shared" function="isCustomModID"/>

<export type="server" function="addExternalMod_IDFilenames"/>
<export type="server" function="addExternalMods_IDFilenames"/>
<export type="server" function="addExternalMod_CustomFilenames"/>
<export type="server" function="addExternalMods_CustomFileNames"/>
<export type="server" function="removeExternalMod"/>
Expand All @@ -72,6 +68,10 @@
<export type="client" function="isBusyDownloading"/>
<!-- Main Scripts END -->

<!-- NandoCrypt plugin script (optional - you can remove it, and edit _config.lua) -->
<script type="client" src="nando_decrypter"/>
<!-- NandoCrypt plugin END -->

<!-- testing scripts (optional - you can remove them) -->
<script type="server" src="testing_server.lua"/>
<script type="client" src="testing_client.lua"/>
Expand Down
238 changes: 165 additions & 73 deletions newmodels/server.lua
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,82 @@ function modCheckError(text)
return false
end

function verifyOneMod(mod, elementType, used_ids)
coroutine.yield()

-- 1. verify IDs
if not tonumber(mod.id) then
return modCheckError("Invalid mod ID '"..tostring(mod.id).."'")
else
if mod.id == 0 then
return modCheckError("Invalid mod ID '"..tostring(mod.id).."', must be >0")
end

if isDefaultID(false, mod.id) then
return modCheckError("Invalid mod ID '"..tostring(mod.id).."', must be out of the default GTA:SA and SAMP ID Range, see shared.lua isDefaultID")
end

for _,id in pairs(used_ids) do
if id == mod.id then
return modCheckError("Duplicated mod ID '"..id.."'")
end
end

table.insert(used_ids, mod.id)
end
if not tonumber(mod.base_id) then
return modCheckError("Invalid mod base ID '"..tostring(mod.base_id).."'")
else
if not isDefaultID(false, mod.base_id) then
return modCheckError("Invalid mod base ID '"..tostring(mod.base_id).."', must be a default GTA:SA ID")
end
end

-- 2. verify name
if not mod.name or type(mod.name)~="string" then

return modCheckError("Missing/Invalid mod name '"..tostring(mod.name).."' for mod ID "..mod.id)
end

-- 3. verify path
if (not mod.path) then

return modCheckError("Missing mod path '"..tostring(mod.path).."' for mod ID "..mod.id)
end
if not (type(mod.path)=="string" or type(mod.path)=="table") then

return modCheckError("Invalid mod path '"..tostring(mod.path).."' for mod ID "..mod.id)
end

-- 4. verify files exist
local ignoreTXD, ignoreDFF, ignoreCOL = mod.ignoreTXD, mod.ignoreDFF, mod.ignoreCOL
local paths
local path = mod.path
if type(path)=="table" then
paths = path
else
paths = getActualModPaths(path, mod.id)
end
for pathType, path2 in pairs(paths) do
if type(pathType) ~= "string" then
return modCheckError("Invalid path type '"..tostring(pathType).."' for mod ID "..mod.id)
end
if type(path2) ~= "string" then
return modCheckError("Invalid file path '"..tostring(pathType).."' for mod ID "..mod.id)
end
if (not fileExists(path2)) and ((ENABLE_NANDOCRYPT) and not fileExists(path2..NANDOCRYPT_EXT)) then
if (not ignoreTXD and pathType == "txd")
or (not ignoreDFF and pathType == "dff")
or ((not ignoreCOL) and elementType == "object" and pathType == "col") then

return modCheckError("File doesn't exist: '"..tostring(path2).."' for mod ID "..mod.id)
end
end
end

return true
end

-- verifies mapList, because people can fuck up sometimes :)
function doModListChecks()

Expand All @@ -237,74 +313,12 @@ function doModListChecks()

for k,mod in pairs(mods) do

-- 1. verify IDs
if not tonumber(mod.id) then
return modCheckError("Invalid mod ID '"..tostring(mod.id).."'")
else
if mod.id == 0 then
return modCheckError("Invalid mod ID '"..tostring(mod.id).."', must be >0")
end

if isDefaultID(false, mod.id) then
return modCheckError("Invalid mod ID '"..tostring(mod.id).."', must be out of the default GTA:SA and SAMP ID Range, see shared.lua isDefaultID")
end

for _,id in pairs(used_ids) do
if id == mod.id then
return modCheckError("Duplicated mod ID '"..id.."'")
end
end

table.insert(used_ids, mod.id)
end
if not tonumber(mod.base_id) then
return modCheckError("Invalid mod base ID '"..tostring(mod.base_id).."'")
else
if not isDefaultID(false, mod.base_id) then
return modCheckError("Invalid mod base ID '"..tostring(mod.base_id).."', must be a default GTA:SA ID")
end
end

-- 2. verify name
if not mod.name or type(mod.name)~="string" then

return modCheckError("Missing/Invalid mod name '"..tostring(mod.name).."' for mod ID "..mod.id)
end

-- 3. verify path
if (not mod.path) then

return modCheckError("Missing mod path '"..tostring(mod.path).."' for mod ID "..mod.id)
end
if not (type(mod.path)=="string" or type(mod.path)=="table") then

return modCheckError("Invalid mod path '"..tostring(mod.path).."' for mod ID "..mod.id)
end
local co = coroutine.create(verifyOneMod)
coroutine.resume(co, mod, elementType, used_ids)

-- 4. verify files exist
local ignoreTXD, ignoreDFF, ignoreCOL = mod.ignoreTXD, mod.ignoreDFF, mod.ignoreCOL
local paths
local path = mod.path
if type(path)=="table" then
paths = path
else
paths = getActualModPaths(path, mod.id)
end
for pathType, path2 in pairs(paths) do
if type(pathType) ~= "string" then
return modCheckError("Invalid path type '"..tostring(pathType).."' for mod ID "..mod.id)
end
if type(path2) ~= "string" then
return modCheckError("Invalid file path '"..tostring(pathType).."' for mod ID "..mod.id)
end
if (not fileExists(path2)) and ((ENABLE_NANDOCRYPT) and not fileExists(path2..NANDOCRYPT_EXT)) then
if (not ignoreTXD and pathType == "txd")
or (not ignoreDFF and pathType == "dff")
or ((not ignoreCOL) and elementType == "object" and pathType == "col") then

return modCheckError("File doesn't exist: '"..tostring(path2).."' for mod ID "..mod.id)
end
end
local _, result = coroutine.resume(co)
if not result then
return result
end
end
end
Expand All @@ -318,9 +332,29 @@ function (startedResource)

startTickCount = getTickCount()

-- STARTUP CHECKS
if doModListChecks() then
if (STARTUP_VERIFICATIONS) then

-- STARTUP CHECKS
if not doModListChecks() then return end

SERVER_READY = true -- all checks passed

else
SERVER_READY = true -- checks ignored
end

for k, v in ipairs(OTHER_RESOURCES) do
local name, start, stop = v.name, v.start, v.stop
if type(name)=="string" and start == true then
local res = getResourceFromName(name)
if res and getResourceState(res) == "loaded" then
if not startResource(res) then
outputDebugString("Failed to start resource '"..name.."' on "..resName.." res-start")
else
outputDebugString("Started resource '"..name.."' on "..resName.." res-start")
end
end
end
end
end)

Expand All @@ -336,13 +370,33 @@ function (stoppedResource, wasDeleted)
end
end

local willStart = {}
for k, v in ipairs(OTHER_RESOURCES) do
local name, start, stop = v.name, v.start, v.stop
if type(name)=="string" then
if start == true then
willStart[name] = true
end
if stop == true then
local res = getResourceFromName(name)
if res and getResourceState(res) == "running" then
if not stopResource(res) then
outputDebugString("Failed to stop resource '"..name.."' on "..resName.." res-stop")
else
outputDebugString("Stopped resource '"..name.."' on "..resName.." res-stop")
end
end
end
end
end

local notified = {}
for elementType,mods in pairs(modList) do
for k,mod in pairs(mods) do
local srcRes = mod.srcRes
if srcRes then
local res = getResourceFromName(srcRes)
if res and not notified[srcRes] then
if res and not notified[srcRes] and not willStart[srcRes] then

outputDebugString("Resource '"..srcRes.."' needs to be restarted because '"..resName.."' stopped", 0, 211, 255, 0)
notified[srcRes] = true
Expand Down Expand Up @@ -457,11 +511,42 @@ end



--[[
This function exists to avoid too many exports calls of the function below from
external resources to add mods from those
With this one you can just pass a table of mods and it calls that function for you
]]
function addExternalMods_IDFilenames(list) -- [Exported]
if type(list) ~= "table" then
return false, "Missing/Invalid 'list' table passed: "..tostring(list)
end
local countWorked = 0
for _, modInfo in ipairs(list) do
if type(modInfo) ~= "table" then
return false, "Missing/Invalid 'modInfo' table passed: "..tostring(modInfo)
end
local elementType, id, base_id, name, path, ignoreTXD, ignoreDFF, ignoreCOL, metaDownloadFalse = unpack(modInfo)

local co = coroutine.create(addExternalMod_IDFilenames)
coroutine.resume(co, elementType, id, base_id, name, path, ignoreTXD, ignoreDFF, ignoreCOL, metaDownloadFalse, true)
local _, worked, reason = coroutine.resume(co)
if worked then
countWorked = countWorked + 1
else
return false, "Aborting, one failed, reason: "..tostring(reason)
end
end
return countWorked
end

--[[
The difference between this function and addExternalMod_CustomFilenames is that
you pass a folder path in 'path' and it will search for ID.dff ID.txd etc
]]
function addExternalMod_IDFilenames(elementType, id, base_id, name, path, ignoreTXD, ignoreDFF, ignoreCOL, metaDownloadFalse) -- [Exported]
function addExternalMod_IDFilenames(elementType, id, base_id, name, path, ignoreTXD, ignoreDFF, ignoreCOL, metaDownloadFalse, usingCoroutine) -- [Exported]
if (usingCoroutine == true) then
coroutine.yield()
end

local sourceResName = getResourceName(sourceResource)
if sourceResName == resName then
Expand Down Expand Up @@ -581,7 +666,11 @@ function addExternalMods_CustomFileNames(list) -- [Exported]
if type(modInfo) ~= "table" then
return false, "Missing/Invalid 'modInfo' table passed: "..tostring(modInfo)
end
local worked, reason = addExternalMod_CustomFilenames(unpack(modInfo))
local elementType, id, base_id, name, path_dff, path_txd, path_col, ignoreTXD, ignoreDFF, ignoreCOL, metaDownloadFalse = unpack(modInfo)

local co = coroutine.create(addExternalMod_CustomFilenames)
coroutine.resume(co, elementType, id, base_id, name, path_dff, path_txd, path_col, ignoreTXD, ignoreDFF, ignoreCOL, metaDownloadFalse, true)
local _, worked, reason = coroutine.resume(co)
if worked then
countWorked = countWorked + 1
else
Expand All @@ -595,7 +684,10 @@ end
The difference between this function and addExternalMod_IDFilenames is that
you pass directly individual file paths for dff, txd and col files
]]
function addExternalMod_CustomFilenames(elementType, id, base_id, name, path_dff, path_txd, path_col, ignoreTXD, ignoreDFF, ignoreCOL, metaDownloadFalse) -- [Exported]
function addExternalMod_CustomFilenames(elementType, id, base_id, name, path_dff, path_txd, path_col, ignoreTXD, ignoreDFF, ignoreCOL, metaDownloadFalse, usingCoroutine) -- [Exported]
if (usingCoroutine == true) then
coroutine.yield()
end

local sourceResName = getResourceName(sourceResource)
if sourceResName == resName then
Expand Down
Loading

0 comments on commit 6756a7d

Please sign in to comment.