Cuberite Forum
Thunder - Printable Version

+- Cuberite Forum (https://forum.cuberite.org)
+-- Forum: Cuberite (https://forum.cuberite.org/forum-4.html)
+--- Forum: Development (https://forum.cuberite.org/forum-13.html)
+--- Thread: Thunder (/thread-1926.html)

Pages: 1 2


Thunder - NiLSPACE - 05-09-2015

Anyone know why cWorld:GetNumPlayers is commented out? It could be used to make thunder work correctly.

int NumPlayers = GetNumPlayers();

class cThunderCaster : public cPlayerListCallback
{
	int m_PlayerToCastThunderAt;
	int m_CurrentPlayer;
	
	virtual bool Item(cPlayer * a_Player)
	{
		if (m_CurrentPlayer != m_PlayerToCastThunderAt)
		{
			return false;
		}
		
		// Cast thunder somewhere around the player
		return true;
	}
	
	public:
		cThunderCaster(int a_PlayerToCastThunderAt) :
			m_PlayerToCastThunderAt(a_PlayerToCastThunderAt),
			m_CurrentPlayer(0)
		{}
} ThunderCaster(GetTickRandomNumber(NumPlayers));

ForEachPlayer(ThunderCaster);



RE: Thunder - worktycho - 05-09-2015

Its commented out because it encourages dangerous code. For example the code given has a chance of not casting any thunder at all.


RE: Thunder - xoft - 05-09-2015

It's mostly due to multithreading - it was causing deadlocks when used, and once you got your answer you still wouldn't know any better, because players may have disconnected from another thread in the meantime.

How about adding cWorld:DoWithRandomPlayer(a_Callback)?


RE: Thunder - worktycho - 05-09-2015

That's two specific, How about DoWithPlayerList?


RE: Thunder - xoft - 05-09-2015

Good enough, except for the name. It's not a list. How about simple DoWithPlayers() ?


RE: Thunder - worktycho - 05-09-2015

Too similar to DoWithPlayer. And its a list of things, even if it's not a linked list, c++ is about the only language where list automatically means linked list.


RE: Thunder - Shadowraix - 05-13-2015

These kind of issues where a player disconnecting causing issues is confusing to me. In the environment I worked in we usually had methods that would search for a player so something like

Code:
local Player = game.Players:FindPlayer("Player")

Then the Player variable would store the player object then I can simply do
Code:
if Player then
--code
end

Is this not feasible with your API? This method of things seems a lot better instead of worrying about player disconnecting. Player will just become nil when the player disconnects. That if statement can handle the player disconnecting easily.


RE: Thunder - xoft - 05-13-2015

Due to multithreading it cannot be so simple - the "player disconnecting" will be processed by a different thread running in parallel to your plugin, so the Player object can become invalid right after the IF has checked it to be valid, but before the --code executes:
-- Player is currently connected, PlayerObj is a valid object
if (PlayerObj) then
  -- Player disconnects right here
  -- PlayerObj becomes invalid
  PlayerObj:SendMessage("...")  -- fails - PlayerObj invalid, despite the condition
end
This is the price we pay for being multithreaded - we do need to use the DoWith and ForEach calls. Those guarantee that the object is valid as long as the callback is executing (but, again, you cannot store the object to be used later after the call).


RE: Thunder - Shadowraix - 05-13-2015

(05-13-2015, 06:40 AM)xoft Wrote: Due to multithreading it cannot be so simple - the "player disconnecting" will be processed by a different thread running in parallel to your plugin, so the Player object can become invalid right after the IF has checked it to be valid, but before the --code executes:
-- Player is currently connected, PlayerObj is a valid object
if (PlayerObj) then
  -- Player disconnects right here
  -- PlayerObj becomes invalid
  PlayerObj:SendMessage("...")  -- fails - PlayerObj invalid, despite the condition
end
This is the price we pay for being multithreaded - we do need to use the DoWith and ForEach calls. Those guarantee that the object is valid as long as the callback is executing (but, again, you cannot store the object to be used later after the call).

I see, what about using pcall? This way your code won't break the whole script and if it errors out anywhere in it, it can be handled? If used rarely then I can see it working fine. I know pcall is relatively slow compared to regular function calls.


RE: Thunder - xoft - 05-13-2015

The problem is that the PlayerObj is invalid, but not nil, so accessing it will hard-crash the server. The underlying C++ cPlayer object is gone, but the Lua object is still pointing to the memory it used to occupy.