Hey!
#11
Yeah, it's not nice, but why would it be scary?
Reply
Thanks given by:
#12
@qaisjp In that code snippet what happens if a player is disconnected whist that snippet is executing? Is there a look on the player object or are you guaranteed to execute on a particular thread?

@bearbin callbacks can be confusing to a beginner. Just look at all the questions on stackoverflow about ajax and variables not updating.
Reply
Thanks given by:
#13
Callbacks = spaghetti code. Spaghetti code = vomit. The only place callbacks are appropriate are for events (onTick, onDead, but these aren't really callbacks) and for databasing (although databasing would be super cool if it was based around coroutines instead; read "how it works"). For us, everything "just works".
We list what scripts we want running in a specific order in a meta file. (example)
These scripts are run and whatever we ask for we are given immediately.

Anywhere and anytime.

Also I think the retrieval of a player by name should be case insensitive (or a boolean value to toggle the case sensitivity).


edit:
The netcode does not run parallel (or for some other reason) making it impossible for a person to leave midcode.
If the code I posted was in a timer/loop, even if the connection is dropped, for us, a player element will still exist until the next "tick". Then in the next tick the event is called.

I'm not 100% sure what the main loop is like for MTASA, I'll take a plunge into the code and ask around but this is how I think it goes:
netcode happens -> cpp calls magic events in lua vm -> more netcode updates
Or atleast:
netcode happens -> net code happens -> netcode happens
events called -> events called ->

But I'm probably wrong, because vehicles/objects/peds can be created instantaneously and immediately manipulated. I'll ask around.
Reply
Thanks given by:
#14
Ah so your single threaded. That makes things soooo much easier. Problem is that in mcserver's architecture you have to hold the players lock when using a player object. Otherwise the object can be removed right under you're code. So if we had an api like you're example:
Code:
p = Player("qaisjp")
// what happens if another thread deletes p here?
Kick(p, "Because I say so")
So you have to hold the lock whilst doing stuff with a player. Aquiring the lock is easy. The problem comes when we need to release it. There are two ways of doing this in lua. One is to __require__ that users call a function when they are finished with the player. This is a horrible interface because people forget. And the other way is callbacks. So the choice was callbacks or explicit lock releases. And we went for callbacks because then you can't get it wrong and crash the server.
Reply
Thanks given by:
#15
(06-13-2014, 03:29 AM)worktycho Wrote: Ah so your single threaded. That makes things soooo much easier. Problem is that in mcserver's architecture you have to hold the players lock when using a player object. Otherwise the object can be removed right under you're code. So if we had an api like you're example:
Code:
p = Player("qaisjp")
// what happens if another thread deletes p here?
Kick(p, "Because I say so")
So you have to hold the lock whilst doing stuff with a player. Aquiring the lock is easy. The problem comes when we need to release it. There are two ways of doing this in lua. One is to __require__ that users call a function when they are finished with the player. This is a horrible interface because people forget. And the other way is callbacks. So the choice was callbacks or explicit lock releases. And we went for callbacks because then you can't get it wrong and crash the server.
I'm probably going off on a tangent, but it probably works better in Minecraft because you guys actually have a server that is aware of the physical world (for us, only players + script created elements are synced). What's wrong with Lua's garbage collection system (for releasing a lock)? Why do you actually have to lock a player, can't you just "modify the data"?

If there was a way to schedule a disconnection it could work. For example:

1. person times out
2. server catches timeout during a script
3. schedule a hook call: "disconnect for reason "timeout" event"
3. server allows script to do what it wants to do until the script ends, return a success for everything (allow the getting of the name) (I'm not sure what kind of client-only capabilities are there, so a script could probably not do everything it is allowed to do).
4. if a player is kicked in the script, the client obviously would just get a timeout message but the kick event overwrites the schedule event (server thinks its a kick, client thinks its just a time out)
5. do kick message console log
6. call disconnect event for type "kick"

I think this works for us because we have an element based system where instead of having direct access to a client (so if a client disconnects, the player element is gone), a player is bound to a client. The only time a player element variable can turn nil (or if isElement(player) == false) is if the argument is passed around in a timer or if it's accessed later in a table.


By the way, what is the time zone on this O_O
Reply
Thanks given by:
#16
The problem with lua's garbage collection is that its a non-deterministic collector (like java). It only collects when lua is running low on memory. If you want to see why we cant use it for locks I suggest you read http://blogs.msdn.com/b/oldnewthing/arch...47586.aspx on the CLR gc which works in the same way. Long story sort is we can't guarantee locks are released.

We have a element based system as well. The problem is that someone has to clean up the player object when the client is gone and the plugin has no guarantees that its run on the same thread as the one that does the clean up. It could be any of the network threads or a generating thread or another worlds thread. So no matter where we move the clean up there's still a risk a plugin could be working with it at the same time.
Reply
Thanks given by:
#17
:/

I don't know if f you looked at lapis, but, couldn't we just run each plugin (or all plugins) in one gigantic coroutine (get rid of those filthy callbacks!). (Click me, this forum seems to have invisible links)
Reply
Thanks given by:
#18
Lapis solves a different problem of how to have a single threaded lua do things asynchronously. Our problem is different in that we need to do multi-threading safely. The key thing is that the callbacks are being used differently. In lapis callbacks would have been used similar to node where the purpose is to allow the server to do something else whilst waiting for whatever you where waiting for to finish. What we use callbacks for is scoping locks as lua does not provide any other way to do it.
Reply
Thanks given by:
#19
Oh, right, yes of course... :/

Well, I don't know then :/ I've always worked in a single thread..
Reply
Thanks given by:




Users browsing this thread: 7 Guest(s)