Davion
Idle Hand


Group: Administrators
Posts: 1,422
Joined: May 14, 2006
|
#31 id:36744 Posted Oct 25, 2009, 11:55 pm
|
Mudder said:
Erok said:I haven't looked at it, but if you are working with an existing codebase, migrating it to libevent is also an option that has good documentation and user forums.
Currently I'm using a rom codebase. RaM fire, actually.
I downloaded libevent but have absolutely no idea how to make use of it. It's a library, right? ...My knowledge with such things leaves much to be desired.
It looks like this code is meant to replace the entire socket layer. It's quite a modification for someone just starting out :). Might want to consider writing your own.
|
......................... 
|
|
Erok
Magician

Group: Members
Posts: 64
Joined: Jul 27, 2009
|
#32 id:36811 Posted Oct 27, 2009, 9:57 am
|
Davion said:It looks like this code is meant to replace the entire socket layer. It's quite a modification for someone just starting out :). Might want to consider writing your own.
I'll take a look a SocketMud, and see how much effort it would be to migrate it to libevent. It sounds like it would be helpful to have a reference implementation of an event driven MUD available.
|
|
|
JohnnyStarr
Wizard


Group: Members
Posts: 822
Joined: Feb 14, 2009
|
#33 id:36833 Posted Oct 27, 2009, 2:24 pm
|
Here's my event system idea: (let me know what you think)
I am using EventMachine for the server object. I have an event queue that can schedule
one time or reoccurring events. It can even have events schedule other events. Then, I am
going to use the Observer Pattern to have the game-objects observe each other. Here's a quick
example:
Code (text): 1
2
3
4
5
6
7
8
9
10
11
12
13 |
(event queue)-> runs: cleanup_corpses
|
->(room 1300)-> runs: remove_corpse
|
(state of room 1300 has changed)-> notify_observers "A corpse decays into nothing."
|
Aragorn.send "A corpse decays into nothing."
Legolas.send "A corpse decays into nothing."
|
This seems good so far, but this is pretty new stuff to me, so I would appreciate any constructive criticism.
|
|
.........................
"It's not the daily increase but daily decrease. Hack away at the unessential." - Bruce Lee
Last edited Oct 27, 2009, 2:26 pm by staryavsky
|
|
|
|
Tyche
Wizard


Group: Members
Posts: 1,343
Joined: May 23, 2006
|
#35 id:36838 Posted Oct 27, 2009, 3:58 pm
|
Mudder said:
What does that mean exactly? I thought ticks were themselves an event? I realize that with each "tick" other events are triggered off of this and creates a somewhat machine like feel but how else could this be done without creating other versions of a "tick" and making them fire off other events. In a sense, simply creating a tick for each event type. So how could a MUD truly be "tick free" and purely "event driven" ?
This thread may be of interest to you.
Anyway I pull in my take on events...
Tyche's Immediate Temporal System
Here are the two simple laws of TITS:
# An event is issued at the point of a state change.
# An event is guaranteed to complete.
Events should not be scheduled to occur at some future point in time as events are by their very nature immediate. That is to say a scheduled event is not really an event but a potential event.
Consider the consequences of the TITS-less implementation above. If something should occurred before the scheduled event like an earthquake, flood, or a hole is ripped in the space time continuum that redirects or otherwise voids the destination, then there is no way the event can occur, be completed and will be invalidated. One must handle that. Or consider the consequences of your present TITS-less system. Either way you will be faced with unsatisfactory results unless you embrace and grasp TITS.
There are many others involving causality and logic errors, a few examples:
Inevitable Death scenario:
Bob eats a poisoned apple.
A death event is scheduled to occur in 10 minutes.
Bob takes an antidote to the poison.
Bob dies in ten minutes.
Elves and the Swordmaker scenario:
Bob is crafting a sword
A sword completed event is scheduled to occur in 2 hours
Bob goes to the local pub gets drunk and returns to smithy in time to receive the completed sword
Non-interruptus scenario:
Bob begins casting a fireball
A fireball spell event is scheduled to occured in 2 minutes
Sam knocks Bob unconscious
Bob completes the casting of the spell and a fireball is produced
All of these problems have different solutions depending on how you want the scenario to play out, most involve carefully removing the non-event from the queue or writing additional (code) to carefully check the validity of the assumed state.
Event removal may also introduces new problems...
Item Eaters and the Swordmaker scenario:
Bob is crafting a sword
A sword completed event is scheduled to occur in 2 hours
Someone knocks on the shop door and Bob goes to answer it.
The sword completed event is removed from the queue.
Bob returns to an empty work bench and has to start all over again.
Expanded definition of TITS theory:
# An event is something that happens at a point in time. Now, not in the future!
# An event has no duration. No duration!
# Two events may be said to precede or follow another or may be unrelated.
# Those that are unrelated are said to be concurrent.
# An event is a one way transmission of information from one object or subsystem to another object or subsystem.
# It is not like a subroutine, thus there is no return. An object or subsystem may expect a reply, but this reply would be in the form of an event under control of the second object or subsystem.
# Objects or subsystems are considered to be innately concurrent.
It certainly quite difficult to test and build a system or even generate meaningful event-state diagrams to test your system when you don't know the state! Scheduling events to occur in the future implies that these aren't really single discrete events as they actually have a duration, but actually pairs of events with some unspecified/undefined state that exists in between.
A Ruby implementation of TITS can be found in TeensyMud available at all fine mud code repositories.
|
.........................  
For now we see through a glass, darkly; but then face to face: now I know in part; but then shall I know even as also I am known.
Last edited Oct 27, 2009, 4:01 pm by Tyche
|
|
Erok
Magician

Group: Members
Posts: 64
Joined: Jul 27, 2009
|
#36 id:36840 Posted Oct 27, 2009, 4:42 pm
|
Tyche said:Anyway I pull in my take on events...
So without having seen your TITS, I think what you are saying is that an event should be the result of a state transition, of which a timeout can be one of many triggers. Yes, no argument here.
|
|
|
Scandum
Wizard


Group: Members
Posts: 1,400
Joined: Aug 8, 2006
|
#37 id:36844 Posted Oct 27, 2009, 6:21 pm
|
Tyche said:
Events should not be scheduled to occur at some future point in time as events are by their very nature immediate. That is to say a scheduled event is not really an event but a potential event.
You can link an event to an object. When an event is removed from the event hash it's also removed from the object it is attached to, and when the object is removed all events tied to it vanish as well. This at least guarantees data access and integrity.
|
|
|
quixadhal
Wizard


Group: Members
Posts: 1,472
Joined: Oct 17, 2007
|
#38 id:36847 Posted Oct 27, 2009, 8:47 pm
|
Tyche said:
Item Eaters and the Swordmaker scenario:
Bob is crafting a sword
A sword completed event is scheduled to occur in 2 hours
Someone knocks on the shop door and Bob goes to answer it.
The sword completed event is removed from the queue.
Bob returns to an empty work bench and has to start all over again.
So, without having looked at your TITS, would this be one way to model the above safely?
Bob begins crafting a sword.
Event happens, creating an incomplete sword object.
The sword object begins completing itself on a timer, adding a percent
every N minutes that it, Bob, and the workbench are together.
Bob leaves the workbench to answer the door.
Event happens, The sword object stops updating, since Bob is not present.
Bob returns.
Event happens, The sword continues updating, since all three components are present.
The sword's completion percentage hits 100%.
Event happens, incomplete sword object replaced with crafted sword object.
Bob goes out and drinks a beer.
If I'm buying into the theory, each event is a state change, but the actual timer-based actions are not events but listeners which may change their behavior based on events they observe. If the shop catches fire and destroys the workbench, that would presumably generate an event which the incomplete sword would see as a component becoming unavailable.
|
......................... 
|
|
Koron
Sorcerer

Group: Members
Posts: 382
Joined: Jun 7, 2008
|
#39 id:36850 Posted Oct 27, 2009, 9:34 pm
|
I loathe minute based timers. They're so imprecise. I just had to put that out there.
I would make the incomplete sword object track its timer based on the amount of time (seconds, probably!) Bob was in the room with (bob->crafting_item == this) while unintoxicated, awake and whatever other complications need to be absent to allow proper crafting time. Every second those conditions are TRUE, decrement the timer. To complicate things, you can add stages at which interruptions destroy (or weaken) the final product.
Of course, this is ideal-world stuff. Just because Bob logs off doesn't mean his crafted item is destroyed. If he's whittling a staff, there's no reason to expect interruptions to do anything other than delay completion. Real world complications may arise as you try to decide how to store these states. Woo!
|
Last edited Oct 27, 2009, 9:35 pm by Koron
|
|
JohnnyStarr
Wizard


Group: Members
Posts: 822
Joined: Feb 14, 2009
|
#40 id:36852 Posted Oct 27, 2009, 10:33 pm
|
I trust Tyche on this one, don't get me wrong. But it seems like some additional mechanism is required to accomplish things this way.
For example, what mud doesn't need global events like; respawns, auctions, weather changes, etc? Of course, I can see that you aren't saying
that muds don't need these, because every popular mud has them. It seems like if you passed enough arguments to the event, you could accommodate
for any potential logic conflicts. But then again, I'm not as experienced as Tyche or others yet, so I must be missing something.
|
|
.........................
"It's not the daily increase but daily decrease. Hack away at the unessential." - Bruce Lee
Last edited Oct 27, 2009, 10:34 pm by staryavsky
|
|
Scandum
Wizard


Group: Members
Posts: 1,400
Joined: Aug 8, 2006
|
#41 id:36853 Posted Oct 27, 2009, 11:31 pm
|
quixadhal said:
So, without having looked at your TITS, would this be one way to model the above safely?
Bob begins crafting a sword.
Event happens, creating an incomplete sword object.
The sword object begins completing itself on a timer, adding a percent
every N minutes that it, Bob, and the workbench are together.
Ideally you'd want to place the player in a crafting state, and the sword would keep track of the progress as its state is steadily altered toward being finished, but the sword itself shouldn't be doing anything. If Bob leaves to answer the door that would change his state, and subsequently stop anything associated to that state, including the crafting of the sword. In an ideal situation the unfinished sword wouldn't be replaced by a finished sword either. If a bandit was to enter the store Bob should be able to pick up the unfinished sword and defend himself.
I think the trouble starts when the events are supposed to keep track of an object's state, or detect when a state change has occurred.
staryavsky said:It seems like if you passed enough arguments to the event, you could accommodate
for any potential logic conflicts. But then again, I'm not as experienced as Tyche or others yet, so I must be missing something.
The more information carried by the event the more information is lost when the event becomes invalid, so I'd say the trick is to store the various states and data on the objects and keeping the events as simple as possible.
|
|
|
David Haley
Wizard


Group: Members
Posts: 6,874
Joined: Jun 30, 2007
|
#42 id:36857 Posted Oct 27, 2009, 11:51 pm
|
Koron said:Just because Bob logs off doesn't mean his crafted item is destroyed. If he's whittling a staff, there's no reason to expect interruptions to do anything other than delay completion. Real world complications may arise as you try to decide how to store these states. Woo!
This is a very interesting distinction IMO: the difference between global time and "character time" or "session time". Many events are indeed global, but others only make sense during the lifetime of a character -- and when you have characters like players that can appear and disappear "at will" you need to decide if the event persists along with them. This seems far-fetched, until you think about relatively common situations like duration spells: should these all disappear when the character logs off?
|
|
|
Erok
Magician

Group: Members
Posts: 64
Joined: Jul 27, 2009
|
#43 id:36897 Posted Oct 28, 2009, 4:48 pm
|
Erok said:I'll take a look a SocketMud, and see how much effort it would be to migrate it to libevent. It sounds like it would be helpful to have a reference implementation of an event driven MUD available.
I've got this mostly working now.
Socket i/o is handled asynchronously, and there are two repeating jobs (events, timers, whatever). One fires every 10s to call recycle_sockets(), and the other fires every pulse to call update_handler(). Whatever update_handler() is supposed to do (presumably combat and all that other good stuff), it could be broken up into smaller jobs (single shot or repeating) that are handled independently of each other.
I need to handle shutdown, copyover, and clean things up, and then I'll upload it here. It's not beautiful, and this was my first foray into libevent, which isn't as nicely designed as ASIO, but it was relatively painless to get going.
|
Last edited Oct 28, 2009, 4:50 pm by Erok
|
|
Erok
Magician

Group: Members
Posts: 64
Joined: Jul 27, 2009
|
#44 id:36944 Posted Oct 29, 2009, 5:16 pm
|
Erok said:I'll take a look a SocketMud, and see how much effort it would be to migrate it to libevent. It sounds like it would be helpful to have a reference implementation of an event driven MUD available.
Ok, I just uploaded EventMud-1.0 under the SocketMud branch in the code repository (it won't show up until cleared by the admin staff).
Disclaimer: This was the first time I'd looked at either SocketMud or libevent, so quality is neither guaranteed nor implied.
|
Last edited Oct 29, 2009, 5:18 pm by Erok
|
|
Tyche
Wizard


Group: Members
Posts: 1,343
Joined: May 23, 2006
|
#45 id:36945 Posted Oct 29, 2009, 5:31 pm
|
quixadhal said:
Bob begins crafting a sword.
Event happens, creating an incomplete sword object.
The sword object begins completing itself on a timer, adding a percent
every N minutes that it, Bob, and the workbench are together.
Bob leaves the workbench to answer the door.
Event happens, The sword object stops updating, since Bob is not present.
Bob returns.
Event happens, The sword continues updating, since all three components are present.
The sword's completion percentage hits 100%.
Event happens, incomplete sword object replaced with crafted sword object.
Bob goes out and drinks a beer.
If I'm buying into the theory, each event is a state change, but the actual timer-based actions are not events but listeners which may change their behavior based on events they observe. If the shop catches fire and destroys the workbench, that would presumably generate an event which the incomplete sword would see as a component becoming unavailable.
A timer event is just a state change in time, informing any object listening that the time changed.
If I were doing a simulationist crafting game, I'd do pretty much what Scandum described. I'd check that the resources were present to build the item, put the character or characters in a crafting mode, make sure I'm registered with a timer, and then begin tracking completion of the item as I receive time events. If resources or characters disappear, or go out of crafting mode, we don't continue to progress the crafting. I'd probably create a crafting job, so multiple resources, products and characters could be associated with it, rather than put all the state tracking in the product (sword).
|
.........................  
For now we see through a glass, darkly; but then face to face: now I know in part; but then shall I know even as also I am known.
|
|