29 Jul, 2009, Kintar wrote in the 1st comment:
Votes: 0
I'm curious to know if anyone has done any work on a MUD server based on a component system instead of a class hierarchy.

For anyone not familiar with the term, a component system differs from a typical class hierarchy system in that each potential "class" of object is a separate, stand-alone class definition. At runtime, the items and mobs within the mud are nothing more than a reference number or string that is associated with one or more instances of those component classes. So, a knife might be Entity #15 and have the components "MudObject" and "Weapon", rather than being a class "Knife" that extends "Weapon" which extends "MudObject".

If anyone has used or worked on such a system, I'm curious to know what you think its greatest strength and greatest weakness is/was.
29 Jul, 2009, ghasatta wrote in the 2nd comment:
Votes: 0
You could call what I have come up with to be a hybrid. Each object can have one or more parent prototypes, and the prototypes can in turn have other prototypes as parents. So, using your example, Entity #15 could have "Knife" as a parent, which would have Weapon as a parent, etc. However, Entity #15 could also have "MagicWand" as a parent, which would cause it to inherit another set of properties.

I have found this to be more flexible than more traditional 'types'. It is still hierarchical, primarily for builder convenience - I don't think anyone wants to add the low level properties (e.g. 'MudObject') to each and every item they design. However, it has no built in limitations. It is also possible to override a parent's properties for special objects. An example might be a "SharpKnife" prototype that redefines the damage numbers from the "Knife" prototype, but leaves all the other properties intact.

When I originally built this system, I intentionally left it as open and free-form as possible. It turns out though, that people working to actually create objects felt a little adrift – it was too wide open. I didn't include any way to distinguish between lower level prototypes such as "physical object" or "arm" and higher level ones such as "leather cowl" or "bastard sword". Consequently it was a bit cumbersome to ensure that you were adding the proper parents to your object and not something too low level. Something to consider if you implement something similar.
29 Jul, 2009, Kintar wrote in the 3rd comment:
Votes: 0
How did you implement the prototypes? Were they classes in the classic sense, or were they defined as collections of key/value pairs on some other, more generic type? I've played with both mechanisms, and have been finding a special type of pain in each. ;)
29 Jul, 2009, JohnnyStarr wrote in the 4th comment:
Votes: 0
What kind of codebase are you using?
Are you adding this to something existing? Are you building the codebase from scratch? If so,
what language are you using?

I like the idea, and am curious about it.
30 Jul, 2009, Idealiad wrote in the 5th comment:
Votes: 0
ghasatta, you're describing a system of mix-in classes, no (or in other words, basically multiple inheritance)?

The main problem I've heard people talk about with inheritance-based component models is forgetting to limit the scope of a particular mix-in (or prototype), because then you can get in the situation where two mix-ins have similar functionality. But then if you override one of those methods for a special derived object, it may not be clear that another one of its mix-ins is conflicting with the overridden method. Hopefully someone with more experience here can clear that up. In any case as long as you keep the scope of a component well-defined things should work OK.

Incidentally both the TADS 3 (custom) and PAWS (Python-based) interactive fiction languages use mix-ins in a component model. And NakedMUD uses prototypes I believe.

This is a little off-topic Kintar, but I'm working on a single-player game now that uses a component model and I like it a lot, but I'm still at such an early stage I can't really speak to its greatest advantages or disadvantages. I found this thread and also this thread at TIGSource an interesting read on the topic.
30 Jul, 2009, flumpy wrote in the 6th comment:
Votes: 0
Kintar said:
I'm curious to know if anyone has done any work on a MUD server based on a component system instead of a class hierarchy.

For anyone not familiar with the term, a component system differs from a typical class hierarchy system in that each potential "class" of object is a separate, stand-alone class definition. At runtime, the items and mobs within the mud are nothing more than a reference number or string that is associated with one or more instances of those component classes. So, a knife might be Entity #15 and have the components "MudObject" and "Weapon", rather than being a class "Knife" that extends "Weapon" which extends "MudObject".

If anyone has used or worked on such a system, I'm curious to know what you think its greatest strength and greatest weakness is/was.


That sounds more like protyping to me. Item "knife" could be a Weapon object, that is also a MudObject, but there are many different kinds of ordinary weapons: one which happens to have the id "knife" or "knife230487", or whatever.

I use this kind of system in GroovyMud via the power of the Grails BeanBuilder (which utilizes Spring), so I can have one MOB class with a lot of generic things in them. I declare my prototype mob like this:

tcWander(MOBWander)  // ordinary wander behaviour

tcChanceToWander(ChanceBehaviour){ // make it random
numDice = 1
sides = 1000
chance = (0..5)
behaviour = ref('tcWander')
}

//declare a goblin prototype
"goblin"(MOBImpl, name:"hob-goblin", shortNames:["goblin"]){bean->
bean.parent = ref("baseMob", true)
bean.lazyInit = true

articleRequired = true
description = "This is a $name."
heartbeatBehaviours = [ref("tcChanceToWander")]
}


.. and then I can get an instance of my hob-goblin from the spring context using either the same "ref" mechanism as above (when defining other prototypes), or use applicationContext.getBean("goblin") (programatically).


The strengths of this are that I don't have to create hundreds of different mob classes, just prototypes with different abilities. The downsides, if any, are that I am tending to overuse the prototype system for the wrong kind of thing, such as defining rooms, where it is not really powerful enough. Another problem is that I may (although I have not as yet) hit problems with duplicate bean id's. I can adopt best practice to avoid this happening tho, since the beans id can be set programatically too:

def $area = "my/area/name"



"$area:goblin"(MOBImpl){bean->
bean.parent = ref("baseMob", true)
bean.lazyInit = true
articleRequired = true
description = "This is a $name."
heartbeatBehaviours = [ref("tcChanceToWander")]
}


Apart from that, it really is quite powerful.

Was this the kind of thing you meant?

[EDIT]

I also have no way with a beanbuilder prototype (although I could be wrong) to add any functionality. If I extend the Weapon object I can add extra methods to it, but with the beanbuilder I cannot just add methods willy-nilly.

This precludes me from doing things like defining a new room that is a shop, because a shop may have a buy command function associated with it, and this can be frustrating at times. However I feel this is a limitation of myself, and an over-expectation of the tool rather than an actual limitation of the technique.
31 Jul, 2009, hollis wrote in the 7th comment:
Votes: 0
I do something like you describe. Things inherit from a list of templates that define the thing's functionality and behavior. My system isn't quite the same as you describe, however. Game things are more than just a reference number and a list of components. I had originally thought of doing it this way, but the problem that I ran into is that I wanted game things to be mutable (swords might receive enchantments, NPCs might vary their stats between instantiations). So instead, things act more like a whiteboard where various templates can "post" behavior and functionality onto. In 90% of circumstances, this works the same as (I think) what you are describing would, but it's just all put together a little looser.

This results in conflicts or overriden behavior every now and then, like Idealiad says, but it isn't often; things in mud worlds are so well-defined that you don't have these sorts of conflicts often. When they do, I have a script attached to game things that runs whenever the thing is loaded to sanitize any conflicts. This is one of the reasons I really like a post-it-board system over a rigid component system (things can extend themselves when needed).

In both cases, I think there's three main pros. First, it really helps reduce redundancy in game development (compared to, say, the DIKU approach which I am most familiar with). If you want to design an armor or weapon, you just inherit from the relevant template(s) and simply provide descriptions. If you want to make a big stretch of similar rooms (for whatever reason), just make one master version and have all the others inherit from it and link them appropriately. Developers have minimal repetitive things they need to do.

A component approach allows you to mix behavior and functionality from multiple sources together fluidly. I find MUD worlds are often very boring and generic. In part, I think this is because of the onerous nature of making a hand-crafted interesting, interactive world. When you can just "plug in" components that define interesting behavior your world suddenly becomes much more interesting, and you're always looking for places to spruce the world up instead of dreadfully avoiding the topic.

A component approach can help avoid power creep. With the loose quality control that most muds have, it's not uncommon for the overall power of used equipment to increase as a slightly overpowered item appears here or there. If a designer must use the knife component to make a knife, you gain a great deal of control over what your designers are doing (balance-wise).

NakedMud was designed to be amenable to this "component" type system you are describing, and that's what I do my development with.
31 Jul, 2009, flumpy wrote in the 8th comment:
Votes: 0
Ok I've been doing some reading up on component based programming, and I guess I am way off…

Wikipedia says that:

wikipedia said:
The idea in object-oriented programming (OOP) is that software should be written according to a mental model of the actual or imagined objects it represents. OOP and the related disciplines of object-oriented design and object-oriented analysis focus on modeling real-world[citation needed] interactions and attempting to create 'verbs' and 'nouns' which can be used in intuitive[citation needed] ways, ideally by end users as well as by programmers coding for those end users.

Component-based software engineering, by contrast, makes no such assumptions, and instead states that software should be developed by gluing prefabricated components together much like in the field of electronics or mechanics. Some peers[who?] will even talk of modularizing systems as software components as a new programming paradigm.


So, a bit like an OLE/COM based mud… interesting idea. I would like to see how that would work in reality.
03 Aug, 2009, Kintar wrote in the 9th comment:
Votes: 0
Thanks for the input, everyone! Sorry I've been quiet; ended up out of town for the past few days to help my parents take the honey off their bees. ;)

I'm glad to see that others have used this kind of approach. I'm currently building a component-based codebase from scratch in Java, but I'm becoming very frustrated with my attempt to mix dynamically alterable types (i.e., entities with runtime-mutable components) and a strongly typed language. I want very much to be able to strongly type method calls to prevent the huge class of "you thought this was type X, but it isn't" errors that can occur when a MUD's development team isn't very experienced, but at the same time I don't want to go back to something like Diku where we end up with huge "god functions" that deal with enormous if/then or switch statements, or something like CoffeeMUD where EVERYTHING in the game is a subclass of some parent type and inherits gobs of functionality it might not need.

In short, I'm beginning to finally understand why some MUDs (LP, LambdaMOO, Mud2) just decided to implement their own domain-specific language for MUD programming. :P
03 Aug, 2009, flumpy wrote in the 10th comment:
Votes: 0
Kintar said:
Thanks for the input, everyone! Sorry I've been quiet; ended up out of town for the past few days to help my parents take the honey off their bees. ;)

I'm glad to see that others have used this kind of approach. I'm currently building a component-based codebase from scratch in Java, but I'm becoming very frustrated with my attempt to mix dynamically alterable types (i.e., entities with runtime-mutable components) and a strongly typed language. I want very much to be able to strongly type method calls to prevent the huge class of "you thought this was type X, but it isn't" errors that can occur when a MUD's development team isn't very experienced, but at the same time I don't want to go back to something like Diku where we end up with huge "god functions" that deal with enormous if/then or switch statements, or something like CoffeeMUD where EVERYTHING in the game is a subclass of some parent type and inherits gobs of functionality it might not need.

In short, I'm beginning to finally understand why some MUDs (LP, LambdaMOO, Mud2) just decided to implement their own domain-specific language for MUD programming. :P


This is precisely why I used the Groovy scripting language.

Have you heard of Groovy/Scala/Haskell/Beanshell/Rhino? These are all JVM scripting languages that you could use to perform the same job as LPC? Java even has a Lua engine I believe. Java6 also has it's own scripting engine you could leverage. One day I might leverage it myself, but I didn't know about it when I started out.

On the other hand, if you'd like to help my project (it's mostly written in Java, with a Groovy language mudbase) then you would be most welcome - it is a code base from scratch that has taken me about a year and a half to do so far and still isn't quite there. You are also welcome to fork the code and doctor it to produce your own, obviously if you comply with the license that is :)
03 Aug, 2009, David Haley wrote in the 11th comment:
Votes: 0
You can't have your cake and eat it too, Kintar. :wink: When working in Java, either you have strong typing, or you have to reimplement the dynamic features yourself one way or another. It is very hard to push the full scale of dynamic type mixing to Java's strong typing.

In a sense, you have Java's type system, and you are implementing your own type system on top of it. It's important to remember that Java's types do not have to map directly to the types in your game logic.

This is tricky business and it's pretty easy for your head to explode when dealing with the many levels of type. It's a much more complicated version of having code objects vs. in-game objects.

I would recommend trying to implement your game types (knife, town guard, whatever) using some separate mechanism from the Java class hierarchy. If these game-types are just collections of responses to events, you can capture that somewhat easily. And you can still implement high-level types in Java like GameObject, GameActor, GameRoom, whatever.

But basically, you will need to distinguish between your code objects and types, and your game objects and types.

flumpy said:
Java even has a Lua engine I believe.

Indeed, although it's a bit out of date. I believe that the author is in the process of updating it to Lua 5.1.4. Unless you were referring to Kahlua, which is actually an implementation of Lua in Java (as opposed to a binding to the C API, which is what LuaJava does). I don't remember what Kahlua's status is, to be honest…
03 Aug, 2009, Kintar wrote in the 12th comment:
Votes: 0
flumpy said:
This is precisely why I used the Groovy scripting language.

Have you heard of Groovy/Scala/Haskell/Beanshell/Rhino?


Yep! Actually, my first pass at this kind of thing was with Java as the core engine, and all the game objects and logic implemented in Groovy. But I kept coming back to the fact that ensuring sloppy scripts didn't blow up in messy ways was requiring me to enforce some kind of strong typing, or else go to a whole lot of trouble isolating the threads that were running dynamic code and then doing a lot (and I mean a /lot/) of exception handling and error reporting.

BTW: I'd be very curious to see a Scala-based MUD at some point, if for no other reason than I want to see their Actor threading system leveraged to deal with all the message passing that goes on. =)

David Haley said:
In a sense, you have Java's type system, and you are implementing your own type system on top of it. It's important to remember that Java's types do not have to map directly to the types in your game logic.


Very true, although it would be very nice if they did. ;) I thought I was on to something late last week when I had the idea to use components only as definitions of properties on a game object. That way the component definition could be parsed into Java code to declare an interface per component, and I could use dynamic proxies to ensure that the Java-level entity objects implemented all of the component interfaces that were assigned to them. It works, but there are some compromises I had to make when implementing it that I'm not too happy with.

Also, my goal of allowing entities to have their components altered during runtime keeps rearing its ugly head when I start dealing with complex types on game objects. How do I allow a game object to hold a collection of other objects, if the "type" of (as in, the components applied to) any of those objects might change without notice? Using reference objects to get to the entities themselves would work (allowing an extra layer between the entity reference and the actual object implementing the interfaces, thus allowing the classes in use on the implementing object to be discarded and picked up from a new classloader whenever), but then I'm having to trust that the people writing code for this system will only stick reference objects in their collections and not directly add an entity.

I was really hoping I could realize all of my design goals in pure Java, but it's really looking like you're right, and I'll have to put a second layer in there, either via a language like Lua or Groovy, or by writing my own simple compiler that let me abstract the game objects definitions away from Java code.

EDIT: I realized I wasn't clear in the paragraph about dynamic components. Not only should the entities be able to say "I don't want to be a Weapon anymore, now I want to be a Container", but I also am aiming to have the member fields for a "Weapon" or "Container" alterable during runtime. I know, I don't want much. ;)
03 Aug, 2009, Kintar wrote in the 13th comment:
Votes: 0
One of David's comments keeps coming back in my head, so let me take a minute to talk about it, and maybe it'll jar something loose that will be useful. :)

David Haley said:
But basically, you will need to distinguish between your code objects and types, and your game objects and types.


That's a very true statement, and is the basic idea behind using a component system for the MUD. Honestly, the component system idea is so general that it could be used for any game or business system, not just a MUD server. The overall concept I've been working with is this:

When a new thing is created in the game world, a new Java object of type "Entity" is instantiated. This Entity object is used simply as a gathering point for all of the game types (components) that are aggregated to make up the thing in the world. Components are not defined in the server itself. Rather, they are separate Java projects that depend on some of the utility classes from the server, and are compiled into their own Jars. While the server is running, one of these jars can be dropped into the server's components directory, at which point a new classloader is created to handle creation of objects defined in that component module.

This means that, for example, the "Weapon" component could be defined in the combat module. When an Entity is created that is a weapon, like a knife, a Weapon object is instantiated and associated with the Entity representing the knife. Game logic that depends on that entity being a weapon can now make calls like "entity.isA(CombatType.Weapon)" to verify that the Weapon component is applied to the entity, or a call like "Weapon w = entity.as(CombatType.Weapon)" to retrieve the Weapon object itself. Properties distinct to weapons, like type of damage, damage dice, etc., can all be retrieved from that component object.

Since components are loaded from separate classloaders, the Weapon component could be changed at any arbitrary time. All classes loaded from the Combat module would be discarded, a new classloader would be created for that module, and then the component classes could be re-created from property or prototype data. The new instances of "Weapon" would have the updated methods and fields from the new combat module Jar file.

This system works, and it works very well; I've got an implementation that has a basic Area/Room/Item/Player mudlib implemented using it. The problems arise when you think about the "average" coder attempting to modify or create a new component class. For example:

class Mobile implements Component {
private Set<Wearable> equipment;

// …

public void wearItem(Wearable w) {
// …
equipment.add(w);
// …
}
}


What happens if Wearable is defined in a separate component module, and that module gets reloaded? We either have to discard and recreate every Mobile component so that the contents of equipment can be created from the new class definition of Wearable, or else we start throwing type mismatch related exceptions the next time some piece of game logic says "Wearable w = mobile.getItemEquippedOnHead()". The other option would be to decree that Component classes can't be stored, instead requiring the Entity to be saved. That's simple for the previous case. The code just changes to something like:

class Mobile implements Component {
private Set<Entity> equipment;

// …

public void wearItem(Wearable w) {
// …
equipment.add(w.entity());
// …
}
}


But what happens if a Component allows the entire set of equipment to be changed at once? Like:

public void setEquippedItems(Set<Wearable> equipment) {
this.equipment = equipment;
}


We can't let them pass in any old set of Entities; what if they're not Wearable? We have to…



Actually, talking about it has helped some. This is one of the reasons that being the only coder is a bad idea! =) The last example I gave seemed like a perfectly reasonable use case until I actually typed it out to explain it. Now, however, it seems like the kind of thing that is completely pointless to try and guard against, and I'm tossing away a perfectly workable component system implementation just to deal with a situation that is very unlikely to come up, and is exceedingly easy to resolve if it DOES come up. :)

Since I've already come this far in the explanation of my last implementation, though, what does everyone think? Overly complicated? Missing something that should be obvious if I'd ever written a mud server before? Or, miracle of miracles, does it sound like a good idea to someone? ;)
03 Aug, 2009, David Haley wrote in the 14th comment:
Votes: 0
Kintar said:
What happens if Wearable is defined in a separate component module, and that module gets reloaded?

Dynamic reloading of any modules is incredibly hairy for all kinds of reasons. :sigh:

Kintar said:
The last example I gave seemed like a perfectly reasonable use case until I actually typed it out to explain it. Now, however, it seems like the kind of thing that is completely pointless to try and guard against, and I'm tossing away a perfectly workable component system implementation just to deal with a situation that is very unlikely to come up, and is exceedingly easy to resolve if it DOES come up. :)

I agree. I would make the common use cases easy to deal with, and then simply forbid things that are too annoying and that wouldn't be used. If something is useful and annoying, well, you just have to provide interface functions to deal with it, even if they're annoying. :wink:

Kintar said:
Since I've already come this far in the explanation of my last implementation, though, what does everyone think? Overly complicated? Missing something that should be obvious if I'd ever written a mud server before? Or, miracle of miracles, does it sound like a good idea to someone? ;)

It seems reasonable enough to me, although I have to admit that I'm still only at the prototyping stage myself and don't know how well these things end up in practice.

One thing you've got me thinking about for the n^th time is how much I want to put in Lua vs. a statically typed language. Currently I use C++ and Lua and was pushing off an awful lot of stuff to Lua. I'm thinking I might move more to C++. The problem with objects existing in two "language spaces" is that you have to work very hard to keep memory management in control; you don't want to destroy a C++ object and have its Lua reference lying around. Head explosion time. And on that note, time constraints force me to stop this here. :smile:
03 Aug, 2009, Kintar wrote in the 15th comment:
Votes: 0
David Haley said:
Dynamic reloading of any modules is incredibly hairy for all kinds of reasons. :sigh:


Don't I know it, brother! :tongue: You should have seen my first few prototypes; you'd think I was on crack when I wrote them! =)

David Haley said:
If something is useful and annoying, well, you just have to provide interface functions to deal with it, even if they're annoying. :wink:


LOL! Very well said. ;)

David Haley said:
It seems reasonable enough to me, although I have to admit that I'm still only at the prototyping stage myself and don't know how well these things end up in practice.


Like I said, my first viable build on this premise worked pretty well. Design issues that were related to serialization caused me to scrap most of it and start again, but the basic component system worked far better than I expected it to.

David Haley said:
One thing you've got me thinking about for the n^th time is how much I want to put in Lua vs. a statically typed language. Currently I use C++ and Lua and was pushing off an awful lot of stuff to Lua. I'm thinking I might move more to C++. The problem with objects existing in two "language spaces" is that you have to work very hard to keep memory management in control; you don't want to destroy a C++ object and have its Lua reference lying around. Head explosion time. And on that note, time constraints force me to stop this here. :smile:


So are you saying you'd move away from LUA because you'd like to get back to a more statically-typed language, or because you're wanting to reduce your memory-management-related Advil intake? ;)
03 Aug, 2009, David Haley wrote in the 16th comment:
Votes: 0
Unfortunately I can't go into much detail at the moment, but there are two main things:

1- it is really, very, awfully nice to have static typing for "core engine" functionality. Lua doesn't allow this.
2- it is difficult to manage objects that can exist in one or both "language spaces" – in essence you have to implement your own garbage collection (of sorts) on top of Lua's garbage collection! It's … well, it's headache-prone. :wink:

I'll talk more about this later – maybe even with some code examples.
03 Aug, 2009, Kintar wrote in the 17th comment:
Votes: 0
Looking forward to hearing about it when you've got some time!
03 Aug, 2009, flumpy wrote in the 18th comment:
Votes: 0
Kintar said:
Yep! Actually, my first pass at this kind of thing was with Java as the core engine, and all the game objects and logic implemented in Groovy. But I kept coming back to the fact that ensuring sloppy scripts didn't blow up in messy ways was requiring me to enforce some kind of strong typing, or else go to a whole lot of trouble isolating the threads that were running dynamic code and then doing a lot (and I mean a /lot/) of exception handling and error reporting.


There's nothing wrong with strong typing in a mixed type language. Actually I found it was more me than the language, as static typing came more naturally. When you dynamically type, unit testing is paramount, otherwise yes you do get all sorts of runtime issues.

[edit] as for exception handling, I don't see an issue with your mud catching Exception in this case. After all, the Mud is your framework, and you don't really want it to blow up just because one script fails.

Really, you should download GroovyMud and take a look. A lot of it is "not how to do it" but I am learning myself, so if you have questions you can ask away I'm only an email away.

Kintar said:
BTW: I'd be very curious to see a Scala-based MUD at some point, if for no other reason than I want to see their Actor threading system leveraged to deal with all the message passing that goes on. =)


Me too :D

David Haley said:
In a sense, you have Java's type system, and you are implementing your own type system on top of it. It's important to remember that Java's types do not have to map directly to the types in your game logic.


Hmm. Yes, but Groovy (and other scripting languages) have already done this for you. You don't need to go reinventing the wheel.

Kintar said:
Also, my goal of allowing entities to have their components altered during runtime keeps rearing its ugly head when I start dealing with complex types on game objects. How do I allow a game object to hold a collection of other objects, if the "type" of (as in, the components applied to) any of those objects might change without notice?


Well, you don't actually go about never checking the object for some semblance of interface.. in a dynamically typed language you check for availability of a method before calling it. I don't really find there's much in checking "type" with "instanceof" or checking "respondsTo".


Kintar said:
I was really hoping I could realize all of my design goals in pure Java, but it's really looking like you're right, and I'll have to put a second layer in there, either via a language like Lua or Groovy, or by writing my own simple compiler that let me abstract the game objects definitions away from Java code.

EDIT: I realized I wasn't clear in the paragraph about dynamic components. Not only should the entities be able to say "I don't want to be a Weapon anymore, now I want to be a Container", but I also am aiming to have the member fields for a "Weapon" or "Container" alterable during runtime. I know, I don't want much. ;)



Well, Groovy's dynamic metaClass lets you do this. You can add and remove methods to an object just like in Ruby. I think you can even change the type of the object at runtime by using "as" when passing it about. Really, you don't actually care about typing at all, you care if it has the method you want to call. "If it quacks like a duck.."

[edit]

Here's a brief example of a dynamic object. I added this today as a quick way to get the god power in my mud.
MudObjectImpl redPill = context.getBean("blankMudObject") // get a new object from the spring context -
// or you could use a map "[:] as MudObjectImpl"
//if you wanted (would need to run "initialise" after creation tho)
redPill.setName("red pill")
redPill.setShortNames(["pill", "red pill"])
redPill.setDescription("A small, red pill. Are you ready to find out the truth? Then eat it…")
redPill.metaClass.eat = { Alive player, String str ->
if(str == "red pill" && delegate.currentContainer == player){
Thread.start(){
sendMessageToRoom(player, "You almost choke as you swallow the little red pill…",
"${player.name} looks a bit sick as he eats a red pill.")
Thread.sleep(2000)
sendMessageToRoom(player, "Wow, that feels MUCH better.", "A flash of light bursts forth from
${player.name}'s mouth as the power of a God issues forth. ")
player.subject.principals.add(new MudPrincipal("god"))
delegate.dest(true)
}
return true
}
return false
}
03 Aug, 2009, Kintar wrote in the 19th comment:
Votes: 0
All very good points about Groovy! I have to admit, though, that as much as I love Groovy for use in certain cases (I use it quite a bit in unit testing, and in certain highly fluid portions of my day job), it carries a LOT of overhead that I'd prefer not to have. Just the size of the runtime jar made me shudder when it was part of my MUD server's core, and there were times when I wanted to set fire to my computer just because of the depth of the stack traces I was getting during testing. :)

Also, and I'll freely admit that this is probably something I was doing wrong, there were a few cases where very innocuous operations would run off down rabbit holes for hundreds, if not thousands, of milliseconds. One example was in an early prototype. I had a command implemented in Java, and it was working just fine. I literally changed the extension on the source file to .groovy and recompiled, and the command started taking over two seconds to complete. More debugging would have likely solved that issue, but I was already considering a different approach for some of the core system, and it was a lot simpler to just yank Groovy out of the mix entirely.

I'll probably end up going back to it when it comes time to implement mobprog, though. I'm not sure I have the patience or the bandwidth to implement my own scripting language right now. ;)
03 Aug, 2009, flumpy wrote in the 20th comment:
Votes: 0
Kintar said:
All very good points about Groovy! I have to admit, though, that as much as I love Groovy for use in certain cases (I use it quite a bit in unit testing, and in certain highly fluid portions of my day job), it carries a LOT of overhead that I'd prefer not to have. Just the size of the runtime jar made me shudder when it was part of my MUD server's core, and there were times when I wanted to set fire to my computer just because of the depth of the stack traces I was getting during testing. :)


Yes, I am hoping that improves as the version numbers increase…
Kintar said:
Also, and I'll freely admit that this is probably something I was doing wrong, there were a few cases where very innocuous operations would run off down rabbit holes for hundreds, if not thousands, of milliseconds. One example was in an early prototype. I had a command implemented in Java, and it was working just fine. I literally changed the extension on the source file to .groovy and recompiled, and the command started taking over two seconds to complete. More debugging would have likely solved that issue, but I was already considering a different approach for some of the core system, and it was a lot simpler to just yank Groovy out of the mix entirely.


Yes. You don't need to do the core as groovy. My core is Java, not Groovy at all. Its faster that way. Groovy for scripting the mud, Java for running the core threading and the telnet stuff.

Kintar said:
I'll probably end up going back to it when it comes time to implement mobprog, though. I'm not sure I have the patience or the bandwidth to implement my own scripting language right now. ;)


… I've actually implemented a "mobprog" in groovy, as a DSL. Again if you need some help…
0.0/43