mirror of
https://github.com/esx-framework/esx_core.git
synced 2026-08-30 01:38:52 +00:00
Merge pull request #1187 from thelindat/legacy
Legacy - Fix non-networked objects/vehicles; send full MySQL.store queries; improve multichar support and minor fixes
This commit is contained in:
@@ -58,10 +58,11 @@ To get an idea for how you can utilise imports and the new functions, you can re
|
||||
|
||||
## Conflicts
|
||||
* The following resources should not be used with ESX Legacy and can result in errors
|
||||
- **essentialsmode**
|
||||
- basic-gamemode
|
||||
- fivem-map-skater
|
||||
- fivem-map-hipster
|
||||
- **essentialsmode**
|
||||
- default_spawnpoint
|
||||
|
||||
|
||||
## 1.2 + Features
|
||||
|
||||
@@ -335,11 +335,10 @@ ESX.Game.Teleport = function(entity, coords, cb)
|
||||
end
|
||||
end
|
||||
|
||||
ESX.Game.SpawnObject = function(object, coords, cb, networked, dynamic)
|
||||
ESX.Game.SpawnObject = function(object, coords, cb, networked)
|
||||
local model = (type(object) == 'number' and model or GetHashKey(object))
|
||||
local vector = type(coords) == "vector3" and coords or vec(coords.x, coords.y, coords.z)
|
||||
networked = networked == nil and true or false
|
||||
dynamic = dynamic ~= nil and true or false
|
||||
networked = networked or true
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
ESX.Streaming.RequestModel(model)
|
||||
@@ -347,7 +346,7 @@ ESX.Game.SpawnObject = function(object, coords, cb, networked, dynamic)
|
||||
-- The below has to be done just for CreateObject since for some reason CreateObjects model argument is set
|
||||
-- as an Object instead of a hash so it doesn't automatically hash the item
|
||||
model = type(model) == 'number' and model or GetHashKey(model)
|
||||
local obj = CreateObject(model, vector.xyz, networked, false, dynamic)
|
||||
local obj = CreateObject(model, vector.xyz, networked, false, true)
|
||||
if cb then
|
||||
cb(obj)
|
||||
end
|
||||
@@ -372,7 +371,7 @@ end
|
||||
ESX.Game.SpawnVehicle = function(vehicle, coords, heading, cb, networked)
|
||||
local model = (type(vehicle) == 'number' and vehicle or GetHashKey(vehicle))
|
||||
local vector = type(coords) == "vector3" and coords or vec(coords.x, coords.y, coords.z)
|
||||
networked = networked == nil and true or false
|
||||
networked = networked or true
|
||||
Citizen.CreateThread(function()
|
||||
ESX.Streaming.RequestModel(model)
|
||||
|
||||
|
||||
+3
-7
@@ -17,7 +17,6 @@ AddEventHandler('esx:playerLoaded', function(playerData, isNew, skin)
|
||||
FreezeEntityPosition(PlayerPedId(), true)
|
||||
|
||||
if Config.Multichar then
|
||||
TriggerEvent('esx_multicharacter:SpawnCharacter', playerData.coords, isNew)
|
||||
Citizen.Wait(3000)
|
||||
else
|
||||
exports.spawnmanager:spawnPlayer({
|
||||
@@ -85,13 +84,13 @@ AddEventHandler('esx:setMaxWeight', function(newMaxWeight) ESX.PlayerData.maxWei
|
||||
AddEventHandler('esx:onPlayerSpawn', function()
|
||||
local playerPed = PlayerPedId()
|
||||
if ESX.PlayerData.ped ~= playerPed then ESX.SetPlayerData('ped', playerPed) end
|
||||
ESX.SetPlayerData('dead', false)
|
||||
if ESX.PlayerData.dead ~= false then ESX.SetPlayerData('dead', false) end
|
||||
end)
|
||||
|
||||
AddEventHandler('esx:onPlayerDeath', function()
|
||||
local playerPed = PlayerPedId()
|
||||
if ESX.PlayerData.ped ~= playerPed then ESX.SetPlayerData('ped', playerPed) end
|
||||
ESX.SetPlayerData('dead', true)
|
||||
if ESX.PlayerData.dead ~= false then ESX.SetPlayerData('dead', true) end
|
||||
end)
|
||||
|
||||
AddEventHandler('skinchanger:modelLoaded', function()
|
||||
@@ -186,9 +185,6 @@ end)
|
||||
|
||||
RegisterNetEvent('esx:addWeapon')
|
||||
AddEventHandler('esx:addWeapon', function(weapon, ammo)
|
||||
-- Removed ESX.PlayerData.ped from being stored in a variable, not needed
|
||||
-- when it's only being used once, also doing it in a few
|
||||
-- functions below this one
|
||||
GiveWeaponToPed(ESX.PlayerData.ped, GetHashKey(weapon), ammo, false, false)
|
||||
end)
|
||||
|
||||
@@ -406,7 +402,6 @@ function StartServerSyncLoops()
|
||||
local previousCoords = vector3(ESX.PlayerData.coords.x, ESX.PlayerData.coords.y, ESX.PlayerData.coords.z)
|
||||
|
||||
while ESX.PlayerLoaded do
|
||||
Citizen.Wait(1500)
|
||||
local playerPed = PlayerPedId()
|
||||
if ESX.PlayerData.ped ~= playerPed then ESX.SetPlayerData('ped', playerPed) end
|
||||
|
||||
@@ -421,6 +416,7 @@ function StartServerSyncLoops()
|
||||
TriggerServerEvent('esx:updateCoords', formattedCoords)
|
||||
end
|
||||
end
|
||||
Citizen.Wait(1500)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
+10
-11
@@ -165,7 +165,7 @@ end
|
||||
|
||||
local savePlayers = -1
|
||||
Citizen.CreateThread(function()
|
||||
savePlayers = MySQL.Sync.store("UPDATE users SET ? WHERE ?")
|
||||
savePlayers = MySQL.Sync.store("UPDATE users SET `accounts` = ?, `job` = ?, `job_grade` = ?, `group` = ?, `position`= ?, `inventory`, = ?, `loadout` = ? WHERE `identifier` = ?")
|
||||
end)
|
||||
|
||||
ESX.SavePlayer = function(xPlayer, cb)
|
||||
@@ -173,15 +173,14 @@ ESX.SavePlayer = function(xPlayer, cb)
|
||||
|
||||
table.insert(asyncTasks, function(cb2)
|
||||
MySQL.Async.execute(savePlayers, {
|
||||
{
|
||||
['accounts'] = json.encode(xPlayer.getAccounts(true)),
|
||||
['job'] = xPlayer.job.name,
|
||||
['job_grade'] = xPlayer.job.grade,
|
||||
['group'] = xPlayer.getGroup(),
|
||||
['loadout'] = json.encode(xPlayer.getLoadout(true)),
|
||||
['position'] = json.encode(xPlayer.getCoords()),
|
||||
['inventory'] = json.encode(xPlayer.getInventory(true))
|
||||
}, {['identifier'] = xPlayer.getIdentifier()}
|
||||
json.encode(xPlayer.getAccounts(true)),
|
||||
xPlayer.job.name,
|
||||
xPlayer.job.grade,
|
||||
xPlayer.getGroup(),
|
||||
json.encode(xPlayer.getCoords()),
|
||||
json.encode(xPlayer.getInventory(true)),
|
||||
json.encode(xPlayer.getLoadout(true)),
|
||||
xPlayer.getIdentifier()
|
||||
}, function(rowsChanged)
|
||||
cb2()
|
||||
end)
|
||||
@@ -251,7 +250,7 @@ end
|
||||
|
||||
ESX.GetIdentifier = function(playerId)
|
||||
for k,v in ipairs(GetPlayerIdentifiers(playerId)) do
|
||||
if string.match(v, 'license') then
|
||||
if string.match(v, 'license:') then
|
||||
local identifier = string.gsub(v, 'license:', '')
|
||||
return identifier
|
||||
end
|
||||
|
||||
+46
-52
@@ -1,31 +1,41 @@
|
||||
local NewPlayer, LoadPlayer = -1, -1
|
||||
Citizen.CreateThread(function()
|
||||
SetMapName('San Andreas')
|
||||
SetGameType('ESX Roleplay')
|
||||
MySQL.Async.store("INSERT INTO users SET ?", function(storeId)
|
||||
NewPlayer = storeId
|
||||
end)
|
||||
SetGameType('ESX Legacy')
|
||||
|
||||
local query = '`accounts`, `job`, `job_grade`, `group`, `position`, `inventory`, `skin`, `loadout`'
|
||||
if Config.Multichar or Config.Identity then query = query..', `firstname`, `lastname`, `dateofbirth`, `sex`, `height`' end
|
||||
local query = '`accounts`, `job`, `job_grade`, `group`, `position`, `inventory`, `skin`, `loadout`' -- Select these fields from the database
|
||||
if Config.Multichar or Config.Identity then -- append these fields to the select query
|
||||
query = query..', `firstname`, `lastname`, `dateofbirth`, `sex`, `height`'
|
||||
end
|
||||
|
||||
MySQL.Async.store("SELECT "..query.." FROM `users` WHERE ?? LIKE ?", function(storeId)
|
||||
if Config.Multichar then -- insert identity data with creation
|
||||
MySQL.Async.store("INSERT INTO `users` SET `accounts` = ?, `identifier` = ?, `group` = ?, `firstname` = ?, `lastname` = ?, `dateofbirth` = ?, `sex` = ?, `height` = ?", function(storeId)
|
||||
NewPlayer = storeId
|
||||
end)
|
||||
else
|
||||
MySQL.Async.store("INSERT INTO `users` SET `accounts` = ?, `identifier` = ?, `group` = ?", function(storeId)
|
||||
NewPlayer = storeId
|
||||
end)
|
||||
end
|
||||
|
||||
MySQL.Async.store("SELECT "..query.." FROM `users` WHERE identifier = ?", function(storeId)
|
||||
LoadPlayer = storeId
|
||||
end)
|
||||
end)
|
||||
|
||||
local awaitingRegistration = {}
|
||||
RegisterNetEvent('esx:onPlayerJoined')
|
||||
if Config.Multichar then
|
||||
AddEventHandler('esx_identity:completedRegistration', function(playerId, data)
|
||||
awaitingRegistration[playerId] = data
|
||||
end)
|
||||
AddEventHandler('esx:onPlayerJoined', function(src, char, isNew)
|
||||
AddEventHandler('esx:onPlayerJoined', function(src, char, data)
|
||||
if not ESX.Players[src] then
|
||||
onPlayerJoined(src, char, isNew)
|
||||
local identifier = char..':'..ESX.GetIdentifier(src)
|
||||
if data then
|
||||
createESXPlayer(identifier, src, data)
|
||||
else
|
||||
loadESXPlayer(identifier, src, false)
|
||||
end
|
||||
end
|
||||
end)
|
||||
else
|
||||
RegisterNetEvent('esx:onPlayerJoined')
|
||||
AddEventHandler('esx:onPlayerJoined', function()
|
||||
if not ESX.Players[source] then
|
||||
onPlayerJoined(source)
|
||||
@@ -33,15 +43,13 @@ else
|
||||
end)
|
||||
end
|
||||
|
||||
function onPlayerJoined(playerId, char, isNew)
|
||||
function onPlayerJoined(playerId)
|
||||
local identifier = ESX.GetIdentifier(playerId)
|
||||
if char then identifier = char..':'..identifier end
|
||||
|
||||
if identifier then
|
||||
if ESX.GetPlayerFromIdentifier(identifier) then
|
||||
DropPlayer(playerId, ('there was an error loading your character!\nError code: identifier-active-ingame\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same Rockstar account.\n\nYour Rockstar identifier: %s'):format(identifier))
|
||||
elseif Config.Multichar and isNew then
|
||||
createESXPlayer(identifier, playerId)
|
||||
else
|
||||
MySQL.Async.fetchScalar('SELECT 1 FROM users WHERE identifier = @identifier', {
|
||||
['@identifier'] = identifier
|
||||
@@ -56,7 +64,7 @@ function onPlayerJoined(playerId, char, isNew)
|
||||
end
|
||||
end
|
||||
|
||||
function createESXPlayer(identifier, playerId)
|
||||
function createESXPlayer(identifier, playerId, data)
|
||||
local accounts = {}
|
||||
|
||||
for account,money in pairs(Config.StartingAccountMoney) do
|
||||
@@ -72,33 +80,22 @@ function createESXPlayer(identifier, playerId)
|
||||
|
||||
if not Config.Multichar then
|
||||
MySQL.Async.execute(NewPlayer, {
|
||||
{
|
||||
['accounts'] = json.encode(accounts),
|
||||
['identifier'] = identifier,
|
||||
['group'] = defaultGroup,
|
||||
}
|
||||
json.encode(accounts),
|
||||
identifier,
|
||||
defaultGroup,
|
||||
}, function(rowsChanged)
|
||||
loadESXPlayer(identifier, playerId, true)
|
||||
end)
|
||||
else
|
||||
local data
|
||||
awaitingRegistration[playerId] = true
|
||||
while true do
|
||||
Citizen.Wait(250)
|
||||
if awaitingRegistration[playerId] ~= true then data = awaitingRegistration[playerId] break end
|
||||
end
|
||||
awaitingRegistration[playerId] = nil
|
||||
MySQL.Async.execute(NewPlayer, {
|
||||
{
|
||||
['accounts'] = json.encode(accounts),
|
||||
['identifier'] = identifier,
|
||||
['group'] = defaultGroup,
|
||||
['firstname'] = data.firstname,
|
||||
['lastname'] = data.lastname,
|
||||
['dateofbirth'] = data.dateofbirth,
|
||||
['sex'] = data.sex,
|
||||
['height'] = data.height,
|
||||
}
|
||||
json.encode(accounts),
|
||||
identifier,
|
||||
defaultGroup,
|
||||
data.firstname,
|
||||
data.lastname,
|
||||
data.dateofbirth,
|
||||
data.sex,
|
||||
data.height,
|
||||
}, function(rowsChanged)
|
||||
loadESXPlayer(identifier, playerId, true)
|
||||
end)
|
||||
@@ -129,13 +126,11 @@ function loadESXPlayer(identifier, playerId, isNew)
|
||||
accounts = {},
|
||||
inventory = {},
|
||||
job = {},
|
||||
loadout = {},
|
||||
playerName = GetPlayerName(playerId),
|
||||
weight = 0
|
||||
}
|
||||
|
||||
table.insert(tasks, function(cb)
|
||||
MySQL.Async.fetchAll(LoadPlayer, {'identifier', {identifier}
|
||||
MySQL.Async.fetchAll(LoadPlayer, { identifier
|
||||
}, function(result)
|
||||
local job, grade, jobObject, gradeObject = result[1].job, tostring(result[1].job_grade)
|
||||
local foundAccounts, foundItems = {}, {}
|
||||
@@ -300,7 +295,7 @@ function loadESXPlayer(identifier, playerId, isNew)
|
||||
loadout = xPlayer.getLoadout(),
|
||||
maxWeight = xPlayer.getMaxWeight(),
|
||||
money = xPlayer.getMoney(),
|
||||
dead = 0
|
||||
dead = false
|
||||
}, isNew, userData.skin)
|
||||
|
||||
xPlayer.triggerEvent('esx:createMissingPickups', ESX.Pickups)
|
||||
@@ -333,7 +328,6 @@ end)
|
||||
if Config.Multichar then
|
||||
AddEventHandler('esx:playerLogout', function(playerId)
|
||||
local xPlayer = ESX.GetPlayerFromId(playerId)
|
||||
awaitingRegistration[playerId] = nil
|
||||
if xPlayer then
|
||||
TriggerEvent('esx:playerDropped', playerId, reason)
|
||||
|
||||
@@ -595,12 +589,12 @@ ESX.RegisterServerCallback('esx:getPlayerNames', function(source, cb, players)
|
||||
end)
|
||||
|
||||
AddEventHandler('txAdmin:events:scheduledRestart', function(eventData)
|
||||
if eventData.secondsRemaining == 60 then
|
||||
Citizen.CreateThread(function()
|
||||
Citizen.Wait(50000)
|
||||
ESX.SavePlayers()
|
||||
end)
|
||||
end
|
||||
if eventData.secondsRemaining == 60 then
|
||||
Citizen.CreateThread(function()
|
||||
Citizen.Wait(50000)
|
||||
ESX.SavePlayers()
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
-- version check
|
||||
@@ -651,7 +645,7 @@ Citizen.CreateThread(
|
||||
print(
|
||||
([[
|
||||
^1----------------------------------------------------------------------
|
||||
^1URGENT: YOUR ES_EXTENDED IS OUTDATATED!!!
|
||||
^1URGENT: YOUR ES_EXTENDED IS OUTDATED!!!
|
||||
^1COMMIT UPDATE: ^5%s AVAILABLE
|
||||
^1DOWNLOAD:^5 https://github.com/esx-framework/es_extended/tree/legacy
|
||||
^1CHANGELOG:^5 %s
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "legacy",
|
||||
"commit" : "1.3.2",
|
||||
"changelog": "Corrected a mistake resulting in loadouts not being loaded with players"
|
||||
"commit" : "1.3.3",
|
||||
"changelog": "\n- Resolved an issue when using Config.Identity\n- MySQL.store is now storing entire queries ahead of time\n- Improved support when using esx_multicharacter"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user