Initial commit
This commit is contained in:
627
gamemodes/darkrp/gamemode/modules/base/sv_data.lua
Normal file
627
gamemodes/darkrp/gamemode/modules/base/sv_data.lua
Normal file
@@ -0,0 +1,627 @@
|
||||
--[[---------------------------------------------------------------------------
|
||||
Functions and variables
|
||||
---------------------------------------------------------------------------]]
|
||||
local setUpNonOwnableDoors,
|
||||
setUpTeamOwnableDoors,
|
||||
setUpGroupDoors,
|
||||
migrateDB
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Database initialize
|
||||
---------------------------------------------------------]]
|
||||
function DarkRP.initDatabase()
|
||||
MySQLite.begin()
|
||||
-- Gotta love the difference between SQLite and MySQL
|
||||
local is_mysql = MySQLite.isMySQL()
|
||||
local AUTOINCREMENT = is_mysql and "AUTO_INCREMENT" or "AUTOINCREMENT"
|
||||
-- in MySQL, the engine is set to InnoDB. InnoDB has been the default
|
||||
-- for a while, but people might be running old versions of MySQL.
|
||||
-- SQLite has no database engine, so it is not explicitly set.
|
||||
local ENGINE_INNODB = is_mysql and "ENGINE=InnoDB" or ""
|
||||
|
||||
-- Table that holds all position data (jail, spawns etc.)
|
||||
-- Queue these queries because other queries depend on the existence of the darkrp_position table
|
||||
-- Race conditions could occur if the queries are executed simultaneously
|
||||
MySQLite.queueQuery([[
|
||||
CREATE TABLE IF NOT EXISTS darkrp_position(
|
||||
id INTEGER NOT NULL PRIMARY KEY ]] .. AUTOINCREMENT .. [[,
|
||||
map VARCHAR(45) NOT NULL,
|
||||
type CHAR(1) NOT NULL,
|
||||
x INTEGER NOT NULL,
|
||||
y INTEGER NOT NULL,
|
||||
z INTEGER NOT NULL
|
||||
) ]] .. ENGINE_INNODB .. [[;
|
||||
]])
|
||||
|
||||
-- team spawns require extra data
|
||||
MySQLite.queueQuery([[
|
||||
CREATE TABLE IF NOT EXISTS darkrp_jobspawn(
|
||||
id INTEGER NOT NULL PRIMARY KEY REFERENCES darkrp_position(id)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE,
|
||||
|
||||
teamcmd VARCHAR(255) NOT NULL
|
||||
) ]] .. ENGINE_INNODB .. [[;
|
||||
]])
|
||||
|
||||
-- This table is kept for compatibility with older addons and websites
|
||||
-- See https://github.com/FPtje/DarkRP/issues/819
|
||||
MySQLite.queueQuery([[
|
||||
CREATE TABLE IF NOT EXISTS playerinformation(
|
||||
uid BIGINT NOT NULL,
|
||||
steamID VARCHAR(50) NOT NULL PRIMARY KEY
|
||||
) ]] .. ENGINE_INNODB .. [[
|
||||
]])
|
||||
|
||||
-- Player information
|
||||
MySQLite.queueQuery([[
|
||||
CREATE TABLE IF NOT EXISTS darkrp_player(
|
||||
uid BIGINT NOT NULL PRIMARY KEY,
|
||||
rpname VARCHAR(45),
|
||||
salary INTEGER NOT NULL DEFAULT 45,
|
||||
wallet BIGINT NOT NULL
|
||||
) ]] .. ENGINE_INNODB .. [[;
|
||||
]])
|
||||
|
||||
-- Door data
|
||||
MySQLite.queueQuery([[
|
||||
CREATE TABLE IF NOT EXISTS darkrp_door(
|
||||
idx INTEGER NOT NULL,
|
||||
map VARCHAR(45) NOT NULL,
|
||||
title VARCHAR(25),
|
||||
isLocked BOOLEAN,
|
||||
isDisabled BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
PRIMARY KEY(idx, map)
|
||||
) ]] .. ENGINE_INNODB .. [[;
|
||||
]])
|
||||
|
||||
-- Some doors are owned by certain teams
|
||||
MySQLite.queueQuery([[
|
||||
CREATE TABLE IF NOT EXISTS darkrp_doorjobs(
|
||||
idx INTEGER NOT NULL,
|
||||
map VARCHAR(45) NOT NULL,
|
||||
job VARCHAR(255) NOT NULL,
|
||||
|
||||
PRIMARY KEY(idx, map, job)
|
||||
) ]] .. ENGINE_INNODB .. [[;
|
||||
]])
|
||||
|
||||
-- Door groups
|
||||
MySQLite.queueQuery([[
|
||||
CREATE TABLE IF NOT EXISTS darkrp_doorgroups(
|
||||
idx INTEGER NOT NULL,
|
||||
map VARCHAR(45) NOT NULL,
|
||||
doorgroup VARCHAR(100) NOT NULL,
|
||||
|
||||
PRIMARY KEY(idx, map)
|
||||
) ]] .. ENGINE_INNODB .. [[
|
||||
]])
|
||||
|
||||
MySQLite.queueQuery([[
|
||||
CREATE TABLE IF NOT EXISTS darkrp_dbversion(version INTEGER NOT NULL PRIMARY KEY) ]] .. ENGINE_INNODB .. [[
|
||||
]])
|
||||
|
||||
-- Load the last DBVersion into DarkRP.DBVersion, to allow checks to see whether migration is needed.
|
||||
MySQLite.queueQuery([[
|
||||
SELECT MAX(version) AS version FROM darkrp_dbversion
|
||||
]], function(data)
|
||||
-- The database is created with the schema of the latest version. On
|
||||
-- initialization the version is not set yet. Set it to the latest
|
||||
-- version.
|
||||
if not data or not data[1] or not tonumber(data[1].version) then
|
||||
DarkRP.DBVersion = 20211228
|
||||
MySQLite.query([[
|
||||
REPLACE INTO darkrp_dbversion VALUES(20211228)
|
||||
]])
|
||||
else
|
||||
DarkRP.DBVersion = tonumber(data[1].version)
|
||||
end
|
||||
end)
|
||||
|
||||
MySQLite.commit(fp{migrateDB, -- Migrate the database
|
||||
function() -- Initialize the data after all the tables have been created
|
||||
setUpNonOwnableDoors()
|
||||
setUpTeamOwnableDoors()
|
||||
setUpGroupDoors()
|
||||
|
||||
if MySQLite.isMySQL() then -- In a listen server, the connection with the external database is often made AFTER the listen server host has joined,
|
||||
--so he walks around with the settings from the SQLite database
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
DarkRP.offlinePlayerData(v:SteamID(), function(data)
|
||||
local Data = data and data[1]
|
||||
if not IsValid(v) or not Data then return end
|
||||
|
||||
v:setDarkRPVar("rpname", Data.rpname)
|
||||
v:setSelfDarkRPVar("salary", Data.salary)
|
||||
v:setDarkRPVar("money", Data.wallet)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
hook.Call("DarkRPDBInitialized")
|
||||
end})
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------------------------
|
||||
Database migration
|
||||
backwards compatibility with older versions of DarkRP
|
||||
---------------------------------------------------------------------------]]
|
||||
function migrateDB(callback)
|
||||
-- Simple function that checks the database version, migrates if
|
||||
-- necessary, and recurses to perform the next migration, until the last
|
||||
-- migration has been performed.
|
||||
-- Calls callback when the migration is finished or not necessary.
|
||||
local function migrate(version)
|
||||
if version < 20160610 then
|
||||
MySQLite.begin()
|
||||
if MySQLite.isMySQL() then
|
||||
-- if only SQLite were this easy
|
||||
MySQLite.queueQuery([[DROP INDEX rpname ON darkrp_player]])
|
||||
else
|
||||
-- darkrp_player used to have a UNIQUE rpname field.
|
||||
-- This sucks, get rid of it
|
||||
MySQLite.queueQuery([[PRAGMA foreign_keys=OFF]])
|
||||
|
||||
MySQLite.queueQuery([[
|
||||
CREATE TABLE IF NOT EXISTS new_darkrp_player(
|
||||
uid BIGINT NOT NULL PRIMARY KEY,
|
||||
rpname VARCHAR(45),
|
||||
salary INTEGER NOT NULL DEFAULT 45,
|
||||
wallet INTEGER NOT NULL
|
||||
);
|
||||
]])
|
||||
|
||||
MySQLite.queueQuery([[INSERT INTO new_darkrp_player SELECT * FROM darkrp_player]])
|
||||
|
||||
MySQLite.queueQuery([[DROP TABLE darkrp_player]])
|
||||
|
||||
MySQLite.queueQuery([[ALTER TABLE new_darkrp_player RENAME TO darkrp_player]])
|
||||
|
||||
MySQLite.queueQuery([[PRAGMA foreign_keys=ON]])
|
||||
end
|
||||
MySQLite.queueQuery([[REPLACE INTO darkrp_dbversion VALUES(20160610)]])
|
||||
MySQLite.commit(fp{migrate, 20160610})
|
||||
return
|
||||
end
|
||||
|
||||
if version < 20181013 then
|
||||
-- migrate from darkrp_jobown to darkrp_doorjobs
|
||||
MySQLite.tableExists("darkrp_jobown", function(exists)
|
||||
if not exists then migrate(20181013) return end
|
||||
|
||||
MySQLite.begin()
|
||||
-- Create a temporary table that links job IDs to job commands
|
||||
MySQLite.queueQuery("CREATE TABLE IF NOT EXISTS TempJobCommands(id INT NOT NULL PRIMARY KEY, cmd VARCHAR(255) NOT NULL);")
|
||||
if MySQLite.isMySQL() then
|
||||
local jobCommands = {}
|
||||
for k, v in pairs(RPExtraTeams) do
|
||||
table.insert(jobCommands, "(" .. k .. "," .. MySQLite.SQLStr(v.command) .. ")")
|
||||
end
|
||||
|
||||
-- This WOULD work with SQLite if the implementation in GMod wasn't out of date.
|
||||
MySQLite.queueQuery("INSERT IGNORE INTO TempJobCommands VALUES " .. table.concat(jobCommands, ",") .. ";")
|
||||
else
|
||||
for k, v in pairs(RPExtraTeams) do
|
||||
MySQLite.queueQuery("INSERT INTO TempJobCommands VALUES(" .. k .. ", " .. MySQLite.SQLStr(v.command) .. ");")
|
||||
end
|
||||
end
|
||||
|
||||
MySQLite.queueQuery("REPLACE INTO darkrp_doorjobs SELECT darkrp_jobown.idx AS idx, darkrp_jobown.map AS map, TempJobCommands.cmd AS job FROM darkrp_jobown JOIN TempJobCommands ON darkrp_jobown.job = TempJobCommands.id;")
|
||||
|
||||
-- Clean up the transition table and the old table
|
||||
MySQLite.queueQuery("DROP TABLE TempJobCommands;")
|
||||
MySQLite.queueQuery("DROP TABLE darkrp_jobown;")
|
||||
MySQLite.queueQuery([[REPLACE INTO darkrp_dbversion VALUES(20181013)]])
|
||||
MySQLite.commit(fp{migrate, 20181013})
|
||||
end)
|
||||
return
|
||||
end
|
||||
|
||||
if version < 20181014 then
|
||||
MySQLite.query([[SELECT * FROM darkrp_jobspawn]], function(oldData)
|
||||
oldData = oldData or {}
|
||||
MySQLite.begin()
|
||||
|
||||
MySQLite.queueQuery([[DROP TABLE darkrp_jobspawn]])
|
||||
|
||||
MySQLite.queueQuery([[
|
||||
CREATE TABLE darkrp_jobspawn(
|
||||
id INTEGER NOT NULL PRIMARY KEY REFERENCES darkrp_position(id)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE,
|
||||
|
||||
teamcmd VARCHAR(255) NOT NULL
|
||||
);
|
||||
]])
|
||||
|
||||
for i, row in pairs(oldData) do
|
||||
local teamcmd = (RPExtraTeams[tonumber(row.team)] or {}).command
|
||||
if not teamcmd then continue end
|
||||
|
||||
MySQLite.queueQuery(string.format([[INSERT INTO darkrp_jobspawn(id, teamcmd) VALUES(%s, %s)]], row.id, MySQLite.SQLStr(teamcmd)))
|
||||
end
|
||||
|
||||
MySQLite.queueQuery([[REPLACE INTO darkrp_dbversion VALUES(20181014)]])
|
||||
|
||||
MySQLite.commit(fp{migrate, 20181014})
|
||||
end)
|
||||
return
|
||||
end
|
||||
|
||||
if version < 20190914 then
|
||||
MySQLite.begin()
|
||||
-- Migration not necessary for SQLite, since BIGINT and
|
||||
-- INTEGER are considered the same in SQLite
|
||||
-- https://www.sqlite.org/datatype3.html
|
||||
if MySQLite.isMySQL() then
|
||||
MySQLite.queueQuery([[DROP TRIGGER IF EXISTS JobPositionFKDelete]])
|
||||
MySQLite.queueQuery([[ALTER TABLE darkrp_player MODIFY wallet BIGINT;]])
|
||||
end
|
||||
MySQLite.queueQuery([[REPLACE INTO darkrp_dbversion VALUES(20190914)]])
|
||||
MySQLite.commit(fp{migrate, 20190914})
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
if version < 20211228 then
|
||||
MySQLite.begin()
|
||||
-- Migrate all tables to InnoDB if they weren't already.
|
||||
-- See https://github.com/FPtje/DarkRP/issues/3157
|
||||
if MySQLite.isMySQL() then
|
||||
MySQLite.queueQuery([[ALTER TABLE darkrp_dbversion ENGINE = InnoDB;]])
|
||||
MySQLite.queueQuery([[ALTER TABLE darkrp_door ENGINE = InnoDB;]])
|
||||
MySQLite.queueQuery([[ALTER TABLE darkrp_doorgroups ENGINE = InnoDB;]])
|
||||
MySQLite.queueQuery([[ALTER TABLE darkrp_doorjobs ENGINE = InnoDB;]])
|
||||
MySQLite.queueQuery([[ALTER TABLE darkrp_jobspawn ENGINE = InnoDB;]])
|
||||
MySQLite.queueQuery([[ALTER TABLE darkrp_player ENGINE = InnoDB;]])
|
||||
MySQLite.queueQuery([[ALTER TABLE darkrp_position ENGINE = InnoDB;]])
|
||||
MySQLite.queueQuery([[ALTER TABLE playerinformation ENGINE = InnoDB;]])
|
||||
end
|
||||
|
||||
MySQLite.queueQuery([[REPLACE INTO darkrp_dbversion VALUES(20211228)]])
|
||||
MySQLite.commit(fp{migrate, 20211228})
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-- All migrations finished
|
||||
callback()
|
||||
end
|
||||
migrate(DarkRP.DBVersion)
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Players
|
||||
---------------------------------------------------------]]
|
||||
function DarkRP.storeRPName(ply, name)
|
||||
if not name or string.len(name) < 2 then return end
|
||||
hook.Call("onPlayerChangedName", nil, ply, ply:getDarkRPVar("rpname"), name)
|
||||
ply:setDarkRPVar("rpname", name)
|
||||
|
||||
MySQLite.query([[UPDATE darkrp_player SET rpname = ]] .. MySQLite.SQLStr(name) .. [[ WHERE UID = ]] .. ply:SteamID64() .. ";")
|
||||
MySQLite.query([[UPDATE darkrp_player SET rpname = ]] .. MySQLite.SQLStr(name) .. [[ WHERE UID = ]] .. ply:UniqueID() .. ";")
|
||||
end
|
||||
|
||||
function DarkRP.retrieveRPNames(name, callback)
|
||||
MySQLite.query("SELECT COUNT(*) AS count FROM darkrp_player WHERE rpname = " .. MySQLite.SQLStr(name) .. ";", function(r)
|
||||
callback(tonumber(r[1].count) > 0)
|
||||
end)
|
||||
end
|
||||
|
||||
function DarkRP.offlinePlayerData(steamid, callback, failed)
|
||||
local sid64 = util.SteamIDTo64(steamid)
|
||||
local uniqueid = util.CRC("gm_" .. string.upper(steamid) .. "_gm")
|
||||
|
||||
MySQLite.query(string.format([[REPLACE INTO playerinformation VALUES(%s, %s);]], MySQLite.SQLStr(sid64), MySQLite.SQLStr(steamid)), nil, failed)
|
||||
|
||||
local query = [[
|
||||
SELECT rpname, wallet, salary, "SID64" AS kind
|
||||
FROM darkrp_player
|
||||
where uid = %s
|
||||
|
||||
UNION
|
||||
|
||||
SELECT rpname, wallet, salary, "UniqueID" AS kind
|
||||
FROM darkrp_player
|
||||
where uid = %s
|
||||
;
|
||||
]]
|
||||
|
||||
MySQLite.query(
|
||||
query:format(sid64, uniqueid),
|
||||
function(data, ...)
|
||||
-- The database has no record of the player data in SteamID64 form
|
||||
-- Otherwise the first row would have kind SID64
|
||||
if data and data[1] and data[1].kind == "UniqueID" then
|
||||
-- The rpname must be unique
|
||||
-- adding a new row with uid = SteamID64, but the same rpname will remove the uid=UniqueID row
|
||||
|
||||
local replquery = [[
|
||||
REPLACE INTO darkrp_player(uid, rpname, wallet, salary)
|
||||
VALUES (%s, %s, %s, %s)
|
||||
]]
|
||||
|
||||
MySQLite.begin()
|
||||
MySQLite.queueQuery(
|
||||
replquery:format(
|
||||
sid64,
|
||||
data[1].rpname == "NULL" and "NULL" or MySQLite.SQLStr(data[1].rpname),
|
||||
data[1].wallet,
|
||||
data[1].salary
|
||||
),
|
||||
nil,
|
||||
failed
|
||||
)
|
||||
MySQLite.commit()
|
||||
end
|
||||
|
||||
return callback and callback(data, ...)
|
||||
end
|
||||
, failed
|
||||
)
|
||||
end
|
||||
|
||||
function DarkRP.retrievePlayerData(ply, callback, failed, attempts, err)
|
||||
attempts = attempts or 0
|
||||
|
||||
if attempts > 3 then return failed(err) end
|
||||
|
||||
DarkRP.offlinePlayerData(ply:SteamID(), callback, function(sqlErr)
|
||||
if not IsValid(ply) then return end
|
||||
|
||||
DarkRP.retrievePlayerData(ply, callback, failed, attempts + 1, sqlErr)
|
||||
end)
|
||||
end
|
||||
|
||||
function DarkRP.createPlayerData(ply, name, wallet, salary, onError)
|
||||
MySQLite.query([[REPLACE INTO darkrp_player VALUES(]] ..
|
||||
ply:SteamID64() .. [[, ]] ..
|
||||
MySQLite.SQLStr(utf8.force(name)) .. [[, ]] ..
|
||||
salary .. [[, ]] ..
|
||||
wallet .. ");", nil, onError)
|
||||
|
||||
-- Backwards compatibility
|
||||
MySQLite.query([[REPLACE INTO darkrp_player VALUES(]] ..
|
||||
ply:UniqueID() .. [[, ]] ..
|
||||
MySQLite.SQLStr(utf8.force(name)) .. [[, ]] ..
|
||||
salary .. [[, ]] ..
|
||||
wallet .. ");", nil, onError)
|
||||
end
|
||||
|
||||
function DarkRP.storeMoney(ply, amount)
|
||||
if not isnumber(amount) or amount < 0 or amount >= 1 / 0 then
|
||||
DarkRP.errorNoHalt("Some addon attempted to store a invalid money amount " .. tostring(amount) .. " for Player " .. ply:Nick() .. " (" .. ply:SteamID() .. ")", 1, {
|
||||
"This money amount will not be stored in the database, but it may be set in the game.",
|
||||
"The database simply stores the last valid, non-negative amount of money.",
|
||||
"Please try to find the very first time this error happened for this player. Then look at the files mentioned in this error.",
|
||||
"That will tell you which addon is causing this.",
|
||||
"IMPORTANT: This is NOT a DarkRP bug!",
|
||||
"Note: The player can simply rejoin to fix their negative money, until whatever causes this happens again."
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
-- Also keep deprecated UniqueID data at least somewhat up to date
|
||||
MySQLite.query([[UPDATE darkrp_player SET wallet = ]] .. amount .. [[ WHERE uid = ]] .. ply:UniqueID() .. [[ OR uid = ]] .. ply:SteamID64())
|
||||
end
|
||||
|
||||
function DarkRP.storeOfflineMoney(sid64, amount)
|
||||
if isnumber(sid64) or isstring(sid64) and string.len(sid64) < 17 then -- smaller than 76561197960265728 is not a SteamID64
|
||||
DarkRP.errorNoHalt([[Some addon is giving DarkRP.storeOfflineMoney a UniqueID as its first argument, but this function now expects a SteamID64]], 1, {
|
||||
"The function used to take UniqueIDs, but it does not anymore.",
|
||||
"If you are a server owner, please look closely to the files mentioned in this error",
|
||||
"After all, these files will tell you WHICH addon is doing it",
|
||||
"This is NOT a DarkRP bug!",
|
||||
"Your server will continue working normally",
|
||||
"But whichever addon just tried to store an offline player's money",
|
||||
"Will NOT take effect!"
|
||||
})
|
||||
end
|
||||
|
||||
if not isnumber(amount) or amount < 0 or amount >= 1 / 0 then
|
||||
DarkRP.errorNoHalt("Some addon attempted to store a invalid money amount " .. tostring(amount) .. " for an offline player with steamID64 " .. sid64, 1, {
|
||||
"This money amount will not be stored in the database.",
|
||||
"Please try to find the very first time this error happened for this player. Then look at the files mentioned in this error.",
|
||||
"That will tell you which addon is causing this.",
|
||||
"IMPORTANT: This is NOT a DarkRP bug!"
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
-- Also store on deprecated UniqueID
|
||||
local uniqueid = util.CRC("gm_" .. string.upper(util.SteamIDFrom64(sid64)) .. "_gm")
|
||||
MySQLite.query([[UPDATE darkrp_player SET wallet = ]] .. amount .. [[ WHERE uid = ]] .. uniqueid .. [[ OR uid = ]] .. sid64)
|
||||
end
|
||||
|
||||
local function resetAllMoney(ply, cmd, args)
|
||||
if ply:EntIndex() ~= 0 and not ply:IsSuperAdmin() then return end
|
||||
MySQLite.query("UPDATE darkrp_player SET wallet = " .. GAMEMODE.Config.startingmoney .. " ;")
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
v:setDarkRPVar("money", GAMEMODE.Config.startingmoney)
|
||||
end
|
||||
if ply:IsPlayer() then
|
||||
DarkRP.notifyAll(0, 4, DarkRP.getPhrase("reset_money", ply:Nick()))
|
||||
else
|
||||
DarkRP.notifyAll(0, 4, DarkRP.getPhrase("reset_money", "Console"))
|
||||
end
|
||||
end
|
||||
concommand.Add("rp_resetallmoney", resetAllMoney)
|
||||
|
||||
function DarkRP.storeSalary(ply, amount)
|
||||
ply:setSelfDarkRPVar("salary", math.floor(amount))
|
||||
|
||||
return amount
|
||||
end
|
||||
|
||||
function DarkRP.retrieveSalary(ply, callback)
|
||||
local val =
|
||||
ply:getJobTable() and ply:getJobTable().salary or
|
||||
RPExtraTeams[GAMEMODE.DefaultTeam].salary or
|
||||
(GM or GAMEMODE).Config.normalsalary
|
||||
|
||||
if callback then callback(val) end
|
||||
|
||||
return val
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------------------------
|
||||
Players
|
||||
---------------------------------------------------------------------------]]
|
||||
local meta = FindMetaTable("Player")
|
||||
function meta:restorePlayerData()
|
||||
self.DarkRPUnInitialized = true
|
||||
|
||||
local function onError(err)
|
||||
if not IsValid(self) then return end
|
||||
self.DarkRPUnInitialized = true -- no information should be saved from here, or the playerdata might be reset
|
||||
|
||||
self:setDarkRPVar("money", GAMEMODE.Config.startingmoney)
|
||||
self:setSelfDarkRPVar("salary", DarkRP.retrieveSalary(self))
|
||||
local name = string.sub(string.gsub(self:SteamName(), "\\\"", "\""), 1, 30)
|
||||
self:setDarkRPVar("rpname", name)
|
||||
|
||||
self.DarkRPDataRetrievalFailed = true -- marker on the player that says shit is fucked
|
||||
DarkRP.error("Failed to retrieve player information from the database. ", nil, {"This means your database or the connection to your database is fucked.", "This is the error given by the database:\n\t\t" .. tostring(err)})
|
||||
end
|
||||
|
||||
DarkRP.retrievePlayerData(self, function(data)
|
||||
if not IsValid(self) then return end
|
||||
|
||||
self.DarkRPUnInitialized = nil
|
||||
|
||||
local info = data and data[1] or {}
|
||||
if not info.rpname or info.rpname == "NULL" then info.rpname = string.sub(string.gsub(self:SteamName(), "\\\"", "\""), 1, 30) end
|
||||
|
||||
info.wallet = info.wallet or GAMEMODE.Config.startingmoney
|
||||
info.salary = DarkRP.retrieveSalary(self)
|
||||
|
||||
self:setDarkRPVar("money", tonumber(info.wallet))
|
||||
self:setSelfDarkRPVar("salary", tonumber(info.salary))
|
||||
|
||||
self:setDarkRPVar("rpname", info.rpname)
|
||||
|
||||
if not data then
|
||||
info = hook.Call("onPlayerFirstJoined", nil, self, info) or info
|
||||
DarkRP.createPlayerData(self, info.rpname, info.wallet, info.salary, onError)
|
||||
end
|
||||
end, onError)
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Doors
|
||||
---------------------------------------------------------]]
|
||||
function DarkRP.storeDoorData(ent)
|
||||
if not ent:CreatedByMap() then return end
|
||||
local map = string.lower(game.GetMap())
|
||||
local nonOwnable = ent:getKeysNonOwnable()
|
||||
local title = ent:getKeysTitle()
|
||||
|
||||
MySQLite.query([[REPLACE INTO darkrp_door VALUES(]] .. ent:doorIndex() .. [[, ]] .. MySQLite.SQLStr(map) .. [[, ]] .. (title and MySQLite.SQLStr(title) or "NULL") .. [[, ]] .. "NULL" .. [[, ]] .. (nonOwnable and 1 or 0) .. [[);]])
|
||||
end
|
||||
|
||||
function setUpNonOwnableDoors()
|
||||
MySQLite.query("SELECT idx, title, isLocked, isDisabled FROM darkrp_door WHERE map = " .. MySQLite.SQLStr(string.lower(game.GetMap())) .. ";", function(r)
|
||||
if not r then return end
|
||||
|
||||
for _, row in pairs(r) do
|
||||
local e = DarkRP.doorIndexToEnt(tonumber(row.idx))
|
||||
|
||||
if not IsValid(e) then continue end
|
||||
if e:isKeysOwnable() then
|
||||
if tobool(row.isDisabled) then
|
||||
e:setKeysNonOwnable(tobool(row.isDisabled))
|
||||
end
|
||||
if row.isLocked and row.isLocked ~= "NULL" then
|
||||
e:Fire((tobool(row.isLocked) and "" or "un") .. "lock", "", 0)
|
||||
end
|
||||
e:setKeysTitle(row.title ~= "NULL" and row.title or nil)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local keyValueActions = {
|
||||
["DarkRPNonOwnable"] = function(ent, val) ent:setKeysNonOwnable(tobool(val)) end,
|
||||
["DarkRPTitle"] = function(ent, val) ent:setKeysTitle(val) end,
|
||||
["DarkRPDoorGroup"] = function(ent, val) if RPExtraTeamDoors[val] then ent:setDoorGroup(val) end end,
|
||||
["DarkRPCanLockpick"] = function(ent, val) ent.DarkRPCanLockpick = tobool(val) end
|
||||
}
|
||||
|
||||
local function onKeyValue(ent, key, value)
|
||||
if not ent:isDoor() then return end
|
||||
|
||||
if keyValueActions[key] then
|
||||
keyValueActions[key](ent, value)
|
||||
end
|
||||
end
|
||||
hook.Add("EntityKeyValue", "darkrp_doors", onKeyValue)
|
||||
|
||||
function DarkRP.storeTeamDoorOwnability(ent)
|
||||
if not ent:CreatedByMap() then return end
|
||||
local map = string.lower(game.GetMap())
|
||||
|
||||
MySQLite.query("DELETE FROM darkrp_doorjobs WHERE idx = " .. ent:doorIndex() .. " AND map = " .. MySQLite.SQLStr(map) .. ";")
|
||||
for k in pairs(ent:getKeysDoorTeams() or {}) do
|
||||
MySQLite.query("INSERT INTO darkrp_doorjobs VALUES(" .. ent:doorIndex() .. ", " .. MySQLite.SQLStr(map) .. ", " .. MySQLite.SQLStr(RPExtraTeams[k].command) .. ");")
|
||||
end
|
||||
end
|
||||
|
||||
function setUpTeamOwnableDoors()
|
||||
MySQLite.query("SELECT idx, job FROM darkrp_doorjobs WHERE map = " .. MySQLite.SQLStr(string.lower(game.GetMap())) .. ";", function(r)
|
||||
if not r then return end
|
||||
local map = string.lower(game.GetMap())
|
||||
|
||||
for _, row in pairs(r) do
|
||||
row.idx = tonumber(row.idx)
|
||||
|
||||
local e = DarkRP.doorIndexToEnt(row.idx)
|
||||
if not IsValid(e) then continue end
|
||||
|
||||
local _, job = DarkRP.getJobByCommand(row.job)
|
||||
|
||||
if job then
|
||||
e:addKeysDoorTeam(job)
|
||||
else
|
||||
print(("can't find job %s for door %d, removing from database"):format(row.job, row.idx))
|
||||
MySQLite.query(("DELETE FROM darkrp_doorjobs WHERE idx = %d AND map = %s AND job = %s;"):format(row.idx, MySQLite.SQLStr(map), MySQLite.SQLStr(row.job)))
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function DarkRP.storeDoorGroup(ent, group)
|
||||
if not ent:CreatedByMap() then return end
|
||||
local map = MySQLite.SQLStr(string.lower(game.GetMap()))
|
||||
local index = ent:doorIndex()
|
||||
|
||||
if group == "" or not group then
|
||||
MySQLite.query("DELETE FROM darkrp_doorgroups WHERE map = " .. map .. " AND idx = " .. index .. ";")
|
||||
return
|
||||
end
|
||||
|
||||
MySQLite.query("REPLACE INTO darkrp_doorgroups VALUES(" .. index .. ", " .. map .. ", " .. MySQLite.SQLStr(group) .. ");");
|
||||
end
|
||||
|
||||
function setUpGroupDoors()
|
||||
local map = MySQLite.SQLStr(string.lower(game.GetMap()))
|
||||
MySQLite.query("SELECT idx, doorgroup FROM darkrp_doorgroups WHERE map = " .. map, function(data)
|
||||
if not data then return end
|
||||
|
||||
for _, row in pairs(data) do
|
||||
local ent = DarkRP.doorIndexToEnt(tonumber(row.idx))
|
||||
|
||||
if not IsValid(ent) or not ent:isKeysOwnable() then
|
||||
continue
|
||||
end
|
||||
|
||||
if not RPExtraTeamDoorIDs[row.doorgroup] then continue end
|
||||
ent:setDoorGroup(row.doorgroup)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
hook.Add("PostCleanupMap", "DarkRP.hooks", function()
|
||||
setUpNonOwnableDoors()
|
||||
setUpTeamOwnableDoors()
|
||||
setUpGroupDoors()
|
||||
end)
|
||||
Reference in New Issue
Block a user