[Fix] PointShop users losing points + tmysql4 instead of mysqloo.

**NOTICE: As of 29th August, 2013: Pointshop has been updated with the fix, you no longer need this if you have the latest version. You can still convert to TMYSQL. You don’t need to update your pointshop if you already applied the fix.
**
NOTE: You don’t need to switch to tmysql4 for the fix to work!!

I’ve realized that player inventory and points gets saved without first checking if they’ve been loaded.
Here’s the fix:

In sv_player_extension.lua, replace the functions Player:PS_Save & Player:PS_LoadData() with:



function Player:PS_Save()
	if (self.PS_Loaded) then
		PS:SetPlayerData(self, self.PS_Points, self.PS_Items)
	end
end

function Player:PS_LoadData()
	self.PS_Points = 0
	self.PS_Items = {}
	PS:GetPlayerData(self, function(points, items)
		self.PS_Points = points
		self.PS_Items = items
		
		self:PS_SendPoints()
		self:PS_SendItems()
	end)
	self.PS_Loaded = true;
end

Add this to the end of the file: (Thank you ajLittle for reporting the problem.)



function PS_ServerChangeMap()
	for k, v in pairs( player.GetAll() ) do
		-- Save the player's data so that it doesn't reset next map.
		v:PS_Save()
	end;
end

hook.Add( "ShutDown", "PS_ServerChangeMap", PS_ServerChangeMap )

My server never had a problem since the beginning thanks to this small tweak.

To get rid of MySQLOO and use tmysql4, replace your mysql.lua provider with:



--[[

	PointShop MySQL Adapter by _Undefined
	
	Usage:
	
		First, make sure you have the MySQLOO module installed from:
			http://www.facepunch.com/showthread.php?t=1220537
			Installation instructions are in that thread.
	
		Then configure your MySQL details below and import the tables into your
			database using the provided sql file. If you do not have a database
			already set up, do that before importing the file.
		
		MAKE SURE YOU ALLOW REMOTE ACCESS TO YOUR DATABASE FROM YOUR GMOD SERVERS IP ADDRESS.
		
		If you're upgrading from the old version, run the following SQL before starting your server and then remove the old tables (pointshop_points and pointshop_items):
		
			INSERT INTO `pointshop_data` SELECT `pointshop_points`.`uniqueid`, `points`, `items` FROM `pointshop_points` INNER JOIN `pointshop_items` ON `pointshop_items`.`uniqueid` = `pointshop_points`.`uniqueid`
		
		Once configured, change PS.Config.DataProvider = 'pdata' to PS.Config.DataProvider = 'mysql' in pointshop's sh_config.lua.
	
]]--


-- end config, don't change anything below unless you know what you're doing

local shouldmysql = true

PROVIDER.Fallback = 'pdata'

function PROVIDER:GetData(ply, callback)
    if not shouldmysql then self:GetFallback():GetData(ply, callback) end
     GetDBConnection():Query("SELECT * FROM pointshop_data WHERE uniqueid = '" .. tmysql.escape(ply:UniqueID()) .. "'", function(result)
            if (result and type(result) == "table" and #result > 0) then
                    local row = result[1]
                    local points = row.points or 0
                    local items = util.JSONToTable(row.items or '{}')
                    callback(points, items)
            else
                    callback(0, {})
            end
        end, 1);
end
 
function PROVIDER:SetData(ply, points, items)
    if not shouldmysql then self:GetFallback():SetData(ply, points, items) end
    GetDBConnection():Query("INSERT INTO `pointshop_data` (uniqueid, points, items) VALUES ('" .. tmysql.escape(ply:UniqueID()) .. "', '" .. (points or 0) .. "', '" .. tmysql.escape(util.TableToJSON(items or {})) .. "') ON DUPLICATE KEY UPDATE points = VALUES(points), items = VALUES(items)")
end

Note: tmysql connection should be initiated before calling any of those two functions…I initiate it in the init function of the gamemode.

Nice one :slight_smile:

What would be the benefit of using tmysql? I don’t know what either of them do. :stuck_out_tongue:

I think instead of rating the dude above me as dumb, you should try to answer his question; unless of course you don’t know either, then what does that say about you? I don’t know the answer, and would also like to know. It’s never dumb to ask questions so you can learn new things.

http://www.productivity.org/projects/tmysql/

I personally switched to tmysql since my gamemode is already using it and I didn’t want the extra MySQLOO Module, plus I would only one one connection to the database instead of one from MySQLOO and one from tmysql. To top it off, I didn’t like the OnSuccess and OnFail callbacks. tmysql is simpler for me.

tmysql isn’t object oriented

that’s the main difference, it’s pretty much personal preference

I just thought I should tell you guys, after I put this on players can sell the item, and on next map change it will re-add it to their inventory, so basically a way to farm points.

unlike the previous versions of tmysql, tmysql4 is object oriented (atleast some of it is):
GetDBConnection():Query

[editline]20th August 2013[/editline]

Hmm, did you only implement the fix or did you switch to tmysql?

I will look into this. I’ve never experienced this since my server is RP and never needed to change maps.

This is my attempted fix: It should work. Try it and tell me if it still happens.
Add this to the end of sv_player_extension.lua:


function PS_ServerChangeMap()
	for k, v in pairs( g_Player.GetAll() ) do
		-- Save the player's data so that it doesn't reset next map.
		v:PS_Save()
	end;
end

hook.Add( "ShutDown", "PS_ServerChangeMap", PS_ServerChangeMap )

Could you elaborate please? Thank you.

Well, before you send any queries, you must first connect to the database with
tmysql.initialize(host, user, pass, port);
It only needs to called once serverside. Once it’s called, it will return you with a connection object. Save that object somewhere.
Then you need to make a function called GetDBConnection() that returns that object and you’ll be good to go.

THis fix should work fine with MySQLOO without having to switch to tmysql4 correct?

Yes. You do not need to convert to tmysql4.

After applying this update, Pointshop seems to broadcast a very odd message.


You were awarded 0 points from Server.

Here’s a screenshot: http://i.imgur.com/XFJ24Ge.jpg

Does anyone else have the same problem?

EDIT: Another addon was conflicting.

Which addon was it? Inform us please.

This is an error which I found recently:


17:10:08 Lua Error: [ERROR] addons/pointshopmaster/lua/sv_player_extension.lua:460: attempt to index global 'g_Player' (a nil value) 
1. fn - addons/pointshopmaster/lua/sv_player_extension.lua:460 
2. unknown - addons/ulib/lua/ulib/shared/hook.lua:183

Line 460:


	for k, v in pairs( g_Player.GetAll() ) do

and this is line 183 of the hook.lua


				-- Call hook function
				if isstring( v.name ) then
					a, b, c, d, e, f = v.fn( ... )       --::::::::::::::::::::::::::::::::::::::::This is line 183
				else

I hope this does not count as bump since it is on topic + it is rather important and not a troll post.


g_Player.GetAll()

should be


player.GetAll()

Sorry about that, I have a habit of making global variables for ease. Fixed it in OP.
You don’t need to change anything, it’s basically just what Pandaman09 fixed.

We fixed this a while ago in commit c04cd81199a6e5e092f6b89e5c7c87f3b263e149.
I suggest pulling latest instead of using this patch.

@Handsome Matt, Thanks, I updated the OP with a notice.