Tuesday, April 24, 2012

Can jQuery help me?

I am currently checking out jQuery to see what the hype is all about and if I can use it to make the client work better.

Features I could use:
  • Selectors - I already thought about an own alias function for the annoyingly verbose document.getElementById.
  • Position for centering divs properly. Also maybe for some other things.
  • Tabs - I already have an implementation of a tabbed container for the chat, but maybe I could make it better with JQuery.
  • Drag & Drop - For inventory handling and putting spells into the quick bar
  • Sortable for inventory handling (maybe)
  • Resizable GUI windows

Friday, April 20, 2012

Game system software architecture

Before I start with Milestone 6, which is about the implementation of a game system, I decided to do some refactoring first.

To allow quick and easy changes to my game system, all logic related to it should be concentrated at one place: A GameSystem class which implements all the game rules. All the provisoric existing logic needs to be removed and replaced with calls to this class. The game system does of course need the system-specific stats of all the participants like mobs and players. Storing this data in the existing objects would be a violation of the principle to isolate the game system. So every participant now gets a gameSystemDelegate object with all the game system specific data which is received from the GameSystem during construction and is passed to every call to GameSystem instead of the original object.

To allow easy replacement of the game system, I decided to follow the principle of dependency injection and the strategy pattern. GameSystem as well as the delegates GameSystemPlayer and GameSystemMob are only interfaces. The implementing class Wizardwar is only referenced in the main class, where it is used for a global GameSystem object referenced everywhere else. The implementations of the delegates, WizardwarPlayer and WizardwarMob, are only referenced in Wizardwar.

That way I could create an entirely new game system, and the only place in the engine code where I need to make a change is the line gameSystem = new Wizardwar() in the Main class.

About the wizardwar package itself: I intend the delegates to be "dumb" data holders with all members set to public. All game logic should be contained in the Wizardwar class.

Thursday, April 19, 2012

Fringe tiles work - Milestone 5 finished

The client can now display maps with multiple map layers, including a fringe layer where the draw order of the tiles is combined with the sprites. I implemented that by converting all non-null tiles on a layer named "Fringe" to map objects (or rather something similar which implements the same interface). 

Client, server and map editor now work the way I intend. Now I theoretically got all the tools I need to start world building. All that is left are tiles and a world building plan.

Milestone 5 is hereby finished.

Tuesday, April 17, 2012

Blocking works

Reading the block map property from each tile works now. Entities with different ways of movement is untested, but should work.

The way of defining the walk properties of each tile of the tileset is a bit cumbersome: you add a tile property "walk" and as a value a hexadecimal value according to the table in my previous post. When you don't set a walk property for a tile, the default value 0xd (walkable for everything but swimmers) is used. This has two possible pitfalls:
  1. the hex values are hard to remember, so you can easily select a wrong one
  2. there is no visual indication which tile has which walkability
It also has the drawback that it isn't possible to have tiles which are only partially blocked, which means that I waste the most powerful feature of my route finding engine. Maybe I could do it like we did at Mana and use a special invisible map layer for the blocking, just with the difference that the graphics of the tiles you put there matter: different colors of pixels mean different walkabilities.

Warp loading works

Loading warps from the map files is also working.

Monster population should wait until milestone 6.

Still left are movement blocking and fringe objects.

Then I will have all basic technical requirements for building a game world and I can call milestone 5 finished.

Tileset loading

The client can now work with tilesets and doesn't require a separate image file for every tile type.

I did a small modification at the server to remove the relative paths from the tilesets in the JSON code provided by Tiled and leave only the filename. That way I don't have to worry about where to save the map files before copying them to the server. The drawback is that I can't organize my tilesets in directories, but I don't believe that I will have so many tilesets that this becomes a problem.

Sunday, April 15, 2012

Blocking tiles

tilewalker (1)swimmer (2)flyer (4)magic (8)examples
shallow water
EXdeep water

normal ground
CXXabyss; low fence or other chest-high obstacle
Xindoor, under overhang
AXXriver under bridge
8XXXgrate, prison bars
Xcircle of protection on shallow water
Xcircle of protection on deep water
Xcircle of protection on normal ground 
Xtree, high stone, other man-high obstacle

The column "magic" applies to spells which need a line-of-sight to be cast as well as to "ghost" type mobs / players. A being can have multiple forms of movement, like a harpy which can both walk and fly. These mobs are only blocked when all of their ways of movement are blocked. Or in computer terms:
if ((tile_bitfield & move_bitfield) == 0) tile=BLOCKED;

Having scenarios where players and enemies have different areas to walk on as well as shared areas where both can walk, could lead to some interesting gameplay situations.

I could also imagine some spells which turn a player into a fish, bird or ghost. This would mean that they can't use equipment anymore, but it would allow them some interesting new leveling strategies as well as open up some new areas. There could also be the ability to polymorph a player involuntarily when he is in an area which allows both types of movement. This could be used as a strategy in PvP. Or it could be the solution to some puzzles before the player acquired said spells.

One puzzle I have in mind is a river with a broken bridge. The river is populated by mermaid mobs which sometimes attack the players with a spell which turns them into a fish. To cross the river, the players need to walk into shallow water, provoke the mermaids to hit them with said spell, swim across the river into shallow water on the other side, and wait for the spell to wear off.

An advanced form of magic could allow players to walk on water or fly without sacrificing their ability to walk on land or have equipment. But this should be a lot more expensive for the player.

Reading maps from Tiled successful

I successfully loaded  a JSON map created with Tiled on the server, passed it to the client, and displayed it there. I also changed the way my randomly generated maps are represented in JSON to match the Tiled format.

What's still missing is the conversion from the numbers Tiled assigns to each tile type to the numbers the client uses to assign images. I had to edit the map file manually to get them to match. Creating the walk map doesn't work either for some reason, but I need to change that anyway, because I want the blocking property to be a property of each tile.

Features of Tiled I still need to implement:
  • Tilesets (will take care of the id mapping problem)
  • Tile properties (for calculating the walkability)
  • Objects for warp areas and spawn areas (and later script triggers)
  • Multiple layers (not yet required, but nice to have in the future)

Gonna use Tiled

I decided to use Tiled for map editing. Reasons:

  1. Very mature map editor
  2. Can save to JSON files
  3. It's open source, so I can fix bugs myself
  4. The idea to do mapping on the production server sounds dangerous 
  5. I know the developer 

    Doing mapping with an external editor

    1. Copy the map file to your workstation.
    2. Load the map with the editor.
    3. Copy your changed  map onto the server with a temporary name.
    4. Warp to the temporary map name. Because there is no instance with that name yet, the server will create one based on the file.
    5. Test the map.
    6. When there are errors, go back to your map editor, replace the temporary map file and use the reset_instance command to reload the map instance.
    7. When the map is OK, replace the original file and delete the temporary one.
    8. Use reset_instance on the original map to activate the changes. Alternatively, restart the server.
    An external version control system like git is needed to care about revisioning on the server.

    Admin commands for mapping with the client

    This concept applies to the option of integrating the map editor into the client. I haven't decided this yet.

    Storing of maps: All map layouts are stored in the database. The database holds all past versions of each map.  The most recent one is the one which is used. 

    Map editing: The mapper can change the layout of the current map on the client-side, but the server won't respect these before the changes are sent to the server using the map save command.


    Local map version: The map on the client side. Identical to the current map version until the mapper starts mapping.
    map version: A version of the map stored in the servers database for version control purposes
    active map version: The latest non-wip version of a map. This version is used for gameplay

    Mapping commands:

    map create [name] [l] [r] [default tile]* creates a new map. The first and active version has the given size and is filled entirely with the default tile.
    map versions request a list of all past versions of the current map with timestamp, author and if it is active or not
    map save [data] creates a new version of the current map which is identical to the local map version. The new version is not active yet.
    map activate* the latest version becomes the active version.
    map load [time] loads a version as local version which doesn't necessarily needs to be the active version. Time can be omitted to load the latest version.
    map copy [name_to]* creates a new map name_to. The first and active version of this map is identical to the local version of the current map.
    map overwrite [name_to]* creates a new version of map name_to which is identical to the local version of the current map. The new version becomes the active version.

    *It should be possible to limit the permissions for create, activate, copy and overwrite commands to specific namespaces to prevent mappers from creating a mess of garbage maps.

    Workflow without QA:
    1. The mapper teleports to the map which needs to be changed
    2. The mapper does the changes 
    3. The mapper uses map save to save the changes
    4. The mapper uses map activate to activate the changes
    By restricting the activate and overwrite command to selected people a QA can be enforced. Workflow with QA:
    1. The mapper teleports to the map which needs to be changed
    2. The mapper does the changes
    3. The mapper uses map copy to create an active copy
    4. The QA teleports to the active copy and tests it
    5. The QA uses map overwrite to  replace the production map
    To restore a map to an earlier state:

    1. The mapper teleports to the map which needs to be changed
    2. The mapper uses map load to restore the version
    3. The mapper uses map save to create a new version identical to the past version
    4. The mapper uses map activate to re-activate the past version

    Saturday, April 14, 2012

    Map editing

    So far my maps were randomly generated using three different tiles. Procedural generation of maps isn't that bad per-se. Some great indie games like Minecraft, Recettear or Dwarf Fortress generate all their maps that way. The result is a versatile game environment with great replay value.

    But still, when you want to do story telling and want to be a creative game designer, you need some way to create locations and scenarios by hand. This means I need a map editor. My requirements are:

    1. Creating and editing maps by placing tiles
    2. Creating warp connections to other maps
    3. Defining monster population
    4. (later) placing NPCs and scripted events

    So what options do I have?


    1. Writing map definitions in a text editor in JSON format

    • I don't have to program any external tools

    • No WYSIWYG
    • Very tedious
    • Very hard to troubleshoot
    Maybe I will do that as a stop-gap measure until I have a more viable tool.


    2. Use Tiled

    • A very mature and powerful map editing application
    •  I would either have to write my own plugin for Tiled which saves to the format I need or I need an XML-parser. Tiled can save JSON files, which have a schema which is quite easy for me to parse.
    • Tiled doesn't work with my overlapping tiles. It does work with them, but you have to define the amount of overlapping yourself
    Although using Tiled instead of reinventing the wheel would save a lot of work,  it is still not perfectly suited for my needs. Getting tiled and my engine to work together will require some work and maybe will even mean that I need to say goodbye to some features.

    3. Create my own map editor as a stand-alone application

    • An application perfectly tailored for my needs
    • A lot of work
    Creating an own map editor as a GUI application - no matter what framework I will use to do so - will be just as much work as creating the client.


    4. Put map editing capabilities into the client

    • Perfect WYSIWYG 
    • Easy way to get the community involved in content creation
    • Still a lot of work, although I can rely on the map rendering
    • Puts more code in the client than I would like to have
    • Air-tight permission management required
    Using the client as a base would save a lot of work over creating a new application from scratch. But integrating the map editor would add a lot of code which would be downloaded by the average player although they will never use it. To avoid this problem I could create the map editing component as a user javascript which runs locally on my machine (or that of the mappers).

    Roadmap updated

    While I ported the client from Metro to HTML5 I  lost track of my roadmap. I implemented some features which were planned for much later milestones (like some steps into the direction of inventory and item management) while forgetting about things which are much more important in the intermediate future. Time to get my priorities straight again.

    Milestone 5 (content):
    • Map editing
    • Map management infrastructure
    • Infrastructure for reading content from external files (JSON?)
    Milestone 6 (growth):
    • Flexible GUI infrastructure
    • Character system
    • EXP gain and leveling
    • Combat mechanics
    • Mob AI
    Milestone 7 (wealth):
    • Items and Inventory
    • Player trading
    • Shops
    Milestone 8 (adventuring):
    • NPC interaction
    • Scripting
    Milestone 9 (security):
    • Permission management
    • Database logging of
      • Logins
      • Administrative actions
      • Usage statistics
    • Logins
    • Brute force protection
     Milestone 10 (eye candy)
    • Animated sprites
    • Animated tiles
    • Particle effects


    This evening I added the skill infrastructure.

    A quickslot bar (usable by click or number keys) is used to switch the mouse cursor to cast mode, and a click on an enemy is used to begin the cast. The server informs all players that a cast happens and how long it will take. The clients show the progress bar of the cast, taking the latency into account.

    When the casting time is over, the server does damage to the victim and sends a message to the clients informing them that the action was performed.

    The basic feel of the combat mechanics is already there. But there is still a long way to go. The skill palette is fixed on the server, and there is no attribute system yet.

    Friday, April 13, 2012

    Prevention of duplicate character and account names

    Today I tweaked the account and character creation. The database now refuses duplicate names using an unique index. The server checks this and also does some other plausibility checks (password complexity, name length, no funny characters in the name) and sends either a negative or a positive response to the client. The client reacts to these by either displaying an error or navigating to the next screen.

    I also added a placeholder privacy policy and terms of use to the registration.

    Thursday, April 5, 2012

    Added password encryption

    The server now uses salting and SHA-1 hashing for the passwords. Just to be sure that no sensitive data can be salvaged should my database ever get hacked. In the USA some website was fined $250.000 for losing plain-text passwords. Although I am living in a less insane jurisdiction than the US, it's better to be safe than sorry. Also it's a matter of responsibility.

    The salt is the string representation of a randomly generated GUID, so it's very unlikely that someone has a rainbow table for it.

    Porting the client part 4: Account and character creation

    I redid the missing parts of the login sequence. Account creation and character creation work now. The usability has still some problems though, because the server doesn't report success or failure. That's mostly because the server doesn't even know any failure conditions - it doesn't check anything for plausibility and it is possible to create multiple accounts and characters with the same names. Securing that should be my next priority. And while I am on it I should also prevent accounts from being logged in twice.