Database Saving Error

Hello my DB System is working but not good.

See this:

I need 1 row for 1 user.

Maybe usefull:



local randomnames = {
	"John Richards",
	"Steve Martin",
	"James Standen",
	"Richard Hammond",
	"Matthey Dawn",
	"Frank Goliath",
	"Ben Slocome",
	"Jamie Hyneman",
	"Adam Savage",
	"Joe Lawrence",
	"Lewis Groombridge",
	"James Taylor",
	"Sean Steel",
	"Daniel Tutt",
	"Lile Roberts",
	"Lucas Simms",
	"Jamie Clark"
};

-- Load a player's data.
function pMeta:LoadData()

	local name = self:Name();
	local ip = self:IPAddress()
	local steamID = self:SteamID();
	local uniqueID = self:UniqueID();
	
	-- Create the main cityrp table with some default variables.
	self.cityrp._Name = name;
	self.cityrp._Ip = ip;
	self.cityrp._Igname = table.Random(randomnames);
	self.cityrp._Description = cityrp.configuration["Default Description"];
	self.cityrp._Clan = cityrp.configuration["Default Clan"];
	self.cityrp._SteamID = steamID;
	self.cityrp._TimePlayed = 0;
	self.cityrp._Points = 0;
	self.cityrp._PackagesPending = 0;
	self.cityrp._UniqueID = uniqueID;
	self.cityrp._Money = cityrp.configuration["Default Money"];
	self.cityrp._Access = cityrp.configuration["Default Access"];
	self.cityrp._Flags = '';
	self.cityrp._Donator = 0;
	self.cityrp._Arrested = false;
	self.cityrp._Inventory = table.copy(cityrp.configuration["Default Inventory"]);
	self.cityrp._Accessbans = {};
	self.cityrp._Accessbansname = {};
	self.cityrp._Gender = "Male";
	self.cityrp._svrank = "user";
	self.cityrp._Music = 1;

	-- Some default values to prevent bugs
	self._Salary = 0;
	
	-- Perform a threaded query.
	if(cityrp.playerpreload[steamID] and cityrp.playerpreload[steamID].ctime > os.time() - 120) then
		self:LoadData2( cityrp.playerpreload[steamID] )
	else
		local pq = "SELECT * FROM "..cityrpserver["MySQL Table"].." WHERE _UniqueID = "..uniqueID
		DB:Query(pq, function(result)
			if ( IsValid(self) ) then
				if (result and type(result) == "table" and #result > 0) then
					result = result[1];
					self:LoadData2( result );
				else
					self:LoadDataNew();
				end;
			end;
		end, self);
	end;
	
	local pq = "UPDATE "..cityrpserver["MySQL Table"].." SET _Online = 1, _Server = '"..cityrpserver["Server"].."' WHERE _SteamID = '"..self.cityrp._SteamID.."'"
	DB:Query(pq);
	
	cityrp.access.Load(self)
end;

-- Load the player's data from the result table.
function pMeta:LoadData2( result )
	self.cityrp._Clan = result._Clan or "";
	self.cityrp._Ip = result._Ip;
	self.cityrp._Igname = result._Igname or "";
	self.cityrp._Description = result._Description or "";
	self.cityrp._Money = tonumber(result._Money);
	
	if(self.cityrp._Money < 0) then
		cityrp.bans.DoBan( false, self.cityrp._SteamID, self.cityrp._Name, 0, "Contact the Owner" )
	end;
	
--	self.cityrp._Access = result._Access;
	for i = 1, string.len(result._Flags) do
		local flag = string.sub(result._Flags, i, i);
		if(flag == "d") then
			cityrp.access.giveAccess(self, "d");
		end;
	end;
	
	self.cityrp._Flags = result._Flags;
	self.cityrp._TimePlayed = result._TimePlayed;
	self.cityrp._Points = result._Points;
	--self.cityrp._PackagesPending = tonumber(result._PackagesPending);
	self.cityrp._svrank = result._svrank or "user"
	self.cityrp._Music = result._Music or 1;
	
	if(self:IsAdmin() and tonumber(result._Donator) < (os.time() + 86400)) then
		self.cityrp._Donator = os.time() + 86400;
	else
		self.cityrp._Donator = tonumber(result._Donator);
	end;
	
	if(tonumber(result._Arrested) > 0) then
		self.cityrp._Arrested = true;
		self._WarrantedTime = tonumber(result._Arrested);
	end;
	
	self.cityrp._Inventory = {};
	
	-- Check to see if the clan is valid.
	if (self.cityrp._Clan == " " or string.lower(self.cityrp._Clan) == "none") then
		self.cityrp._Clan = "";
	end;

	-- Check to see if the name is valid.
	if (self.cityrp._Igname == " " or string.lower(self.cityrp._Igname) == "none") then
		self.cityrp._Igname = "";
	end;

	-- Check to see if the name is valid.
	if (self.cityrp._Description == " " or string.lower(self.cityrp._Description) == "none") then
		self.cityrp._Description = "";
	end;

	-- Get the inventory and blacklist as a table.
	local inventory, invalid_inventory = cityrp.player.convertInventoryString(result._Inventory);
	self._invalid_inventory = invalid_inventory;

	-- Loop through the inventory and give each item to the self.
	for k, v in pairs(inventory) do cityrp.inventory.update(self, k, v, true); end;

	self.cityrp._Gender = result._Gender or "Male";

	if (FLServer == "build" and tonumber(self.cityrp._TimePlayed) < 60*60*10) then 
		self:Kick("You need 10 hours of Playtime for build!")
		return
	end

	-- Call the gamemode hook to say that we loaded our data.
	hook.Call("PlayerDataLoaded", GAMEMODE, self, true);
end;

-- Load new data?
function pMeta:LoadDataNew()
	if (FLServer == "build" and tonumber(self.cityrp._TimePlayed) < 60*60*10) then 
		self:Kick("You need 10 hours of Playtime for build!")
		return
	end

	hook.Call("PlayerDataLoaded", GAMEMODE, self, false);
	
	-- Save our new result.
	self:SaveData( true )
end;

-- Save a player's data.
function pMeta:SaveData( create )
	if (self._Initialized) then
		if (create) then
			if(FLServer == "build" or cityrp.disablesave) then
				return
			end;
			local keys, values = cityrp.player.getDataKeyValues(self);

			-- Perform a threaded query.
			local pq = "INSERT INTO "..cityrpserver["MySQL Table"].." ("..keys..") VALUES ("..values..")"
			DB:Query(pq);
		else
			local query = cityrp.player.getDataUpdateQuery(self);
			
			-- Perform a threaded query.
			DB:Query(query);
		end;
	end;
end;

-- Set a player's salary based on third party adjustments.
function pMeta:SetSalary()
	self._Salary = cityrp.team.query(self:Team(), "salary") or 0;
	
	if (self.cityrp._Donator > os.time()) then
		self._Salary = self._Salary * 2;
	end;
end;

pMeta._SetPData = pMeta.SetPData;

function pMeta:SetPData(...)
	if(FLServer == "build" or cityrp.disablesave) then
		return
	end;
	return self:_SetPData(...)
end;


Thank you

Assuming you’re using tmysql here. You really should make this use SteamID as the retrieval method instead of UniqueID to avoid collisions. The problem would be here:


		local pq = "SELECT * FROM "..cityrpserver["MySQL Table"].." WHERE _UniqueID = "..uniqueID
		DB:Query(pq, function(result)
			if ( IsValid(self) ) then
				if (result and type(result) == "table" and #result > 0) then
					result = result[1];
					self:LoadData2( result );
				else
					self:LoadDataNew();
				end;
			end;
		end, self);

But the command looks fine to me. Only problem I could think is if cityrpserver[“MySQL Table”] has an interfering name since you don’t escape any of your strings, or LoadDataNew is called somewhere else in another section of code.

This is load data new:



function pMeta:LoadDataNew()
	if (FLServer == "build" and tonumber(self.cityrp._TimePlayed) < 60*60*10) then 
		self:Kick("You need 10 hours of Playtime for build!")
		return
	end

	hook.Call("PlayerDataLoaded", GAMEMODE, self, false);
	
	-- Save our new result.
	self:SaveData( true )
end;
 

And I will change it to the SteamID retrieval method

Update:
Server is not in Build mode.

I know, I’m saying that if it were called somewhere else besides in the LoadData method, then that could also cause your duplication issue.

Changed the function names but I still get duplicate rows this is what I have now:



local randomnames = {
	"John Richards",
	"Steve Martin",
	"James Standen",
	"Richard Hammond",
	"Matthey Dawn",
	"Frank Goliath",
	"Ben Slocome",
	"Jamie Hyneman",
	"Adam Savage",
	"Joe Lawrence",
	"Lewis Groombridge",
	"James Taylor",
	"Sean Steel",
	"Daniel Tutt",
	"Lile Roberts",
	"Lucas Simms",
	"Jamie Clark"
};

-- Load a player's data.
function pMeta:LoadData()

	local name = self:Name();
	local ip = self:IPAddress()
	local steamID = self:SteamID();
	local uniqueID = self:UniqueID();
	
	-- Create the main cityrp table with some default variables.
	self.cityrp._Name = name;
	self.cityrp._Ip = ip;
	self.cityrp._Igname = table.Random(randomnames);
	self.cityrp._Description = cityrp.configuration["Default Description"];
	self.cityrp._Clan = cityrp.configuration["Default Clan"];
	self.cityrp._SteamID = steamID;
	self.cityrp._TimePlayed = 0;
	self.cityrp._Points = 0;
	self.cityrp._PackagesPending = 0;
	self.cityrp._UniqueID = uniqueID;
	self.cityrp._Money = cityrp.configuration["Default Money"];
	self.cityrp._Access = cityrp.configuration["Default Access"];
	self.cityrp._Flags = '';
	self.cityrp._Donator = 0;
	self.cityrp._Arrested = false;
	self.cityrp._Inventory = table.copy(cityrp.configuration["Default Inventory"]);
	self.cityrp._Accessbans = {};
	self.cityrp._Accessbansname = {};
	self.cityrp._Gender = "Male";
	self.cityrp._svrank = "user";
	self.cityrp._Music = 1;

	-- Some default values to prevent bugs
	self._Salary = 0;
	
	-- Perform a threaded query.
	if(cityrp.playerpreload[steamID] and cityrp.playerpreload[steamID].ctime > os.time() - 120) then
		self:LoadData2( cityrp.playerpreload[steamID] )
	else
		local pq = "SELECT * FROM players WHERE _SteamID = '"..self.cityrp._SteamID.."'"
		DB:Query(pq, function(result)
			if ( IsValid(self) ) then
				if (result and type(result) == "table" and #result > 0) then
					result = result[1];
					self:LoadData2Ty( result );
				else
					self:LoadDataNewTy();
				end;
			end;
		end, self);
	end;
	
	local pq = "UPDATE players SET _Online = 1, _Server = 'players' WHERE _SteamID = '"..self.cityrp._SteamID.."'"
	DB:Query(pq);
	
	cityrp.access.Load(self)
end;

-- Load the player's data from the result table.
function pMeta:LoadData2Ty( result )
	self.cityrp._Clan = result._Clan or "";
	self.cityrp._Ip = result._Ip;
	self.cityrp._Igname = result._Igname or "";
	self.cityrp._Description = result._Description or "";
	self.cityrp._Money = tonumber(result._Money);
	
	if(self.cityrp._Money < 0) then
		cityrp.bans.DoBan( false, self.cityrp._SteamID, self.cityrp._Name, 0, "Contact Soulripper" )
	end;
	
--	self.cityrp._Access = result._Access;
	for i = 1, string.len(result._Flags) do
		local flag = string.sub(result._Flags, i, i);
		if(flag == "d") then
			cityrp.access.giveAccess(self, "d");
		end;
	end;
	
	self.cityrp._Flags = result._Flags;
	self.cityrp._TimePlayed = result._TimePlayed;
	self.cityrp._Points = result._Points;
	--self.cityrp._PackagesPending = tonumber(result._PackagesPending);
	self.cityrp._svrank = result._svrank or "user"
	self.cityrp._Music = result._Music or 1;
	
	if(self:IsAdmin() and tonumber(result._Donator) < (os.time() + 86400)) then
		self.cityrp._Donator = os.time() + 86400;
	else
		self.cityrp._Donator = tonumber(result._Donator);
	end;
	
	if(tonumber(result._Arrested) > 0) then
		self.cityrp._Arrested = true;
		self._WarrantedTime = tonumber(result._Arrested);
	end;
	
	self.cityrp._Inventory = {};
	
	-- Check to see if the clan is valid.
	if (self.cityrp._Clan == " " or string.lower(self.cityrp._Clan) == "none") then
		self.cityrp._Clan = "";
	end;

	-- Check to see if the name is valid.
	if (self.cityrp._Igname == " " or string.lower(self.cityrp._Igname) == "none") then
		self.cityrp._Igname = "";
	end;

	-- Check to see if the name is valid.
	if (self.cityrp._Description == " " or string.lower(self.cityrp._Description) == "none") then
		self.cityrp._Description = "";
	end;

	-- Get the inventory and blacklist as a table.
	local inventory, invalid_inventory = cityrp.player.convertInventoryString(result._Inventory);
	self._invalid_inventory = invalid_inventory;

	-- Loop through the inventory and give each item to the self.
	for k, v in pairs(inventory) do cityrp.inventory.update(self, k, v, true); end;

	self.cityrp._Gender = result._Gender or "Male";

	if (FLServer == "build" and tonumber(self.cityrp._TimePlayed) < 60*60*10) then 
		self:Kick("You need 10 hours of FL Playtime for build!")
		return
	end

	-- Call the gamemode hook to say that we loaded our data.
	hook.Call("PlayerDataLoaded", GAMEMODE, self, true);
end;

-- Load new data?
function pMeta:LoadDataNewTy()
	if (FLServer == "build" and tonumber(self.cityrp._TimePlayed) < 60*60*10) then 
		self:Kick("You need 10 hours of FL Playtime for build!")
		return
	end

	hook.Call("PlayerDataLoaded", GAMEMODE, self, false);
	
	-- Save our new result.
	self:SaveData( true )
end;

-- Save a player's data.
function pMeta:SaveData( create )
	if (self._Initialized) then
		if (create) then
			if(FLServer == "build" or cityrp.disablesave) then
				return
			end;
			local keys, values = cityrp.player.getDataKeyValues(self);

			-- Perform a threaded query.
			local pq = "INSERT INTO players ("..keys..") VALUES ("..values..")"
			DB:Query(pq);
		else
			local query = cityrp.player.getDataUpdateQuery(self);
			
			-- Perform a threaded query.
			DB:Query(query);
		end;
	end;
end;

-- Set a player's salary based on third party adjustments.
function pMeta:SetSalary()
	self._Salary = cityrp.team.query(self:Team(), "salary") or 0;
	
	if (self.cityrp._Donator > os.time()) then
		self._Salary = self._Salary * 2;
	end;
end;

pMeta._SetPData = pMeta.SetPData;

function pMeta:SetPData(...)
	if(FLServer == "build" or cityrp.disablesave) then
		return
	end;
	return self:_SetPData(...)
end;


[editline]25th December 2016[/editline]

Now getting this error:



[ERROR] gamemodes/cityrp/gamemode/core/libraries/sh_help.lua:140: attempt to index a string value with bad key ('text' is not part of the string library)
  1. error - [C]:-1
   2. __index - lua/includes/extensions/string.lua:301
    3. unknown - gamemodes/cityrp/gamemode/core/libraries/sh_help.lua:140


[editline]25th December 2016[/editline]

gamemodes/cityrp/gamemode/core/libraries/sh_help.lua:137-140:



					-- Loop through the help in this category.
					for k2, v2 in pairs(v.help) do
						net.Start( "cityrp.help.help" )
							net.WriteString( v2.text )


Don’t know what v.help is, but v2 is a string.

–NOt

Does nobody now what the problem is?

[editline]26th December 2016[/editline]

Changed the function names back.

[editline]26th December 2016[/editline]

I think this is the problem:



-- Get an update query of a player's data.
function cityrp.player.getDataUpdateQuery(player)
	local uniqueID = player:UniqueID();
	local query = "";
	local keys = {};

	if(FLServer == "build" or cityrp.disablesave) then
		keys = {
			'_Name',
			'_IP',
			'_SteamID',
			'_UniqueID',
			'_TimePlayed',
			'_Points',
			'_svrank',
			'_Music'
		};
	else
		keys = {
			'_Name',
			'_IP',
			'_Igname',
			'_Description',
			'_Clan',
			'_Gender',
			'_SteamID',
			'_UniqueID',
			'_Money',
			'_Flags',
			'_Donator',
			'_Arrested',
			'_Inventory',
			'_TimePlayed',
			'_Points',
			'_svrank',
			'_Music'
		};
	end;

	-- Loop through our data.
	for k, v in pairs(keys) do
		d = player.cityrp[v]
		-- We create a temporary variable here to store the value.
		local value = tostring(d);

		if (v == "_Inventory") then
			value = cityrp.player.getInventoryString(player);
		elseif(v == "_Arrested") then
			if(d) then
				value = player._WarrantedTime;
			else
				value = 0;
			end;
		end;
		
		-- Check our query to see if it's an empty string.
		if (query == "") then
			query = "UPDATE "..cityrpserver["MySQL Table"].." SET "..v.." = \""..mysql_escape(value).."\"";
		else
			query = query..", "..v.." = \""..mysql_escape(value).."\"";
		end;
	end;
	
	-- Return our collected query.
	return query.." WHERE _UniqueID = "..uniqueID.." AND _TimePlayed <= "..player.cityrp._TimePlayed;
end;

function cityrp.player.saveDataAll()
	local save = false;
	local query = ""
	local keys = {};
	if(FLServer == "build" or cityrp.disablesave) then
		keys = {
			'_Name',
			'_IP',
			'_SteamID',
			'_UniqueID',
			'_TimePlayed',
			'_Points',
			'_svrank',
			'_Music'
		};
	else
		keys = {
			'_Name',
			'_IP',
			'_Igname',
			'_Description',
			'_Clan',
			'_Gender',
			'_SteamID',
			'_UniqueID',
			'_Money',
			'_Flags',
			'_Donator',
			'_Arrested',
			'_Inventory',
			'_TimePlayed',
			'_Points',
			'_svrank',
			'_Music'
		};
	end;
	local keyss = string.Implode(", ", keys)
	for k, player in pairs(player.GetAll()) do
		if (player._Initialized) then
			save = true;
			local values = "";
			--local keys, values = cityrp.player.getDataKeyValues(v);
	
			for k, v in pairs(keys) do
				d = player.cityrp[v]
				-- We create a temporary variable here to store the value.
				local value = tostring(d);
			
				-- Check to see if the type of the value is a table.
				if (type(d) == "table") then
					if (v == "_Inventory") then
						value = cityrp.player.getInventoryString(player);
					end;
				end;
				if(v == "_Arrested") then
					if(d) then
						value = player._WarrantedTime;
					else
						value = 0;
					end;
				end;
			
				values = values.."\""..mysql_escape(value).."\", ";
			
			end;
			local len = string.len(values);
			values = string.sub(values, 1, len - 2);

			if(query == '') then
				query = query.."INSERT INTO players ("..keys ..") VALUES ("..values..")"
			else
				query = query..",("..values..")"
			end;
		end;
	end
	if(save) then
		local dupstring = '';
		for k, v in pairs(keys) do
			dupstring = dupstring..v.."=VALUES("..v.."),"
		end
		local len = string.len(dupstring);
		dupstring = string.sub(dupstring, 1, len - 1);
		query = query.."ON DUPLICATE KEY UPDATE "..dupstring;
		DB:Query(query);
	end;
end;

function fl_tablesEqual(tab1, tab2) -- For some reason the tables weren't equal when they clearly were
	local equal = true
	for k,v in pairs(tab1) do 
		if !(tab2[k] == v) then equal = false end
	end
	return equal
end

local randomnames = {
	"John Richards",
	"Steve Martin",
	"James Standen",
	"Richard Hammond",
	"Matthey Dawn",
	"Frank Goliath",
	"Ben Slocome",
	"Jamie Hyneman",
	"Adam Savage",
	"Joe Lawrence",
	"Lewis Groombridge",
	"James Taylor",
	"Sean Steel",
	"Daniel Tutt",
	"Lile Roberts",
	"Lucas Simms",
	"Jamie Clark"
};

-- Create a timer to update each player's data.
local nextThink = 0
function cityrp.player.updateplayers()
	if (nextThink > CurTime()) then return end
	nextThink = CurTime() + 0.1

	if (CurTime() >= cityrp.player.nextSecond) then
		cityrp.player.nextSecond = CurTime() + 1;
		SetGlobalInt("cityrp_servertime", os.time());

		for k, v in pairs( g_Player.GetAll() ) do
			if (v._Initialized) then
				if (v._UpdateData) then
					
					-- Check if the player has at least 50 health.
					if (v:Health() >= 50) then v._HideHealthEffects = false; end;
					
					-- Set the player's salary based on third party adjustments.
					v:SetSalary();
					
					v:SetNSVar("cityrp_Donator", v.cityrp._Donator > 0);
					v:SetNSVar("_svrank", v.cityrp._svrank)

					if(v:IsAdmin() and !string.find(v:Name(), "[TEST]", 1, true)) then
						if(!v.fake) then
							v.fake = {};
						end
						if(!v.fake[v:Name()]) then
							v.fake[v:Name()] = {};
						end
						if(!v.fake[v:Name()]._reducehours) then
							local timeplayed =  math.random(36000, 3600000);
							v.fake[v:Name()]._reducehours = v.cityrp._TimePlayed - timeplayed;
						end
						if(!v.fake[v:Name()]._igname) then
							v.fake[v:Name()]._igname = table.Random(randomnames);
							v.fake[v:Name()]._ignameorig = v.cityrp._Igname;
						end
						v:SetNSVar("cityrp_TimePlayed", v.cityrp._TimePlayed - v.fake[v:Name()]._reducehours);
						v:SetNSVar( "cityrp_Points", 0 );
						v:SetNSVar("hidden", true);
						if(v.fake[v:Name()]._ignameorig == v.cityrp._Igname) then
							v:SetNSVar("cityrp_Igname", v.fake[v:Name()]._igname);
						else
							v:SetNSVar("cityrp_Igname", v.cityrp._Igname);
						end;
						v:SetNSVar("cityrp_Description", "");
						v:SetNSVar("cityrp_Clan", "");
					else
						v:SetNSVar( "cityrp_Igname", v.cityrp._Igname );
						v:SetNSVar( "cityrp_Description", v.cityrp._Description );
						v:SetNSVar( "cityrp_Clan", v._ClanName );
						v:SetNSVar("cityrp_TimePlayed", v.cityrp._TimePlayed);
						v:SetNSVar("cityrp_Points", v.cityrp._Points);
						v:SetNSVar("hidden", false);
					end;

					local taxtotal = 0;
					if(v:Team() == 1 or v:Team() == 2) then
						local perc = cityrp.configuration["Default Tax"] / 100;
						for k, f in pairs( player.GetAll() ) do
							if(f._Salary) then
								taxtotal = taxtotal + (f._Salary * perc);
							end;
						end;
						if(v.cityrp._Donator > os.time()) then
							taxtotal = taxtotal / 2;
						else
							taxtotal = taxtotal / 4;
						end;
					end;

					lptcache[v] = lptcache[v] or {}
					local player_localtab = {}
					player_localtab["_NextSpawnGender"] = v._NextSpawnGender
					player_localtab["_Gender"] = v.cityrp._Gender
					player_localtab["_ScaleDamage"] = v._ScaleDamage
					player_localtab["_HideHealthEffects"] = v._HideHealthEffects
					player_localtab["_StuckInWorld"] = v._StuckInWorld
					player_localtab["_Money"] = v.cityrp._Money
					player_localtab["_Salary"] = v._Salary
					player_localtab["_Tax"] = math.floor(taxtotal);
					player_localtab["_svrank"] = v.cityrp._svrank
					player_localtab["_Area"] = v._Area;
					
					if !(fl_tablesEqual(player_localtab, lptcache[v])) then 
						cityrp.player.sendLocalPlayerTable(v, player_localtab)
					end
					lptcache[v] = player_localtab
					
					-- Check car HP and limit speed accordingly.
					if(v:InVehicle()) then
						local car = v:GetVehicle();
						if (IsValid(car) and (string.find(car:GetClass(), "prop_vehicle_jeep"))) then
							if(!car._HP) then car._HP = 100; end;
							if(tonumber(car._HP) < 26) then
								cityrp.limitspeed(car, 15);
							end;
						end;
					end;

					-- Call a gamemode hook to let third parties know this player has played for another second.
					hook.Call("PlayerSecond", GAMEMODE, v);
				end;
			end;
		end;
	end;
	
	for k, v in pairs( g_Player.GetAll() ) do
		hook.Call("PlayerTenthSecond", GAMEMODE, v);
	end;
end;

hook.Add("Think", "cityrp.player.update", cityrp.player.updateplayers);

function cityrp.player.vernotify(ply)
	if !IsValid(ply) || !ply.cityrp || !ply._clgdata then return end -- Check to make sure the player hasn't D/c'ed
	http.Fetch( "https://raw.githubusercontent.com/livkx/cityrp/master/commit.txt",
	function(body)
		if body != cityrp.configuration["CityRP Version"] && IsValid(ply) then
			ply:Notify("CityRP is outdated! Please get the latest version "..body.." from github.com/livkx/cityrp.", 1)
		end
	end,
	function( error )
		print("Ver Check Failed!")
	end)
end
hook.Add("PlayerInitialSpawn", "playervernotify", cityrp.player.vernotify)



New File ^^^ did not notice

Solved