Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Isolate PreferredJobModel #3266

Merged
merged 6 commits into from
Sep 28, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 57 additions & 9 deletions gamemode/modules/base/cl_jobmodels.lua
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
-- Create a table for the preferred playermodels
sql.Query([[CREATE TABLE IF NOT EXISTS darkp_playermodels(
jobcmd VARCHAR(45) NOT NULL PRIMARY KEY,
model VARCHAR(140) NOT NULL
--
-- Note: in DarkRP before 2024-09, there was a different table called
-- `darkp_playermodels` (note the misspelling of "darkp"). This table was
-- missing the server column, meaning that preferred job models would persist
-- across multiple servers. To make preferred job models store per server, this
-- new table (without the spelling mistake) was created.
--
-- See the original issue to create the player model preference feature:
-- https://github.com/FPtje/DarkRP/issues/979 and the subsequent refactor at
-- https://github.com/FPtje/DarkRP/pull/3266
sql.Query([[CREATE TABLE IF NOT EXISTS darkrp_playermodels(
server TEXT NOT NULL,
jobcmd TEXT NOT NULL,
model TEXT NOT NULL,
PRIMARY KEY (server, jobcmd)
);]])


local preferredModels = {}


Expand All @@ -14,7 +27,7 @@ function DarkRP.setPreferredJobModel(teamNr, model)
local job = RPExtraTeams[teamNr]
if not job then return end
preferredModels[job.command] = model
sql.Query(string.format([[REPLACE INTO darkp_playermodels VALUES(%s, %s);]], sql.SQLStr(job.command), sql.SQLStr(model)))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's another issue. After the table is migrated to have three columns, the old version of this query will fail with this error: table darkp_playermodels has 3 columns but 2 values were supplied.

Because SQLite errors are silent (the query just returns false, and you have to print sql.LastError() to get the error, job models are silently no longer saved.

This would not have a problem if the query was REPLACE INTO darkp_playermodels(jobcmd, model) VALUES(%s, %s);, but this is not something we can fix in hindsight 🤔

sql.Query(string.format([[REPLACE INTO darkrp_playermodels(server, jobcmd, model) VALUES(%s, %s, %s);]], sql.SQLStr(game.GetIPAddress()), sql.SQLStr(job.command), sql.SQLStr(model)))

net.Start("DarkRP_preferredjobmodel")
net.WriteUInt(teamNr, 8)
Expand All @@ -31,7 +44,7 @@ end
--[[---------------------------------------------------------------------------
Load the preferred models
---------------------------------------------------------------------------]]
local function sendModels() -- run after the jobs have loaded
local function sendModels()
net.Start("DarkRP_preferredjobmodels")
for _, job in pairs(RPExtraTeams) do
if not preferredModels[job.command] then net.WriteBit(false) continue end
Expand All @@ -42,11 +55,46 @@ local function sendModels() -- run after the jobs have loaded
net.SendToServer()
end

do
local models = sql.Query([[SELECT jobcmd, model FROM darkp_playermodels;]])
for _, v in ipairs(models or {}) do
local function jobHasModel(job, model)
return istable(job.model) and table.HasValue(job.model, model) or job.model == model
end

local function setPreferredModels(models)
for _, v in ipairs(models) do
local job = DarkRP.getJobByCommand(v.jobcmd)
if job == nil or not jobHasModel(job, v.model) then continue end

preferredModels[v.jobcmd] = v.model
end
end

timer.Simple(0, sendModels)
-- The old table, darkp_playermodels, acts as a global mapping of preferred
-- models for jobs.
local function setModelsFromOldTable()
local oldTableExists = tobool(sql.QueryValue([[SELECT 1 FROM sqlite_master WHERE type='table' AND name='darkp_playermodels']]))
if not oldTableExists then return end

local models = sql.Query([[SELECT jobcmd, model FROM darkp_playermodels;]])

if not models then return end
setPreferredModels(models)
end

-- The newer table is server specific.
local function setModelsFromNewTable()
local models = sql.Query(string.format([[SELECT jobcmd, model FROM darkrp_playermodels WHERE server = %s;]], sql.SQLStr(game.GetIPAddress())))

if not models then return end
setPreferredModels(models)
end

timer.Simple(0, function()
-- Run after the jobs have loaded, to make sure the jobs can be looked up.

-- Set models from the old table, before overriding them with data from the
-- new table. That way, server specific preferences always have precedence.
setModelsFromOldTable()
setModelsFromNewTable()

sendModels()
end)