From what I have read in the forums, a lot of the questions and ideas you have brought up are covered within the development code of the 2.7.3 version of DuskRPg that is hosted here on SourceForge.
Currently, no one is working on the project that I am aware of, and what I am currently working on has diverted from the normal Dusk stance. However, the code works and is there for you to look at.
Lone Wolf
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The project had a home page hosted by Captain, the founder of the project, when it first started. He's long since exited the Project, however, and so the homepage is no longer operational.
At one point there were atleast 5 live servers up and running with one of the 5 servers having at least 30 users playing on it at the same time- if I remember correctly. Now, as far as I know, all the servers are dead. This is what I found after taking a year's sabatical from the project.
There is a lot to the code and even more to what I have changed and not uploaded since it no longer coincides with Dusk's design as created by Captain.
If you have any questions though, I can probably answer most of them.
Lone Wolf
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hmm ... i downloaded the files, but I couldn't find a "Quick start". What should I do to see some results quick?
(e.g. starting a small server and connecting to it!)
You are using a script language. This is something I thougt a lot about in the past. I thought, that using a script language is much to slow. The server should be able to handle multiple player like real muds. So I took Java itself to expand the game.
This has some problems e.g. updating existing objects, but I think, that the speed of my solution is much better.
With kind regards,
Konrad
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I agree with you about scripting. The over usage of it was the first thing to go in my new architecture. Scripting takes too much I/O, which is the slowest method of storage. However, scripting can be a valuable asset if done right and it is loaded at startup into a cache. Something, that I was working on with DuskRPG before I left the project.
As for a quick start... I have added new release files to the FILES portion of the DuskRPG website. Just be sure to download all three file: DuskClient7.3_Runnable, DuskServer7.3_Runnable, and DuskServer_DataFiles.zip
Then extract the DuskServer_DataFiles.zip into a directory first. Next extract the DuskServer7.3 files into the DuskRPG directory created by the DataFiles zip. Execute the Dusk.bat file in the DuskRPG directory. The server should now be up and running.
Last extract the DuskClient zip anywhere you like, and execute the Start.bat file. Click on Connect. Click on the Connect button within the Connect Frame. Then enter in darkcloud as the username, and sandrock as the password. yes or no for "Allow others to see you in the who list?" and then press a direction key. You are off and running.
Note: The map is a barebone basic one that I just gimmied up for you to use. You can change the map through the map editor by typing in "mapeditor on" on the command line. You will be giving a few tab options to choose from. Everything should be point and click with the editor.
Have fun.
Lone Wolf
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hmmm ... it seems to work, but I didn't see any pictures at the client.
I looked at the available pics in the folders and found some nice pics :) It would be fine to see them in "action".
It would be fine, if we could come together to create a game. If you are interested, we could discuss the game, we want to create. Maybe we come together to work on one project only.
In the moment I don't see the main structure of DuskRPG, so all I can tell you are the things, I believe in:
1) Using java for "scripting" stuff. I wouldn't call it scripting. Extending is a better word in my eyes.
2) Objects are not completly saved. Only attributes are saved (In the moment, it's stored as a HashMap).
3) dividing two parts (as in lpmud drivern muds):
- Driver
- Lib
The driver does all management-actions and the Lib is the stuff, that will be extended.
4) Reducing Traffic as much as possible! It should be possible to run a server as cheap as possible. Traffic costs money and somebody has to pay for it.
My next tasks would be:
- creating some kind of menues (buttons), that could be displayed and used from the player.
- Fight System
- Fixing some stuff with objects, that are seen or not seen.
With kind regards,
Konrad Neitzel
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
There was a problem with the run method of the Ticker Class found within the DuskEngine.java file that was causing my processor to soar. So I commented out the code. This will reduce what you are able to do in the game however, since it is what controls the clock and mob actions. I didn't have time to figure out exactly what was causing the problem and the problem used to not occur. If you wish to see the full functionality you will need to take a little time to find out the problem.
Also.. I found that one of the source java files... in the either the Client package or the Server package... has an extra ';' in it that needs to be removed. other than that, they all appeared to compile nicely.
Lone Wolf
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Ack! I apologize. You are correct. I did not add the rc help portion to the client zip. *sigh*.
You have all that is needed, however. Inside of the DuskRPG directory is a subdirectory called 'rc'. Copy this entire directory to 'C:\rc'.
Then your image should be accessable.
As for the other things:
1) What you are wanting is object oriented polymorphing and inheritance, which Java does handle nicely.
2) DuskRPG saves attributes in data files which are loaded at runtime. So you can add mobs, etc. merely by adding another mob file to the \mobs directory and then adding the mob name and location to the mob config file in the main DuskRPG directory. This applies for all aspects of the game, including floor tiles, room actions, skills, spells, merchants, etc.
3) I do not understand your 'driver' piece unless you mean the 'engine'. If that is what you mean, then that is what I was doing to Dusk before I took a vacation from the project, and what I have done to my new version. That is merely packaging the source code into their proper places and setting scope rights accordingly. The 'lib' would be for stand-alone encapsulated code such as entity beans and third party code.
4) Aye. That takes a lot of design time in figuring out what will need to be transfered and how best to polumorph the data into what is needed. It also deals with how much power you want on the Client side. The more transaction handled by the client leads to less traffic to the server. However, the more power on the client lends to a user being able to hack the system easier and make the system not perform as desired. Another aspect is the setup architecture on how the server is handled. Dusk is made as a single tier infrastructure. The version I have recently created uses n-tier. This means that the user logs into a controller server and the controll will then transfer them to another server as needed. In this model, the 'world' does not all have to recide at the same IP address but can be distributed to many different IP with the same inital IP connection to keep track of the traffic. This is similar to clustering servers, but the servers can be miles apart from each other.
Next Tasks:
That's mostly what I have been working on lately is the GUI. I am not totaly satisfied with what I have created so far, but it is a lot better than was in DuskRPG. Also, I have already handled the case of seen and not seen simply by attributes on the object. In the current release of DuskRPG if you look at the "commands" doc you will see that you are able to "Hide names" to objects and players or show them. In the code I have done recently, the system is able to handle that as well as invisibility, see invisibility, stealth, and etc a lot easier.
As for joining, again... you are welcome to use what code you find in DuskRPG. Most of it (with the exception of the DuskScript which is solely Captain's) is my own code. Do be sure to keep the credits for any used code however, since those that contributed do need to be given their due credit.
As for my personal involvement, I can help some but not much at the present. I have a lot I am working on including 3D MMROPG's and Emulators in C++/C# other than my 2D MMROPG in Java. And this is all side projects to my main business oriented projects for customers.
If you wish to IM me, you can reach me on AIM. My screen name is LoneWolf Oolt
Lone Wolf
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
to 2) Did that mean, that the server must keep everything in memory? I want, that the server is able to drop objects, it isn't needing, if free memory is low.
to 3) Yes - you could call the driver also "engine". The main things like ObjectManager or the Timer is part of the engine. The Lib is simple the whole GameStuff itself. (e.g. Class for Level, Class for Player, ...)
to 4) To prevent to easy cheats, the server is handling everything inside. The client is only used to display things and parse Input from the player.
The server should only send to the client: There is an object <id> with description <a> at place <x,y>. The client must know, how to display the object. And the client mzst know, how to display a move of an object. (So you could create an "nethack" client, that simply shows ASCII Chars or a 3D Client, that shows nice graphics :) )
I hope, that you could understand, what I mean (Maybe my description isn't good enough!)
With kind regards,
Konrad
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
2) What you need there is loose binding. What this means is that you instantiate an object when needed at runtime, and then delete the object during runtime when the object is no longer needed. That is basic procedures for memory management and handled with the java gc.
4) That means that there will be a "load" of information having to be passed between the client and server. You may think there is not that much at the present, but once you get into the design you will find there is a lot that must be transfered between client and server. This is the reason I decided to go with the n-Tire distributed model to handle the bandwidth load. Of course, it has its problems and the main bottleneck being the Controller.
Yes I understand, we do that with Dawn of Light in emulating a DAOC server for the client code. DOL is a project hosted on Sourceforge as well, if you are not familiar with the project give it a visit.
Lone Wolf
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
2) Does that mean, that there are allready some basic functions, that could be used easily? I implemented it on my own with an ObjectManager, that knows all objects, which are loaded. There is also a double linked list of recently used object, so I can drop Objects easily when memory gets short.
To Access an Object, You had to know the id and then you can simply request the object from the ObjectManager (that can load an object, if it doesn't know it allready).
4) I will have a look at the DOL project.
With kind regards,
Konrad
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
2) That's a good start and what we did in Dusk. Also, however, there is a way to go beyond that and only load classes as needed as well. This requires what is called a "Bridge" method. What this method does, is it only "loads" classes that are needed for the current operating platform or device drivers. For instance, the JNI code for Mac is different than for Windows. Because of this you would not want to load the Win classes for the Mac. You can therefore, load a proxy 'stub holder' that manages the function calling which in turn loads the appropiate classes to handle the details. This is just a basic and simple example, but can be used quite efficiently for 'extending' a class without having to create several 'subclasses' in memory. I use this approach in my new development.
You're ID on a double way List works very well for object managment however. One thing to look at on that, however, is the expected size of the information to be stored. At one point, it would be better to convert the double list into a SetMap. But only if the content grows to be very large in number and is searched very frequently. For instance, I put my Living (NPC, Player Combined) and Items objects in a SetMap, but everything else in a double list.
For the most part on reducing memory, Java does that for you, as long as proper procedures are stuck too and all references to the object are properly removed. There is, however, no garuantee when the garbage collection will commense.
4) Some others I have found recently on SourceForge that may be of interest are EQMU (A EQ Emulator) and RunUO (an Ultima Online Emulator). RunUO is supposedly in mature status, though I have not used it.
Also... I'll show you the diagrams I used for my new development and you can see how closely your's resembles it:
System Diagram:
Controller (Handles Login, Messaging)
|
________|____________________
| | | |
World I World II World III I/O
Server Server Server Server
(Handles Saving and Loading of Files)
That is a very simple diagram layout of the system, there is much more involved with "polymorphing", "state", and "bridging" that is shown merely as "inheritance" in the diagrams. And even then, I had to leave out a lot of classes due to space layout problems within this textarea box. Hopefully, it will help you out some in the designing of your game.
Lone Wolf
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hmm .. that sounds interesting. I am doing that stuff a little different:
1) The ObjectManager must know all game intern objects with it's id and the simplest way to do this was a hashmap for me. So I always put objects there with the id as key.
2) The double-linked list is only used to take care, what objects wasn't used for the longest time.
(So whenever accessing the object through the ObjectManager, the object will be taken from the list and will be put on the end.)
In the moment, I am only planing to use ONE Server. I don't see a need to use multiple server in the moment. Of course, the IO Stuff could be seperated, but that would slow down everything!
(Changed Objects must be written to the IO Server immediately and every time, the object must be loaded again, because some other instance could have changed something e.t.c.! This needs more time, than it is ok for me.
I am thinking of splitting the game into multiple parts (later). But then objects will be part of One server and others are unable to use the object. That would be ok for me ... (I hope, you understand, what I mean!) Or when we need AI routines, that needs much CPU: other computers could do that ... But that isn't needed until now.
Objectoriented stuff:
I think I am doing it the same way - only my structure varies is a little:
- All Objects are SavedObjects. Saved Objects are Objects, that are handled by the ObjectManager (and reside in obj.jadv.*).
- JAdvObject - These are Objects, that can be used in the game. These Objects can contain other objects and will be inside another Object.
And it has a "masterParent" - The name ist not very good - "controller" would be better. (This is a JAdvObject, that controls the object. If the object is in the inventory of the player, the player is the controller. If it is inside a Location, the level is the controller.) If something is changed, the controller is informed. (e.g. the object disappears out of the Level: All Livings, that could see the object should be informed!).
And there are a lot of other Classes, e.g. Level, Location, Living, Player, NPC, ...
Maybe a lot of things should be changed. So I need to build some more interfaces. (Controller could be such an interface)
With kind regards,
Konrad
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This is an example of how I did some bridging within the Living Class. A Mob and Player are very close to each other. The only main difference is that one is user controlled and may have a few different calculations than the other.
With this in mind, I did not create a seperate class for Player and Mob and then subclass those to handle options within them. Instead I decided what parts of their coding would be different, and estracted that out of the common code into their own class. This left me with one main controller class - Living and several small 'service' classes that have nothing in common.
This is the class listing:
Class Living extends MudObject implements Location
Merchant merchant
Learned learned
Attributes attributes
Operations operations
public int gold;
int groupID;
int respawnLength;
long timeOfDeath;
Point bind;
Point range;
boolean isMob;
boolean isExecutingLearned;
boolean isInBattle;
boolean isSitting;
boolean isStunned;
boolean isSilenced;
boolean isSleeping;
boolean noManaUseage;
boolean allowKill;
boolean allowSummon;
int movementType;
As you can tell I have seperated out the parts of the code that would have forced me to 'subclass' the Living Class and kept the common ground. Since in my design Players as well as Mobs may be Merchants but do not 'have' to be merchants. I made two types of Merchant classes and the merchant class to be used is bound to the living object at runtime. If the living object is not a merchant, then the link retains the null setting. The same for the Learned, Operations, and Attribute holders. Each of these will load the classes that are needed for that object since the coding in them are handled differently.
To better understand this I will show the layout for the different types of Merchants:
In this setup, there are three different types of a Merchant that a Living may be. A Vendor to sell goods, A healer to sell heals, resurrections, cures, etc, and a Trainer to sell Skills. If I had not used a bridge approach, then I would have had to create atleast 4 subclasses of mob to handle this for mobs alone. However, I wish to allow the Player to use AI that will allow their character to provide the following services as though they were an NPC (when in away mode, or etc) and therefore to allow the player to have these I would have had to subclass the player class 4 times as well. That would have given me 8 subclasses of living! Next, think of what I would have when I wanted to allow a Mob to be both a Vendor and a Healer or even Vendor, Healer, and Trainer all three. That would mean that I would have had to create a subclass for each possible combination. EGads! That's a lot of classes. So what I did was create a merchant class which my three types inherited from and then using the Merchant declaration as a bridge I linked them to the Living Class. If I wish in the future for a Living to be able to have multiple merchant abilities all I simply need to do is use an array declartion for the merchant and I have the ability to combine any combination of Merchant I wish at runtime. Also, in better lighting.. the Merchant class is really nothing more than an interface and can be thought of that except that I wanted to take out common variable instances from the three classes and keep them in just one class.. the Merchant. If I had not cared about this, then making the Merchant an interface rather than a Class would have been sufficient.
Hopefully this explained more than it confused.
Lone Wolf
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
1) I originally had everything in a hasktable, but after doing some benchmarks I found that unless I had over 5000 objects being handled by the hashtable, the overhead outweight the benefits and were slower all around to process than the lists. Specially for large amounts of additions and transitioning. For living, searching was more important
2) Why do you keep track of which object isn't used for the longest time? Unless it is for caching purposes?
Aye, Dusk is a one server game. I just found java to be a bit slow in handling too many rooms which monster calculations, so I made my version able to distribute the load if needed. One server works well for a start, however. As for IO. I try to do the least amount of IO operations possible. In my opinion, it is WAY too slow. Everything I do is in RAM and cached memory. My IO is only for saving states at intervenal times or force loading. I made an IO server to handle the ability to harnesh my RAID drives on one server for all my worlds. Still, seperate IO server is definitely not needed. And I agree with having a seperate AI server. That is in the my architecture as well. Mostly, I think it all depends on what the goal is that the system is perceived to handle. I would suggest however, that if you plan on being able to handle distributed servers, that you put the code in at the front instead of after. Trust me when I say it says a load of time and headaches.
Aye other than the savedObjects thing which if I think may be refered to IO objects, that is how I have thought best for object handling. The trickiest question I found to this however was finding the best way in "notifying" the 'Living' of the changes. I found I made myself a lot of catch 22's in handling that. I ended up with what I think is the simplest method, though I may be wrong. All my "item" objects and "living change" notifications are handled at a room level. Meaning that individual rooms handle their notifications for objects that reside in them. Status, Spells affects and skill execution notifications are handled within an affect controller that handles only statuses, spells, and skills. All player commands are handled via a command controller, and all monster movents and respawns are handled within a monster controller also userd as the game timer. Originally I had lists within each living object to handle these, and found it a pain in notifying everything that needed notifying in a quick amount of time and removing/adding objects without deadlocks. The controllers I developed keep the deadlocks from happening, and the notification time seems to be acceptable so far. All the controllers are seperate threads running against a batch of qued objects. The controllers themselves are governed by the World Engine.
I wouldn't make a controller an interface. Atleast not in the sense that I think of controllers. I was not able to find too many situations where I need an interface within my system other than where I needed mutiple independant classes having the same methods. Ie. A physical object (item, prop, living) and non physical object (event) needing to both be able to be tied to a specific location or linkable within the map and not being related in any other fashion.
I would be interested in seeing how you have planned out your system. If you will, post a technical documentation of the architecture to the files areas. If you already have one out there, I have failed to be able to find it.
Lone Wolf
BTW: I apologize for those diagrams. They were spaced out properly in the textarea box but the html conversion removed all the spacings.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
1) Hmm .... then I should create a better way to store the objects. Maybe it would be fine to create a balanced search tree... Isn't there already such a class in Java? It would be hard to write it on my own ... my studies of computer science are over for some days :) I know, that these trees are possible, but I don't know, how to organize them exactly ....
2) I need a decision, which object I had to drop out of memory when memory gets short. So I wanted to keep track of the usage of the objects.
(And it is a real fast operation, because only a few pointer must be reset).
I had some technical descriptions, but I removed them :(
I will try to create some more technical description in the next days. (That could be found in the Web! Simply go to the server manual from time to time or - when you have cvs of the game - look at the doc directory!)
I dislike the idea of havaing to many threads. And I fear, that one bad object could block everything!
My way to work is event oriented. There are only a few threads:
- a IOThread, that handles the IO stuff (new java.nio channels!)
- a EventThread, This thread gets an event from an eventqueue and handles it. When done, it gets the next event ...
- EventMaster, Normaly it would only hold the eventqueue, but it is also a thread: It starts the EventThread if needed and checks the EventThread. If an EventThread is blocked, the EVent will be marked as bad, the EventThread is "stopped" (Only marked to stop!) and a new EventThread is created. (That way, we could handle even bad objects. If the heartBeat of an event didn't finish itself, the heartbeat of the object will be stopped)
- TimerTask - The Time handles short and long time timers (e.g. heartbeats, Resets, ...). If a timer is triggert, only an event will be placed inside the eventqueue.
With this setup, I will be sure, that there are no problems with multiple processes. All GameObjects are normaly only accessed through the EventThread. (There could be multiple EventThreads at once if the game becomes too slow :( But I thought, that this isn't a real problem).
And the events are handled almost the same as at your server. But not only rooms are "controller". All objects, that contain other objects and that want to do something ith them, could be a "controller".
So there are levels:
- Needed to calculated, what a player can see
- Needed for stuff like "saying" "calling" ...
Livings:
- They want information about the objects, it is carrying
- They want to be notified, if something is changing
Maybe there will be other possibilities, too. But in the moment, that is all.
And your diagrams: I received your posts as eMails, too. They were really good in the eMails, because the space had the right size there ...
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
1) There are tree classes already in Java: TreeSet and TreeMap.
2) Figured it had to be for caching purposes. I used that on the client side for image and sound handling, but for the server I have everything loaded at one time, and it remains in memory. I recycle what is there with only a few additions when truly needed. This method is also one reason why I decided to use the distributed technique on my servers. I had a limit of 500x500 rooms max on my servers using this approach.
Hehehe.."one bad object block everything" is exactly the reason why I made a seperate thread for each type of handling. If I had only one thread handling the objects... then if that object froze in its operations everything would die. This way, only part of the system dies and the controller will make sure that it resets properly. The way I broke operations up makes the system so that no two objects would have the same operations. For instance, instead of putting "can see", "targeting", "can attack" operations within the Living Class where "every Living objects" has to handle those operations, I put those operations within a tracker and therefore only 1 object handles the operations for multiple living objects. This keeps the living objects from clashing with each other. Of course the downside, is that if the tracker breaks, then all living objects will lose this functionality for the time it takes the controller to see that there is a problem and reseting the tracker. Of course, if I had kept the operations within the Living class and two living objects had conflicted then I had an even bigger problem depending on how I managed my living objects. 1) If my engine thread 'only' was responisble for control over the living objects then if two kiving objects conflicted it could cause the whole engine to fault. If I read your post right and you have levels as independant threads and they are used for controling the living objects, then those would freeze up and everything they control will halt as well. This basically can not be avoided. Something has to freeze and be reset. What I tried to do was limit what was effected to the smallest degree I could. So I broke up major functionalities of the game into seperate thread handlers. I found with duskRpg, that if a player had a conflict between a mob, that the engine would freeze up and everything came to a crashing halt. Even though the players were their own seperate threads, since the mob was handled only by the engine, it caused the engine to freeze. That's another reason I serious dislike IO being done on a world server as well. IO has the greatest potential for freezes, and to be honest, this may have been the greatest cause of freeze ups in the DuskRPG. I am sure there are many different ways to handle the problem, I am just letting you know how I dealt with it. Seperate server for IO and seperate controller threads to handle specific areas of the system that I deemed critical and prone to freeze due to catch 22's.
Lone Wolf
(What? Read the code for documentation?????? Hehehehe.... I wish I had the time.)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
1) TreeSet and TreeMap: Are the trees balanced? The tree, that I want to use, should be a balanced tree. I think that this is a "must have"
2) "bad object is blocking everything":
I think, that having to many threads will bring a really bad performance ... I simply know the problems with IO Threads (The old style with blocking sockets, where each Socket will have it's own thread ...)
And my experience with multiple threads are really bad. When using JBoss, I got some bad exceptions because of JBoss detecting deadlocks :(
Ok - that problem could be solved with a better implementation, but I see some major problems.
In such a game are some objects, that will be changed / queried very often. Imagine Player in a fight. There will be some kind of heartbeat, that restores Hitpoints, the fight will do some calculation, maybe special effects (e.g. Spells) must be taken care of, the computer player will check the opponent, because maybe it want to flee, e.t.c.! There are multiple Threads that all need some information about one object. And maybe all want to change one thing in an object!
Synchronized objects could be nice, but that slow downs the game (that was my experience).
3) "Read the code for documentation"
NOOOO ... There will be two parts:
a) JavaDoc - These will describe packages and classes
b) Website (or ./doc/ directory) will get manuals about server and client.
With kind regards,
Konrad
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I found out, that these Trees are balanced. In the javadoc is only written, that these trees have "Red-Black Tree" implementations and I don't know that type of trees (or I know other names).
I searched in google and found, that these red-black trees are balanced trees. So I had a replaement for my hashmap now :)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
From what I have read in the forums, a lot of the questions and ideas you have brought up are covered within the development code of the 2.7.3 version of DuskRPg that is hosted here on SourceForge.
Currently, no one is working on the project that I am aware of, and what I am currently working on has diverted from the normal Dusk stance. However, the code works and is there for you to look at.
Lone Wolf
I will have a closer look in the next days. I found durskrpg, but there was no homepage, so have gone further :)
Maybe it is usefull for me and maybe we could merge our efforts.
With kind regards,
Konrad
The project had a home page hosted by Captain, the founder of the project, when it first started. He's long since exited the Project, however, and so the homepage is no longer operational.
At one point there were atleast 5 live servers up and running with one of the 5 servers having at least 30 users playing on it at the same time- if I remember correctly. Now, as far as I know, all the servers are dead. This is what I found after taking a year's sabatical from the project.
There is a lot to the code and even more to what I have changed and not uploaded since it no longer coincides with Dusk's design as created by Captain.
If you have any questions though, I can probably answer most of them.
Lone Wolf
Hmm ... i downloaded the files, but I couldn't find a "Quick start". What should I do to see some results quick?
(e.g. starting a small server and connecting to it!)
You are using a script language. This is something I thougt a lot about in the past. I thought, that using a script language is much to slow. The server should be able to handle multiple player like real muds. So I took Java itself to expand the game.
This has some problems e.g. updating existing objects, but I think, that the speed of my solution is much better.
With kind regards,
Konrad
I agree with you about scripting. The over usage of it was the first thing to go in my new architecture. Scripting takes too much I/O, which is the slowest method of storage. However, scripting can be a valuable asset if done right and it is loaded at startup into a cache. Something, that I was working on with DuskRPG before I left the project.
As for a quick start... I have added new release files to the FILES portion of the DuskRPG website. Just be sure to download all three file: DuskClient7.3_Runnable, DuskServer7.3_Runnable, and DuskServer_DataFiles.zip
Then extract the DuskServer_DataFiles.zip into a directory first. Next extract the DuskServer7.3 files into the DuskRPG directory created by the DataFiles zip. Execute the Dusk.bat file in the DuskRPG directory. The server should now be up and running.
Last extract the DuskClient zip anywhere you like, and execute the Start.bat file. Click on Connect. Click on the Connect button within the Connect Frame. Then enter in darkcloud as the username, and sandrock as the password. yes or no for "Allow others to see you in the who list?" and then press a direction key. You are off and running.
Note: The map is a barebone basic one that I just gimmied up for you to use. You can change the map through the map editor by typing in "mapeditor on" on the command line. You will be giving a few tab options to choose from. Everything should be point and click with the editor.
Have fun.
Lone Wolf
Hmmm ... it seems to work, but I didn't see any pictures at the client.
I looked at the available pics in the folders and found some nice pics :) It would be fine to see them in "action".
It would be fine, if we could come together to create a game. If you are interested, we could discuss the game, we want to create. Maybe we come together to work on one project only.
In the moment I don't see the main structure of DuskRPG, so all I can tell you are the things, I believe in:
1) Using java for "scripting" stuff. I wouldn't call it scripting. Extending is a better word in my eyes.
2) Objects are not completly saved. Only attributes are saved (In the moment, it's stored as a HashMap).
3) dividing two parts (as in lpmud drivern muds):
- Driver
- Lib
The driver does all management-actions and the Lib is the stuff, that will be extended.
4) Reducing Traffic as much as possible! It should be possible to run a server as cheap as possible. Traffic costs money and somebody has to pay for it.
My next tasks would be:
- creating some kind of menues (buttons), that could be displayed and used from the player.
- Fight System
- Fixing some stuff with objects, that are seen or not seen.
With kind regards,
Konrad Neitzel
One more thing of note.
There was a problem with the run method of the Ticker Class found within the DuskEngine.java file that was causing my processor to soar. So I commented out the code. This will reduce what you are able to do in the game however, since it is what controls the clock and mob actions. I didn't have time to figure out exactly what was causing the problem and the problem used to not occur. If you wish to see the full functionality you will need to take a little time to find out the problem.
Also.. I found that one of the source java files... in the either the Client package or the Server package... has an extra ';' in it that needs to be removed. other than that, they all appeared to compile nicely.
Lone Wolf
Ack! I apologize. You are correct. I did not add the rc help portion to the client zip. *sigh*.
You have all that is needed, however. Inside of the DuskRPG directory is a subdirectory called 'rc'. Copy this entire directory to 'C:\rc'.
Then your image should be accessable.
As for the other things:
1) What you are wanting is object oriented polymorphing and inheritance, which Java does handle nicely.
2) DuskRPG saves attributes in data files which are loaded at runtime. So you can add mobs, etc. merely by adding another mob file to the \mobs directory and then adding the mob name and location to the mob config file in the main DuskRPG directory. This applies for all aspects of the game, including floor tiles, room actions, skills, spells, merchants, etc.
3) I do not understand your 'driver' piece unless you mean the 'engine'. If that is what you mean, then that is what I was doing to Dusk before I took a vacation from the project, and what I have done to my new version. That is merely packaging the source code into their proper places and setting scope rights accordingly. The 'lib' would be for stand-alone encapsulated code such as entity beans and third party code.
4) Aye. That takes a lot of design time in figuring out what will need to be transfered and how best to polumorph the data into what is needed. It also deals with how much power you want on the Client side. The more transaction handled by the client leads to less traffic to the server. However, the more power on the client lends to a user being able to hack the system easier and make the system not perform as desired. Another aspect is the setup architecture on how the server is handled. Dusk is made as a single tier infrastructure. The version I have recently created uses n-tier. This means that the user logs into a controller server and the controll will then transfer them to another server as needed. In this model, the 'world' does not all have to recide at the same IP address but can be distributed to many different IP with the same inital IP connection to keep track of the traffic. This is similar to clustering servers, but the servers can be miles apart from each other.
Next Tasks:
That's mostly what I have been working on lately is the GUI. I am not totaly satisfied with what I have created so far, but it is a lot better than was in DuskRPG. Also, I have already handled the case of seen and not seen simply by attributes on the object. In the current release of DuskRPG if you look at the "commands" doc you will see that you are able to "Hide names" to objects and players or show them. In the code I have done recently, the system is able to handle that as well as invisibility, see invisibility, stealth, and etc a lot easier.
As for joining, again... you are welcome to use what code you find in DuskRPG. Most of it (with the exception of the DuskScript which is solely Captain's) is my own code. Do be sure to keep the credits for any used code however, since those that contributed do need to be given their due credit.
As for my personal involvement, I can help some but not much at the present. I have a lot I am working on including 3D MMROPG's and Emulators in C++/C# other than my 2D MMROPG in Java. And this is all side projects to my main business oriented projects for customers.
If you wish to IM me, you can reach me on AIM. My screen name is LoneWolf Oolt
Lone Wolf
Ok - I will try it again.
to 2) Did that mean, that the server must keep everything in memory? I want, that the server is able to drop objects, it isn't needing, if free memory is low.
to 3) Yes - you could call the driver also "engine". The main things like ObjectManager or the Timer is part of the engine. The Lib is simple the whole GameStuff itself. (e.g. Class for Level, Class for Player, ...)
to 4) To prevent to easy cheats, the server is handling everything inside. The client is only used to display things and parse Input from the player.
The server should only send to the client: There is an object <id> with description <a> at place <x,y>. The client must know, how to display the object. And the client mzst know, how to display a move of an object. (So you could create an "nethack" client, that simply shows ASCII Chars or a 3D Client, that shows nice graphics :) )
I hope, that you could understand, what I mean (Maybe my description isn't good enough!)
With kind regards,
Konrad
2) What you need there is loose binding. What this means is that you instantiate an object when needed at runtime, and then delete the object during runtime when the object is no longer needed. That is basic procedures for memory management and handled with the java gc.
4) That means that there will be a "load" of information having to be passed between the client and server. You may think there is not that much at the present, but once you get into the design you will find there is a lot that must be transfered between client and server. This is the reason I decided to go with the n-Tire distributed model to handle the bandwidth load. Of course, it has its problems and the main bottleneck being the Controller.
Yes I understand, we do that with Dawn of Light in emulating a DAOC server for the client code. DOL is a project hosted on Sourceforge as well, if you are not familiar with the project give it a visit.
Lone Wolf
2) Does that mean, that there are allready some basic functions, that could be used easily? I implemented it on my own with an ObjectManager, that knows all objects, which are loaded. There is also a double linked list of recently used object, so I can drop Objects easily when memory gets short.
To Access an Object, You had to know the id and then you can simply request the object from the ObjectManager (that can load an object, if it doesn't know it allready).
4) I will have a look at the DOL project.
With kind regards,
Konrad
2) That's a good start and what we did in Dusk. Also, however, there is a way to go beyond that and only load classes as needed as well. This requires what is called a "Bridge" method. What this method does, is it only "loads" classes that are needed for the current operating platform or device drivers. For instance, the JNI code for Mac is different than for Windows. Because of this you would not want to load the Win classes for the Mac. You can therefore, load a proxy 'stub holder' that manages the function calling which in turn loads the appropiate classes to handle the details. This is just a basic and simple example, but can be used quite efficiently for 'extending' a class without having to create several 'subclasses' in memory. I use this approach in my new development.
You're ID on a double way List works very well for object managment however. One thing to look at on that, however, is the expected size of the information to be stored. At one point, it would be better to convert the double list into a SetMap. But only if the content grows to be very large in number and is searched very frequently. For instance, I put my Living (NPC, Player Combined) and Items objects in a SetMap, but everything else in a double list.
For the most part on reducing memory, Java does that for you, as long as proper procedures are stuck too and all references to the object are properly removed. There is, however, no garuantee when the garbage collection will commense.
4) Some others I have found recently on SourceForge that may be of interest are EQMU (A EQ Emulator) and RunUO (an Ultima Online Emulator). RunUO is supposedly in mature status, though I have not used it.
Also... I'll show you the diagrams I used for my new development and you can see how closely your's resembles it:
System Diagram:
Controller (Handles Login, Messaging)
|
________|____________________
| | | |
World I World II World III I/O
Server Server Server Server
(Handles Saving and Loading of Files)
World Server Class Diagram:
Server (Singleton. Stores Engines)
|
Engine
___________________|________________________
| | | |
Map MudObjects Learnables Trackers/Managers
| | ___|_____ |
Room | Skills Spells Commands, Battles, Timer, Skills/Spells, Statuses, Items
________|_____
| | |
Item Props Living
| | |
Key -| Door -| Player
Container -| Sign -| Mob
Armor -| Portal -| Merchant
Weapon -| Decoration-|
Perishable -| Tree -|
Writing/ -| Wall -|
Readable -|
Jewel -|
Trap -|
Junk -|
Coins -|
Quest_Item-|
That is a very simple diagram layout of the system, there is much more involved with "polymorphing", "state", and "bridging" that is shown merely as "inheritance" in the diagrams. And even then, I had to leave out a lot of classes due to space layout problems within this textarea box. Hopefully, it will help you out some in the designing of your game.
Lone Wolf
Hmm .. that sounds interesting. I am doing that stuff a little different:
1) The ObjectManager must know all game intern objects with it's id and the simplest way to do this was a hashmap for me. So I always put objects there with the id as key.
2) The double-linked list is only used to take care, what objects wasn't used for the longest time.
(So whenever accessing the object through the ObjectManager, the object will be taken from the list and will be put on the end.)
In the moment, I am only planing to use ONE Server. I don't see a need to use multiple server in the moment. Of course, the IO Stuff could be seperated, but that would slow down everything!
(Changed Objects must be written to the IO Server immediately and every time, the object must be loaded again, because some other instance could have changed something e.t.c.! This needs more time, than it is ok for me.
I am thinking of splitting the game into multiple parts (later). But then objects will be part of One server and others are unable to use the object. That would be ok for me ... (I hope, you understand, what I mean!) Or when we need AI routines, that needs much CPU: other computers could do that ... But that isn't needed until now.
Objectoriented stuff:
I think I am doing it the same way - only my structure varies is a little:
- All Objects are SavedObjects. Saved Objects are Objects, that are handled by the ObjectManager (and reside in obj.jadv.*).
- JAdvObject - These are Objects, that can be used in the game. These Objects can contain other objects and will be inside another Object.
And it has a "masterParent" - The name ist not very good - "controller" would be better. (This is a JAdvObject, that controls the object. If the object is in the inventory of the player, the player is the controller. If it is inside a Location, the level is the controller.) If something is changed, the controller is informed. (e.g. the object disappears out of the Level: All Livings, that could see the object should be informed!).
And there are a lot of other Classes, e.g. Level, Location, Living, Player, NPC, ...
Maybe a lot of things should be changed. So I need to build some more interfaces. (Controller could be such an interface)
With kind regards,
Konrad
This is an example of how I did some bridging within the Living Class. A Mob and Player are very close to each other. The only main difference is that one is user controlled and may have a few different calculations than the other.
With this in mind, I did not create a seperate class for Player and Mob and then subclass those to handle options within them. Instead I decided what parts of their coding would be different, and estracted that out of the common code into their own class. This left me with one main controller class - Living and several small 'service' classes that have nothing in common.
This is the class listing:
Class Living extends MudObject implements Location
Merchant merchant
Learned learned
Attributes attributes
Operations operations
public int gold;
int groupID;
int respawnLength;
long timeOfDeath;
Point bind;
Point range;
boolean isMob;
boolean isExecutingLearned;
boolean isInBattle;
boolean isSitting;
boolean isStunned;
boolean isSilenced;
boolean isSleeping;
boolean noManaUseage;
boolean allowKill;
boolean allowSummon;
int movementType;
As you can tell I have seperated out the parts of the code that would have forced me to 'subclass' the Living Class and kept the common ground. Since in my design Players as well as Mobs may be Merchants but do not 'have' to be merchants. I made two types of Merchant classes and the merchant class to be used is bound to the living object at runtime. If the living object is not a merchant, then the link retains the null setting. The same for the Learned, Operations, and Attribute holders. Each of these will load the classes that are needed for that object since the coding in them are handled differently.
To better understand this I will show the layout for the different types of Merchants:
Merchant
|
__________|__________
| | |
Vendor Healer Trainer
In this setup, there are three different types of a Merchant that a Living may be. A Vendor to sell goods, A healer to sell heals, resurrections, cures, etc, and a Trainer to sell Skills. If I had not used a bridge approach, then I would have had to create atleast 4 subclasses of mob to handle this for mobs alone. However, I wish to allow the Player to use AI that will allow their character to provide the following services as though they were an NPC (when in away mode, or etc) and therefore to allow the player to have these I would have had to subclass the player class 4 times as well. That would have given me 8 subclasses of living! Next, think of what I would have when I wanted to allow a Mob to be both a Vendor and a Healer or even Vendor, Healer, and Trainer all three. That would mean that I would have had to create a subclass for each possible combination. EGads! That's a lot of classes. So what I did was create a merchant class which my three types inherited from and then using the Merchant declaration as a bridge I linked them to the Living Class. If I wish in the future for a Living to be able to have multiple merchant abilities all I simply need to do is use an array declartion for the merchant and I have the ability to combine any combination of Merchant I wish at runtime. Also, in better lighting.. the Merchant class is really nothing more than an interface and can be thought of that except that I wanted to take out common variable instances from the three classes and keep them in just one class.. the Merchant. If I had not cared about this, then making the Merchant an interface rather than a Class would have been sufficient.
Hopefully this explained more than it confused.
Lone Wolf
1) I originally had everything in a hasktable, but after doing some benchmarks I found that unless I had over 5000 objects being handled by the hashtable, the overhead outweight the benefits and were slower all around to process than the lists. Specially for large amounts of additions and transitioning. For living, searching was more important
2) Why do you keep track of which object isn't used for the longest time? Unless it is for caching purposes?
Aye, Dusk is a one server game. I just found java to be a bit slow in handling too many rooms which monster calculations, so I made my version able to distribute the load if needed. One server works well for a start, however. As for IO. I try to do the least amount of IO operations possible. In my opinion, it is WAY too slow. Everything I do is in RAM and cached memory. My IO is only for saving states at intervenal times or force loading. I made an IO server to handle the ability to harnesh my RAID drives on one server for all my worlds. Still, seperate IO server is definitely not needed. And I agree with having a seperate AI server. That is in the my architecture as well. Mostly, I think it all depends on what the goal is that the system is perceived to handle. I would suggest however, that if you plan on being able to handle distributed servers, that you put the code in at the front instead of after. Trust me when I say it says a load of time and headaches.
Aye other than the savedObjects thing which if I think may be refered to IO objects, that is how I have thought best for object handling. The trickiest question I found to this however was finding the best way in "notifying" the 'Living' of the changes. I found I made myself a lot of catch 22's in handling that. I ended up with what I think is the simplest method, though I may be wrong. All my "item" objects and "living change" notifications are handled at a room level. Meaning that individual rooms handle their notifications for objects that reside in them. Status, Spells affects and skill execution notifications are handled within an affect controller that handles only statuses, spells, and skills. All player commands are handled via a command controller, and all monster movents and respawns are handled within a monster controller also userd as the game timer. Originally I had lists within each living object to handle these, and found it a pain in notifying everything that needed notifying in a quick amount of time and removing/adding objects without deadlocks. The controllers I developed keep the deadlocks from happening, and the notification time seems to be acceptable so far. All the controllers are seperate threads running against a batch of qued objects. The controllers themselves are governed by the World Engine.
I wouldn't make a controller an interface. Atleast not in the sense that I think of controllers. I was not able to find too many situations where I need an interface within my system other than where I needed mutiple independant classes having the same methods. Ie. A physical object (item, prop, living) and non physical object (event) needing to both be able to be tied to a specific location or linkable within the map and not being related in any other fashion.
I would be interested in seeing how you have planned out your system. If you will, post a technical documentation of the architecture to the files areas. If you already have one out there, I have failed to be able to find it.
Lone Wolf
BTW: I apologize for those diagrams. They were spaced out properly in the textarea box but the html conversion removed all the spacings.
1) Hmm .... then I should create a better way to store the objects. Maybe it would be fine to create a balanced search tree... Isn't there already such a class in Java? It would be hard to write it on my own ... my studies of computer science are over for some days :) I know, that these trees are possible, but I don't know, how to organize them exactly ....
2) I need a decision, which object I had to drop out of memory when memory gets short. So I wanted to keep track of the usage of the objects.
(And it is a real fast operation, because only a few pointer must be reset).
I had some technical descriptions, but I removed them :(
I will try to create some more technical description in the next days. (That could be found in the Web! Simply go to the server manual from time to time or - when you have cvs of the game - look at the doc directory!)
I dislike the idea of havaing to many threads. And I fear, that one bad object could block everything!
My way to work is event oriented. There are only a few threads:
- a IOThread, that handles the IO stuff (new java.nio channels!)
- a EventThread, This thread gets an event from an eventqueue and handles it. When done, it gets the next event ...
- EventMaster, Normaly it would only hold the eventqueue, but it is also a thread: It starts the EventThread if needed and checks the EventThread. If an EventThread is blocked, the EVent will be marked as bad, the EventThread is "stopped" (Only marked to stop!) and a new EventThread is created. (That way, we could handle even bad objects. If the heartBeat of an event didn't finish itself, the heartbeat of the object will be stopped)
- TimerTask - The Time handles short and long time timers (e.g. heartbeats, Resets, ...). If a timer is triggert, only an event will be placed inside the eventqueue.
With this setup, I will be sure, that there are no problems with multiple processes. All GameObjects are normaly only accessed through the EventThread. (There could be multiple EventThreads at once if the game becomes too slow :( But I thought, that this isn't a real problem).
And the events are handled almost the same as at your server. But not only rooms are "controller". All objects, that contain other objects and that want to do something ith them, could be a "controller".
So there are levels:
- Needed to calculated, what a player can see
- Needed for stuff like "saying" "calling" ...
Livings:
- They want information about the objects, it is carrying
- They want to be notified, if something is changing
Maybe there will be other possibilities, too. But in the moment, that is all.
And your diagrams: I received your posts as eMails, too. They were really good in the eMails, because the space had the right size there ...
1) There are tree classes already in Java: TreeSet and TreeMap.
2) Figured it had to be for caching purposes. I used that on the client side for image and sound handling, but for the server I have everything loaded at one time, and it remains in memory. I recycle what is there with only a few additions when truly needed. This method is also one reason why I decided to use the distributed technique on my servers. I had a limit of 500x500 rooms max on my servers using this approach.
Hehehe.."one bad object block everything" is exactly the reason why I made a seperate thread for each type of handling. If I had only one thread handling the objects... then if that object froze in its operations everything would die. This way, only part of the system dies and the controller will make sure that it resets properly. The way I broke operations up makes the system so that no two objects would have the same operations. For instance, instead of putting "can see", "targeting", "can attack" operations within the Living Class where "every Living objects" has to handle those operations, I put those operations within a tracker and therefore only 1 object handles the operations for multiple living objects. This keeps the living objects from clashing with each other. Of course the downside, is that if the tracker breaks, then all living objects will lose this functionality for the time it takes the controller to see that there is a problem and reseting the tracker. Of course, if I had kept the operations within the Living class and two living objects had conflicted then I had an even bigger problem depending on how I managed my living objects. 1) If my engine thread 'only' was responisble for control over the living objects then if two kiving objects conflicted it could cause the whole engine to fault. If I read your post right and you have levels as independant threads and they are used for controling the living objects, then those would freeze up and everything they control will halt as well. This basically can not be avoided. Something has to freeze and be reset. What I tried to do was limit what was effected to the smallest degree I could. So I broke up major functionalities of the game into seperate thread handlers. I found with duskRpg, that if a player had a conflict between a mob, that the engine would freeze up and everything came to a crashing halt. Even though the players were their own seperate threads, since the mob was handled only by the engine, it caused the engine to freeze. That's another reason I serious dislike IO being done on a world server as well. IO has the greatest potential for freezes, and to be honest, this may have been the greatest cause of freeze ups in the DuskRPG. I am sure there are many different ways to handle the problem, I am just letting you know how I dealt with it. Seperate server for IO and seperate controller threads to handle specific areas of the system that I deemed critical and prone to freeze due to catch 22's.
Lone Wolf
(What? Read the code for documentation?????? Hehehehe.... I wish I had the time.)
1) TreeSet and TreeMap: Are the trees balanced? The tree, that I want to use, should be a balanced tree. I think that this is a "must have"
2) "bad object is blocking everything":
I think, that having to many threads will bring a really bad performance ... I simply know the problems with IO Threads (The old style with blocking sockets, where each Socket will have it's own thread ...)
And my experience with multiple threads are really bad. When using JBoss, I got some bad exceptions because of JBoss detecting deadlocks :(
Ok - that problem could be solved with a better implementation, but I see some major problems.
In such a game are some objects, that will be changed / queried very often. Imagine Player in a fight. There will be some kind of heartbeat, that restores Hitpoints, the fight will do some calculation, maybe special effects (e.g. Spells) must be taken care of, the computer player will check the opponent, because maybe it want to flee, e.t.c.! There are multiple Threads that all need some information about one object. And maybe all want to change one thing in an object!
Synchronized objects could be nice, but that slow downs the game (that was my experience).
3) "Read the code for documentation"
NOOOO ... There will be two parts:
a) JavaDoc - These will describe packages and classes
b) Website (or ./doc/ directory) will get manuals about server and client.
With kind regards,
Konrad
I found out, that these Trees are balanced. In the javadoc is only written, that these trees have "Red-Black Tree" implementations and I don't know that type of trees (or I know other names).
I searched in google and found, that these red-black trees are balanced trees. So I had a replaement for my hashmap now :)