GameDesign: Difference between revisions

Content deleted Content added
imported>StephenIerodiaconou
No edit summary
imported>Blacklads
Undo revision 11673 by Ufizavipupu (Talk)
 
(89 intermediate revisions by 6 users not shown)
Line 1:
{{Navigation for Marauroa Top|Internals}}
{{Navigation for Marauroa Developers}}
 
 
= Basic idea behind GameManager =
The idea behind the Game Manager is to handle all the "business logic". This Manager decides how to reply to each individual message.
Line 17 ⟶ 21:
 
So let's define the reply to each message. First, let's clarify that the best way of modelling this system is using finite automates, (a finite state machine) where, based on the input, we change the state we are currently in and produce an output.
== Login stage ==
<b>NOTE</b>: This stage has been split in 3 to allow proper secure login.
<b>NOTE</b>: Explain here how secure login works.
 
<pre>
Line 51 ⟶ 58:
 
Postcondition: The state MUST be NULL or STATE_LOGIN_COMPLETE
and a we have created a PlayerEntry for this player with ana unique correct clientid.
 
</pre>
 
== Choose character stage ==
<pre>
Process C2S ChooseCharacter ( STATE_LOGIN_COMPLETE )
Line 76 ⟶ 85:
 
</pre>
 
== Logout stage ==
<pre>
 
Line 98 ⟶ 109:
 
</pre>
 
== Perception confirmation stage ==
<pre>
 
Line 109 ⟶ 122:
 
</pre>
 
== Transfer confirmation stage ==
<pre>
 
Line 124 ⟶ 139:
Postcondition: The state is STATE_LOGIN_BEGIN and the content waiting for player is clear.
</pre>
 
= Basic idea behind Database storage =
==Database Tables and Relationships ==
 
The database table relationship schema is:
<pre>
Table PLAYER
{
PK(username)
password
}
 
Table CHARACTERS
{
PK(character)
content
}
 
Table LOGIN_EVENT
{
PK(id)
address
timedate
result
}
 
Table STATISTICS
(
PK(timedate)
 
bytes_send
bytes_recv
 
players_login
players_logout
players_timeout
players_online
)
 
Table RPOBJECT
(
PK(id)
slot_id
)
 
Table RPATTRIBUTE
(
PK(object_id)
PK(name)
value
)
 
Table RPSLOT
(
object_id
name
PK(slot_id)
)
</pre>
 
Relationships:
<pre>
Relationship PLAYER_CHARACTERS
{
PK(player_username)
PK(characters_character)
}
 
Relationship PLAYER_LOGIN_EVENT
{
PK(player_username)
PK(login_event_id)
}
</pre>
Translate this to SQL easily and you have the SQL schema of Marauroa
 
 
== JDBC Database HOWTO==
JDBC technology is an API that lets you access virtually any tabular data source from the Java programming language. It provides cross-DBMS connectivity to a wide range of SQL databases, and now, with the new JDBC API, it also provides access to other tabular data sources, such as spreadsheets or flat files.
 
JDBCPlayerDatabase is anyway not database independent; on the Player table we are using AUTOINCREMENT that is a unique keyword of MySQL that is not part of the SQL standard.
 
You need to download MySQL Connector/J in order to get it to run. <br>
http://www.mysql.com/downloads/api-jdbc-stable.html
 
To configure Marauroa to work with a JDBC source we need to modify the configuration of the JDBC Connection.
 
So open the configuration file '''marauroad.ini''' ''(or whatever you choose to name it)'' and edit the next fields
<pre>
marauroa_DATABASE=JDBCPlayerDatabase
 
jdbc_class=com.mysql.jdbc.Driver
jdbc_url=jdbc:mysql://localhost/marauroa
jdbc_user=marauroa_dbuser
jdbc_pwd=marauroa_dbpwd
</pre>
 
* ''jdbc_class'': This field tells the engine what Driver to use for database access. Please refer to your software manual to see the multiple options.
* ''jdbc_url'': This points to the type and source of the information, for MySQL the string must be as follows:
** '''jdbc:mysql://ip:database_name/'''
* ''jdbc_user'': This is the username for the database
* ''jdbc_pwd'': This is the password for that username in the database.
 
Now, simply save the changes and your configuration file is ready.
 
Before using the application with the database, you need to create the database itself. So, with MySQL just run MySQL and enter:
<pre>
create database marauroa;
grant all on marauroa.* to marauroa_dbuser@localhost identified by 'marauroa_dbpwd';
</pre>
 
The rest of code is handled by the server itself, and it will create the tables if they don't exist.
 
=PlayerContainer Explained=
Line 242 ⟶ 145:
It consists of a list of RuntimePlayerEntry objects and is heavily linked with the PlayerDatabase, so we can hide the complexity to GameManager. By making PlayerDatabase hidden by PlayerContainer we achieve the illusion that managing the runtime behavior we modify automatically the permanent one.
 
RuntimePlayerEntry is the structure that contains the information ofabout the player while it is online. <br>RuntimePlayerEntry contains:
* <i>clientid</i><br>
Clientid is the field in charge ofthat indexingindexes players in the server. See the documentdocumentation about clientid generation to understand what they are and how they are generated.
* <i>source</i><br>
Source is the IPv4 address of the client,. soThis thatis weused canto determine if the message is really coming from the client or another person trying to impersonate it.
* <i>timestamp</i><br>
Timestamp is used to determine if a client has timed out andin aswhich such,case it is only wasting resources on the server. As you may already know, UDP is not a delivery-guaranteed protocol, so we need to check ourselves for dead clients ourselves. Take careNote that itthis only indicates that the player timed out, and it doesn't apply any kind of measures overon them.
* <i>storedTimestamp</i><br>
storeTimestamp is used to determine when itthe wasplayer thewas last timestored thatin thisthe playerdatabase. wasWe storeddon't onstore database,each astime storingthe forplayer eachinfo changes as this changewould willobviously be very CPU time consuming. soInstead we cached itthe changes and store eachthem only every 5 minutes.
* <i>username</i><br>
Username is filled in at runtime with a Login event. soIf thatwe store the username here we are able to use the database from PlayerContainer, This waythus by knowing the clientid we can also now know the username without having to look to the actual database.
* <i>choosenCharacter</i><br>
choosenCharacter is filled in at runtime with a ChooseCharacter event. soIf thatwe store the information here we are able to use the database from PlayerContainer, Thisand wayhence by knowing the clientid we can also know the choosenCharacter without having to refer to the actual database.
* <i>state</i><br>
State is a number expressing the state in which the player is. There are four states:
**Have to login
**Login Complete
**Game begin
**Logout
When we create the entry it is by default Have to login. Once you have logged in correctly, we change state to Login Complete, and once you have chosen a Character we change it to game begin. The logout state is trivial :)
 
When we create the entity, by default, the state is <b>Have to login</b>. Once you have logged in correctly, the state changes to <b>Login Complete</b> and once the player has chosen a Character it changes to <b>game begin</b>. The logout state is pretty trivial :)
The main idea is that some operations are only allowed in one state, so we can more easily control it with the state property.
 
The idea is that some operations are only allowed in certain states, so the state property stores which state they are in to make validating actions easier. ( To read about Perceptions, [[RolePlayingDesign#Perceptions | click here]] )
 
*perception counter<br>
The Perception counter is used forto havingkeep aan incremental countercount of the perceptions send,sent so that the client can see if it gets out of sync.
*perception Previous RPObject<br>
Perception previous RPObject is the RPObject that was sent on the last perception,. soUsing this we can track * changes onto oura RPObject without disturbing the rest of the system.
*perception Out of Sync<br>
This flag indicates ifto the playerserver notifiedif usthe thatplayer ithas wasbecome out of sync,. soThis weallows canus reto re-sync it as soon as possible.
 
Hence, all we need to operate PlayerDatabase is a username and choosenCharacter. So using PlayerEntryContainer we can fully operate it.
 
As you can see all we need to operate PlayerDatabase is a username and choosenCharacter. So using PlayerEntryContainer we can fully operate it.
 
==ClientID generation==
Each client MUST have a session id to avoidprevent another player to impersonateimpersonating it. sessionid must be aof short or int size to make harderguessing forthe anID attackermuch to guess itharder.
 
To make it even more secure, clientids are generated randomly for each player with the only condition that two different players MUST have two different clientids.
 
To make it really fun, clientids are generated randomly for each player with the unique condition that two different players MUST have two different clientids.
Home
 
==Synchronization between Game and RP Managers==
Why bother with itthis? Well, imagine that a player logs out whenwhile the perception is being built, it will no longer be accessible forby the RP Manager, when it really expects the object to be there., Oror aif removedRPManager playertries thatto isremove removeda tooplayer bywhich RPhas Manager.already Thatbeen isremoved, athese reallysituations are very serious problem, as itthey will probably make the server fail.
 
So we need tomust synchronize gamethe Game and RP managerManagers.
 
The idea behind the solution is that the each manger requests access to the PlayerEntryContainer via a central mutex (a mutex is a syncronisation element attached to a resource, which can be owned by one task at any point in time. If the mutex is owned already when a task tries to access the object protected by it then the mutex will inform the task that it doesn't have access at this point in time to the object).
The idea is that they request to a central mutex access to the PlayerEntryContainer, and that mutex is the one that decide how the access is done.
 
WeThere need to differentiate between theare two types of accesses, read accessaccesses and write accessaccesses. WeNote canthat havetwo withoutreaders problemscan twoaccess readersan accessingobject in parallel, but we can only have one write can happen at the same time modifying the stuff.
In GameManager there are only Write actions, as this manager only modifies the state of the PlayerContainer. However, in the RP manager we have both Reads, when we build the perceptions, and Writes when the manager removes idle players. Hence here we have two different locks.
 
[[Marauroa]]
Whatever action we choose in GameManager they are Write actions, as the modify the state of the PlayerContainer, but in RP we have two parts, one that build the perceptions that is read only and one that removes idle players that is write, so we must apply two different locks there.