I added three new script commands.
/players lists all online players with their locations.
/maps lists all active map instances with their player count and mob count.
So far, so boring. But the really powerful command I added is the /shell command. It allows to execute Javascript code on the server. So it can do virtually anything. This powerful tool will allow me to analyze and fix a lot of problems on the running server on-the-fly as well as do complex events. It is also extremely dangerous in the wrong hands and I see no way to add permission-based restrictions to it, so I definitely need to shield this command from unathorized use. I will also not use the existence of this command to refrain from adding more commands which do things which could theoretically also be done with /shell, so I won't be tempted to give the /shell command to people I don't trust 110%.
Wednesday, August 29, 2012
Saturday, August 25, 2012
Multiple logins no longer possible
The shopping task is still daunting me, so I did something else for now. Until now it was possible to log in multiple times with the same account and even multiple times with the same character. Now I finally prevented multiple logins per account. In order to do this I added a static OnlineManager class which keeps hash-maps of all logged-in accounts and characters with their names as keys. This will also be useful for the implementation of /commands and scripts which affect characters by name.
Friday, August 24, 2012
How to do shopping
The shopping window allows the player to both buy and sell items. This is an important dialog window. Making errors while buying or selling could cause some serious damage to the player. But on the other hand, players will use this dialog quite often for annoying but unavoidable routine tasks like getting rid of vendor trash or stocking up on stock consumables.
So how should I design this from a usability standpoint?
While this is pretty intuitive and places the bought items right where the player wants them, it makes it hard to buy whole stacks or sell partial stacks (maybe ask it with a popup window?). It's also hard to communicate how much money the player will make with selling an item.
This especially makes it more comfortable to replace equipment with more expensive one.
So how should I design this from a usability standpoint?
The one-click solution
I put a "buy" button and a "quantity" input field (default: 1) next to each item in the vendor menu. While the menu is open, a "sell" button with a "quantity"(default: current amount) is added to the item detail area.The drag&drop solution
Items are bought by dragging them from the vendor window to the inventory window. Items are sold by dragging them the other way.While this is pretty intuitive and places the bought items right where the player wants them, it makes it hard to buy whole stacks or sell partial stacks (maybe ask it with a popup window?). It's also hard to communicate how much money the player will make with selling an item.
The bargain solution
This would mostly use a dialog I plan to use for player/player trading. The player drags the items they want to sell or buy from their inventory and the vendors inventory into a box. The sum is calculated on both sides and the difference is listed below it. When the difference isn't larger than the money the player got, the buy button becomes active.This especially makes it more comfortable to replace equipment with more expensive one.
The Tibia solution
No, seriously. That's ridiculous for both usability and immersion. Whoever thought that using a chat parser to do NPC trading in a MMORPG would be a good idea, was either lazy, stupid or both.Thursday, August 23, 2012
Money
I added money. It is saved in the database, communicated and displayed in the clients item window. I even added a /command to change it. There is just nothing to do with it yet. Adding shopping will be my big challenge for the weekend.
Preventing data loss due to server bugs
When handling database entities like accounts or characters I used to parse the BSON object, build the Java object from it, and then discard the BSON object except for the _id. When saving the entity, I used to build an entirely new BSON object with the same _id and the data of the Java object and saved it to MongoDB. The drawback of that approach was that any information in the database which was not parsed, stored and written back by the Java object was lost on updates.
To make it less likely to lose data this way, I decided to carry the original BSON object around in the Java object and overwrite all known values with the current ones on saving. That way any data the server does not read is retained.
This does, however, not totally prevent data loss. When a bug causes the server to suddenly be unable to read a value but it is still able to write it, it will replace it with a placeholder value. It also doesn't prevent data loss when the server screws up a dataset during gameplay.
In order to do some damage control in such a case, I could save every object not just to the main collection, but also to a separate backup collection with a non-unique key consisting of name and timestamp. This would give me the opportunity to roll-back individual characters to a previous point in time, should the need arise.
To make it less likely to lose data this way, I decided to carry the original BSON object around in the Java object and overwrite all known values with the current ones on saving. That way any data the server does not read is retained.
This does, however, not totally prevent data loss. When a bug causes the server to suddenly be unable to read a value but it is still able to write it, it will replace it with a placeholder value. It also doesn't prevent data loss when the server screws up a dataset during gameplay.
In order to do some damage control in such a case, I could save every object not just to the main collection, but also to a separate backup collection with a non-unique key consisting of name and timestamp. This would give me the opportunity to roll-back individual characters to a previous point in time, should the need arise.
Wednesday, August 22, 2012
Item Window Enhanced
- Quantity is shown in grid and in detail area
- Total weight of stacks is calculated in detail area
- Selected item is highlighted
- Use button (only for items which can be used)
More about scripting
I am thinking about how to design a good scripting API. Currently, the PlayerCharacter object and the Item object are passed to item use scripts. Unfortunately the PlayerCharacter object can't do much, because most is done by the controllers owned by MapInstance. I can access the MapInstance through the getMapInstance method of the PlayerCharacter, but the map instance doesn't expose the controllers. And for good reason: the main way of communicating with them are messages.
Well. I could pass the message dispatcher to the scripts, but crafting messages is a tad too complex for a scripting API.
So what could I do?
I could add some methods to MapInstance specifically for scripting. I already did that for monster spawning. But that wouldn't make sense for things which have nothing to do with the current MapInstance. Teleporting a player to another map, for example.
Maybe another global object is in order which has static methods specifically for providing helper methods for scripts.
Well. I could pass the message dispatcher to the scripts, but crafting messages is a tad too complex for a scripting API.
So what could I do?
I could add some methods to MapInstance specifically for scripting. I already did that for monster spawning. But that wouldn't make sense for things which have nothing to do with the current MapInstance. Teleporting a player to another map, for example.
Maybe another global object is in order which has static methods specifically for providing helper methods for scripts.
Tuesday, August 14, 2012
Item Use Scripts
I thought adding scripting support would be really complicated, so I postponed it until the NPC milestone. But today I read how ridiculously easy it is to add scripting support to a java program.
So I decided to add script-controlled item use now. I decided to use Javascript as scripting language on the server. Not just because it is supported out-of-the-box by Java but also because I want to avoid to add a third language to the project. The client uses JS, the database uses JS, content files are almost JS (JSON, to be precise), so why not use JS for content scripting?
Doing that was nothing compared to the pain we have on Manasource with the LUA scripting system for Manaserv. There we have to write a wrapper function for every single function we want to expose to the scripting engine. The Java scripting system, on the other hand, can pass any Java objects to a script and then lets the script call any public methods on them without requiring any boilerplate code whatsoever. Just passing the PlayerCharacter object as "user" to the item use scripts allows me to do all sort of interesting stuff.
Sunday, August 12, 2012
Inventory Window with item information
There is now a section with more information about items to the right of the inventory grid. The name and the icon filename are transfered with the inventory contents, but the description and weight are requested from the server as soon as the user clicks on an icon.
The purple book with the "W" on it in the lower right corner is a link to an article in the "Wikinomicon" - a wiki I am going to create where players can add their own information about items and other entities in the world.
Wednesday, August 8, 2012
Inventory window
I created the item window. You can move items with drag&drop (thanks, jQuery UI) and the server saves the positioning.
I also added the /item debug command to create item stacks.
Still missing:
- Showing item amounts
- Item information window
- Using items / dragging usable items to hotkey bar
- Splitting item stacks
- Equipment
- Make item window resizable (both visual size and size of grid)
Subscribe to:
Posts (Atom)