2025-04-07 01:41:12 +00:00

239 lines
9.3 KiB
Lua

---@type WeedSharedConfig
local sharedConfig = require 'config.shared'
---@type WeedServerConfig
local config = require 'config.server'
---@type table<number, vector3>
local outsidePlants = {}
---@param property string
---@return WeedPlant[]
lib.callback.register('qbx_weed:server:getPropertyPlants', function(_, property)
if sharedConfig.plantsSpawnType == 'outside' then return {} end
local propertyPlants = {}
local plants = MySQL.query.await('SELECT * FROM weed_plants WHERE property = ?', { property })
for i = 1, #plants, 1 do
local plant = plants[i]
plant.coords = json.decode(plant.coords)
plant.coords = vec3(plant.coords.x, plant.coords.y, plant.coords.z)
propertyPlants[#propertyPlants + 1] = plant
end
return propertyPlants
end)
---@param ids number[]
---@return WeedPlant[]
lib.callback.register('qbx_weed:server:getOutsidePlants', function(_, ids)
if sharedConfig.plantsSpawnType == 'property' then return {} end
local plants = {}
for i = 1, #ids do
local plant = MySQL.prepare.await('SELECT * FROM weed_plants WHERE id = ?', { ids[i] })
if plant then
plant.coords = json.decode(plant.coords)
plant.coords = vec3(plant.coords.x, plant.coords.y, plant.coords.z)
plants[#plants + 1] = plant
end
end
return plants
end)
---@param coords vector3
---@param sort string
---@param property? string
RegisterNetEvent('qbx_weed:server:placePlant', function(coords, sort, property)
if (property and sharedConfig.plantsSpawnType == 'outside') or (not property and sharedConfig.plantsSpawnType == 'property') then return end
local gender = math.random(1, 2) == 1 and 'female' or 'male'
if property then
MySQL.insert.await('INSERT INTO weed_plants (property, coords, gender, sort) VALUES (?, ?, ?, ?)', { property, json.encode(coords), gender, sort })
TriggerClientEvent('qbx_weed:client:refreshPropertyPlants', -1, property)
else
local id = MySQL.insert.await('INSERT INTO weed_plants (coords, gender, sort) VALUES (?, ?, ?)', { json.encode(coords), gender, sort })
outsidePlants[id] = coords
end
end)
---@param property? string
---@param plantId integer
---@param plantCoords vector3
RegisterNetEvent('qbx_weed:server:removeDeadPlant', function(property, plantId, plantCoords)
if (property and sharedConfig.plantsSpawnType == 'outside') or (not property and sharedConfig.plantsSpawnType == 'property') then return end
local player = exports.qbx_core:GetPlayer(source)
if not player or player.PlayerData.metadata.currentPropertyId ~= property or #(GetEntityCoords(GetPlayerPed(player.PlayerData.source)) - plantCoords) > 2 then return end
MySQL.prepare.await('DELETE FROM weed_plants WHERE id = ?', { plantId })
if property then
TriggerClientEvent('qbx_weed:client:refreshPropertyPlants', -1, property)
else
outsidePlants[plantId] = nil
end
end)
---@param plant WeedPlant
local function checkPlantFood(plant)
if plant.food >= 50 then
MySQL.update.await('UPDATE weed_plants SET food = ? WHERE id = ?', { plant.food - 1, plant.id })
if plant.health + 1 < 100 then
MySQL.update.await('UPDATE weed_plants SET health = ? WHERE id = ?', { plant.health + 1, plant.id })
end
else
if plant.food - 1 >= 0 then
MySQL.update('UPDATE weed_plants SET food = ? WHERE id = ?', { plant.food - 1, plant.id })
end
if plant.health - 1 >= 0 then
MySQL.update.await('UPDATE weed_plants SET health = ? WHERE id = ?', { plant.health - 1, plant.id })
end
end
end
---@param plant WeedPlant
local function growPlant(plant)
if plant.health <= 50 then return end
local grow = math.random(config.randomGrowAmount.min, config.randomGrowAmount.max)
if plant.stageProgress + grow < 100 then
MySQL.update.await('UPDATE weed_plants SET stageProgress = ? WHERE id = ?', { plant.stageProgress + grow, plant.id })
return
end
if plant.stage == #sharedConfig.plants[plant.sort].stages then return end
MySQL.update.await('UPDATE weed_plants SET stage = ? WHERE id = ?', { plant.stage + 1, plant.id })
MySQL.update.await('UPDATE weed_plants SET stageProgress = ? WHERE id = ?', { 0, plant.id })
end
---@param itemSlot integer
---@param seed string
RegisterNetEvent('qbx_weed:server:removeSeed', function(itemSlot, seed)
local player = exports.qbx_core:GetPlayer(source)
if not player then return end
exports.ox_inventory:RemoveItem(player.PlayerData.source, seed, 1, nil, itemSlot)
end)
---@param property? string
---@param seedAmount integer
---@param plantItemName string
---@param plantId integer
---@param plantCoords vector3
RegisterNetEvent('qbx_weed:server:harvestPlant', function(property, seedAmount, plantItemName, plantId, plantCoords)
if (property and sharedConfig.plantsSpawnType == 'outside') or (not property and sharedConfig.plantsSpawnType == 'property') then return end
local player = exports.qbx_core:GetPlayer(source)
if not player or player.PlayerData.metadata.currentPropertyId ~= property or #(GetEntityCoords(GetPlayerPed(player.PlayerData.source)) - plantCoords) > 2 then return end
if not MySQL.prepare.await('SELECT 1 FROM weed_plants WHERE id = ?', { plantId }) then
exports.qbx_core:Notify(player.PlayerData.source, locale('error.this_plant_no_longer_exists'), 'error')
return
end
local weedBag = exports.ox_inventory:Search(player.PlayerData.source, 'count', sharedConfig.items.emptyBag)
local harvestAmount = math.random(config.randomHarvestAmount.min, config.randomHarvestAmount.max)
if weedBag < harvestAmount then
exports.qbx_core:Notify(player.PlayerData.source, locale('error.you_dont_have_enough_resealable_bags'), 'error')
return
end
if not exports.ox_inventory:RemoveItem(player.PlayerData.source, sharedConfig.items.emptyBag, harvestAmount) then return end
exports.ox_inventory:AddItem(player.PlayerData.source, plantItemName .. '_seed', seedAmount)
exports.ox_inventory:AddItem(player.PlayerData.source, plantItemName, harvestAmount)
MySQL.prepare.await('DELETE FROM weed_plants WHERE id = ?', { plantId })
exports.qbx_core:Notify(player.PlayerData.source, locale('text.the_plant_has_been_harvested'), 'success')
if property then
TriggerClientEvent('qbx_weed:client:refreshPropertyPlants', -1, property)
else
outsidePlants[plantId] = nil
end
end)
---@param property string
---@param amount integer
---@param plantName string
---@param plantId integer
RegisterNetEvent('qbx_weed:server:foodPlant', function(property, amount, plantName, plantId)
if (property and sharedConfig.plantsSpawnType == 'outside') or (not property and sharedConfig.plantsSpawnType == 'property') then return end
local player = exports.qbx_core:GetPlayer(source)
if not player then return end
local plantFood = MySQL.prepare.await('SELECT food FROM weed_plants WHERE id = ?', { plantId })
exports.qbx_core:Notify(player.PlayerData.source, ('%s | %s %s%% + %s%% (%s%%)'):format(sharedConfig.plants[plantName].label, locale('text.nutrition'), plantFood, amount, plantFood + amount), 'inform')
local newAmount = plantFood + amount
if newAmount > 100 then
MySQL.update.await('UPDATE weed_plants SET food = ? WHERE id = ?', { 100, plantId })
else
MySQL.update.await('UPDATE weed_plants SET food = ? WHERE id = ?', { newAmount, plantId })
end
exports.ox_inventory:RemoveItem(player.PlayerData.source, sharedConfig.items.nutrition, 1)
if property then
TriggerClientEvent('qbx_weed:client:refreshPropertyPlants', -1, property)
else
TriggerClientEvent('qbx_weed:client:refreshOutsidePlants', -1, outsidePlants)
end
end)
AddEventHandler('qbx_core:server:onSetMetaData', function(meta, _, value, source)
if meta ~= 'currentPropertyId' or value then return end
TriggerClientEvent('qbx_weed:client:refreshOutsidePlants', source, outsidePlants)
end)
CreateThread(function()
if sharedConfig.plantsSpawnType == 'property' then return end
local plants = MySQL.query.await('SELECT * FROM weed_plants WHERE property IS NULL')
for i = 1, #plants do
local plant = plants[i]
plant.coords = json.decode(plant.coords)
plant.coords = vec3(plant.coords.x, plant.coords.y, plant.coords.z)
outsidePlants[plant.id] = plant.coords
end
local sleep = config.outsidePlantsRefreshInterval * 1000
while true do
TriggerClientEvent('qbx_weed:client:refreshOutsidePlants', -1, outsidePlants)
Wait(sleep)
end
end)
CreateThread(function()
local sleep = config.plantFoodCheckInterval * 1000
while true do
local plants = MySQL.query.await('SELECT id, food, health FROM weed_plants')
for i = 1, #plants do
checkPlantFood(plants[i])
end
TriggerClientEvent('qbx_weed:client:refreshPlantStats', -1)
Wait(sleep)
end
end)
CreateThread(function()
local sleep = config.plantGrowInterval * 1000
while true do
local plants = MySQL.query.await('SELECT id, stage, sort, health, stageProgress FROM weed_plants')
for i = 1, #plants do
growPlant(plants[i])
end
TriggerClientEvent('qbx_weed:client:refreshPlantStats', -1)
Wait(sleep)
end
end)