628 lines
26 KiB
Lua
628 lines
26 KiB
Lua
--[[---------------------------------------------------------------------------
|
|
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)
|