crafting exploit fixes

This has several changes

When crafting, it now checks if the inventory is open and stops crafting dead and warns the player with a print.

Multicraft now checks if you have space in your inventory for the items and limits the max amount craftable

Also fixes the "title" of the qb-input box when crafting

Also changed the anim flag for the "placing items" to hopefully keep you in place
This commit is contained in:
Jim Shield
2025-05-06 00:17:07 +01:00
parent 1623feacf1
commit 31633bc61d
3 changed files with 82 additions and 14 deletions

View File

@@ -228,20 +228,24 @@ function multiCraft(data)
end end
end end
local dialog = createInput(data.craftable.Header, { local carryMax = triggerCallback(getScript()..":server:getMaxCarryCraft", {
item = data.item,
max = max
})
local dialog = createInput(data.craftable.Header..(Config.System.Menu == "qb" and ": "..br.."How many to craft? "..br.."Max: "..carryMax or ""), {
((Config.System.Menu == "ox") and { ((Config.System.Menu == "ox") and {
type = "slider", type = "slider",
label = "How many to craft?", label = "How many to craft? "..br.."Max: "..carryMax,
required = true, required = true,
default = 1, default = 1,
min = 1, min = 1,
max = max max = carryMax
}) or nil, }) or nil,
((Config.System.Menu == "qb") and { ((Config.System.Menu == "qb") and {
type = "number", type = "number",
label = "How many to craft?"..br.."Max: "..max,
name = "amount", name = "amount",
isRecuired = true, isRequired = true,
default = 1, default = 1,
}) or nil, }) or nil,
}) })
@@ -251,18 +255,14 @@ function multiCraft(data)
end end
if Config.System.Menu == "qb" then if Config.System.Menu == "qb" then
if dialog["amount"] == nil or dialog["amount"] == "" then
dialog["amount"] = 1
end
dialog["amount"] = tonumber(dialog["amount"]) dialog["amount"] = tonumber(dialog["amount"])
if dialog["amount"] > max or dialog["amount"] < 1 or dialog["amount"] == nil or dialog["amount"] == "" then if dialog["amount"] > carryMax or dialog["amount"] < 1 or dialog["amount"] == nil or dialog["amount"] == "" then
triggerNotify(nil, "Invalid Amount", "error") triggerNotify(nil, "Invalid Amount", "error")
craftingMenu(data) craftingMenu(data)
return return
end end
end end
makeItem({ makeItem({
item = data.item, item = data.item,
craft = data.craft, craft = data.craft,
@@ -270,7 +270,6 @@ function multiCraft(data)
amount = dialog["amount"] or dialog[1], amount = dialog["amount"] or dialog[1],
coords = data.coords, coords = data.coords,
stashName = stashName or nil, stashName = stashName or nil,
--stashTable = data.stashName,
onBack = data.onBack, onBack = data.onBack,
metadata = data.metadata, metadata = data.metadata,
}) })
@@ -327,19 +326,23 @@ function makeItem(data)
local crafted, crafting = true, true local crafted, crafting = true, true
local cam = createTempCam(PlayerPedId(), data.coords) local cam = createTempCam(PlayerPedId(), data.coords)
startTempCam(cam) startTempCam(cam)
for i = 1, craftAmount do for i = 1, craftAmount do
for k, v in pairs(data.craft) do for k, v in pairs(data.craft) do
if not excludeKeys[k] then if not excludeKeys[k] then
if type(v) == "table" then if type(v) == "table" then
for l, b in pairs(v) do for l, b in pairs(v) do
if isInventoryOpen() then
print("^1Error^7: ^2Inventory is open, you tried to break things")
crafted, crafting = false, false
return
end
if crafting and progressBar({ if crafting and progressBar({
label = "Using "..b.." "..Items[l].label, label = "Using "..b.." "..Items[l].label,
time = 1000, time = 1000,
cancel = true, cancel = true,
dict = 'pickup_object', dict = 'pickup_object',
anim = "putdown_low", anim = "putdown_low",
flag = 48, flag = 49,
icon = l, icon = l,
}) then }) then
TriggerEvent((isStarted(QBInv) and QBInvNew and "qb-" or "")..'inventory:client:ItemBox', Items[l], "use", b) TriggerEvent((isStarted(QBInv) and QBInvNew and "qb-" or "")..'inventory:client:ItemBox', Items[l], "use", b)
@@ -349,6 +352,11 @@ function makeItem(data)
end end
Wait(200) Wait(200)
end end
if isInventoryOpen() then
print("^1Error^7: ^2Inventory is open, you tried to break things")
crafted, crafting = false, false
return
end
if crafted then if crafted then
local craftProp = nil local craftProp = nil
if prop then if prop then
@@ -359,6 +367,11 @@ function makeItem(data)
local s = data.sound local s = data.sound
PlaySoundFromEntity(s.soundId, s.audioName, PlayerPedId(), s.audioRef, true, 0) PlaySoundFromEntity(s.soundId, s.audioName, PlayerPedId(), s.audioRef, true, 0)
end end
if isInventoryOpen() then
print("^1Error^7: ^2Inventory is open, you tried to break things")
crafted, crafting = false, false
return
end
if crafting and progressBar({ if crafting and progressBar({
label = bartext..((metadata and metadata.label) or Items[data.item].label), label = bartext..((metadata and metadata.label) or Items[data.item].label),
time = bartime, time = bartime,
@@ -410,7 +423,6 @@ function makeItem(data)
end end
stopTempCam() stopTempCam()
CraftLock = false CraftLock = false
lockInv(false)
if canReturn then craftingMenu(data) end if canReturn then craftingMenu(data) end
ClearPedTasks(PlayerPedId()) ClearPedTasks(PlayerPedId())
end end

View File

@@ -15,6 +15,7 @@
function lockInv(toggle) function lockInv(toggle)
FreezeEntityPosition(PlayerPedId(), toggle) FreezeEntityPosition(PlayerPedId(), toggle)
LocalPlayer.state:set("inv_busy", toggle, true) LocalPlayer.state:set("inv_busy", toggle, true)
LocalPlayer.state:set("invBusy", toggle, true)
TriggerEvent('inventory:client:busy:status', toggle) TriggerEvent('inventory:client:busy:status', toggle)
TriggerEvent('canUseInventoryAndHotbar:toggle', not toggle) TriggerEvent('canUseInventoryAndHotbar:toggle', not toggle)
end end
@@ -169,3 +170,38 @@ function getPlayerInv(src)
end end
return grabInv, foundInv return grabInv, foundInv
end end
function isInventoryOpen()
if isStarted(OXInv) then
return LocalPlayer.state.invBusy
elseif isStarted(QSInv) then
return exports[QSInv]:inInventory()
elseif isStarted(OrigenInv) then
return exports[OrigenInv]:IsInventoryOpen()
elseif isStarted(CoreInv) then
return exports[CoreInv]:isInventoryOpen()
elseif isStarted(CodeMInv) then
return false -- CodeM doesn't have a function to check if the inventory is open
elseif isStarted(TgiannInv) then
return exports["tgiann-inventory"]:IsInventoryActive()
elseif isStarted(QBInv) then
return LocalPlayer.state.inv_busy
elseif isStarted(PSInv) then
return LocalPlayer.state.inv_busy
elseif ESX and isStarted(ESXExport) then
return false
elseif isStarted(RSGInv) then
return LocalPlayer.state.inv_busy
end
end

View File

@@ -698,6 +698,26 @@ if isServer() then
return result return result
end) end)
createCallback(getScript()..":server:getMaxCarryCraft", function(source, data)
local src = source
local item = data.item
local max = data.max or 100
local maxCanCarry = 0
for i = 1, max do
local checkTable = {
[item] = i
}
local result = canCarry(checkTable, src)
if result[item] == true then
maxCanCarry = i
else
break
end
end
return maxCanCarry
end)
local AuthEvent = getScript()..":"..keyGen()..keyGen()..keyGen()..keyGen()..":"..keyGen()..keyGen()..keyGen()..keyGen() local AuthEvent = getScript()..":"..keyGen()..keyGen()..keyGen()..keyGen()..":"..keyGen()..keyGen()..keyGen()..keyGen()
validTokens = validTokens or {} validTokens = validTokens or {}