Hedgeroid: Start using the frontlib for more operations
authorMedo <smaxein@googlemail.com>
Mon, 06 Aug 2012 22:39:36 +0200
changeset 7476 2fb781bbdd51
parent 7473 45b9f25ff611
child 7479 c8c552ee3acb
Hedgeroid: Start using the frontlib for more operations
project_files/Android-build/SDL-android-project/assets/assetsversion.txt
project_files/Android-build/SDL-android-project/libs/ini4j-0.5.2.jar
project_files/Android-build/SDL-android-project/res/drawable-mdpi/lightbulb_off.png
project_files/Android-build/SDL-android-project/res/drawable-mdpi/lightbulb_on.png
project_files/Android-build/SDL-android-project/res/layout-large/activity_lobby.xml
project_files/Android-build/SDL-android-project/res/layout/activity_lobby.xml
project_files/Android-build/SDL-android-project/res/layout/activity_netroom.xml
project_files/Android-build/SDL-android-project/res/layout/fragment_playerlist.xml
project_files/Android-build/SDL-android-project/res/layout/fragment_teamlist.xml
project_files/Android-build/SDL-android-project/res/layout/lobby_players_fragment.xml
project_files/Android-build/SDL-android-project/res/menu/room_playerlist_chief_context.xml
project_files/Android-build/SDL-android-project/res/menu/room_playerlist_context.xml
project_files/Android-build/SDL-android-project/res/raw/basicsettings.ini
project_files/Android-build/SDL-android-project/res/raw/gamemods.ini
project_files/Android-build/SDL-android-project/res/raw/scheme_barrelmayhem.ini
project_files/Android-build/SDL-android-project/res/raw/scheme_cleanslate.ini
project_files/Android-build/SDL-android-project/res/raw/scheme_default_scheme.ini
project_files/Android-build/SDL-android-project/res/raw/scheme_fortmode.ini
project_files/Android-build/SDL-android-project/res/raw/scheme_kingmode.ini
project_files/Android-build/SDL-android-project/res/raw/scheme_minefield.ini
project_files/Android-build/SDL-android-project/res/raw/scheme_promode.ini
project_files/Android-build/SDL-android-project/res/raw/scheme_shoppa.ini
project_files/Android-build/SDL-android-project/res/raw/scheme_thinkingwithportals.ini
project_files/Android-build/SDL-android-project/res/raw/scheme_timeless.ini
project_files/Android-build/SDL-android-project/res/raw/scheme_tunnelhogs.ini
project_files/Android-build/SDL-android-project/res/raw/schemes_builtin.ini
project_files/Android-build/SDL-android-project/res/raw/team_one.hwt
project_files/Android-build/SDL-android-project/res/raw/team_one.xml
project_files/Android-build/SDL-android-project/res/raw/team_two.hwt
project_files/Android-build/SDL-android-project/res/raw/team_two.xml
project_files/Android-build/SDL-android-project/res/values/frontend_data_pointers.xml
project_files/Android-build/SDL-android-project/res/values/strings.xml
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/FrontendDataUtils.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/GameMode.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Grave.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Hog.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Map.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/MetaScheme.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Player.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/RoomlistRoom.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Scheme.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Schemes.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Team.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/TeamFile.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/TeamInGame.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/TeamIngameAttributes.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Weapon.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadAssets.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/EngineProtocol/EngineProtocolNetwork.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/EngineProtocol/GameConfig.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/EngineProtocol/PascalExports.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SDLActivity.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/StartGameActivity.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamCreatorActivity.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamSelectionActivity.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Utils.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/Flib.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/Frontlib.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/FrontlibTypeMapper.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/FrontlibTypeMapper.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/JnaFrontlib.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/LobbyActivity.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/LobbyPlayerlist.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/LobbyPlayerlistAdapter.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/LobbyPlayerlistFragment.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/MessageLog.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Netplay.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/NetplayStateFragment.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/ObservableTreeMap.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/ObservableTreeMapAdapter.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Player.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerList.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerListAdapter.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerlistFragment.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Room.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomActivity.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomList.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomListAdapter.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomPlayerlist.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomPlayerlistAdapter.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomPlayerlistFragment.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomlistFragment.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Teamlist.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/TeamlistAdapter.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/TeamlistFragment.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/TickHandler.java
--- a/project_files/Android-build/SDL-android-project/assets/assetsversion.txt	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/assets/assetsversion.txt	Mon Aug 06 22:39:36 2012 +0200
@@ -1,1 +1,1 @@
-1
\ No newline at end of file
+4
\ No newline at end of file
Binary file project_files/Android-build/SDL-android-project/libs/ini4j-0.5.2.jar has changed
Binary file project_files/Android-build/SDL-android-project/res/drawable-mdpi/lightbulb_off.png has changed
Binary file project_files/Android-build/SDL-android-project/res/drawable-mdpi/lightbulb_on.png has changed
--- a/project_files/Android-build/SDL-android-project/res/layout-large/activity_lobby.xml	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/res/layout-large/activity_lobby.xml	Mon Aug 06 22:39:36 2012 +0200
@@ -45,8 +45,8 @@
 	                android:id="@+id/playerListFragment"
 	                android:layout_width="fill_parent"
 	                android:layout_height="fill_parent"
-	                class="org.hedgewars.hedgeroid.netplay.PlayerlistFragment"
-	                tools:layout="@layout/lobby_players_fragment" />
+	                class="org.hedgewars.hedgeroid.netplay.LobbyPlayerlistFragment"
+	                tools:layout="@layout/fragment_playerlist" />
 	        </FrameLayout>
 	        
 	        <FrameLayout
--- a/project_files/Android-build/SDL-android-project/res/layout/activity_lobby.xml	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/res/layout/activity_lobby.xml	Mon Aug 06 22:39:36 2012 +0200
@@ -47,8 +47,8 @@
                     android:id="@+id/playerListFragment"
                     android:layout_width="fill_parent"
                     android:layout_height="fill_parent"
-                    class="org.hedgewars.hedgeroid.netplay.PlayerlistFragment"
-                    tools:layout="@layout/lobby_players_fragment" />
+                    class="org.hedgewars.hedgeroid.netplay.LobbyPlayerlistFragment"
+                    tools:layout="@layout/fragment_playerlist" />
             </FrameLayout>
         </LinearLayout>
     </TabHost>
--- a/project_files/Android-build/SDL-android-project/res/layout/activity_netroom.xml	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/res/layout/activity_netroom.xml	Mon Aug 06 22:39:36 2012 +0200
@@ -26,14 +26,18 @@
                 android:id="@+id/mapFrame"
                 android:layout_width="0dp"
                 android:layout_height="wrap_content"
+                android:layout_marginRight="10dp"
                 android:layout_weight="1"
-                android:layout_marginRight="10dp"
                 android:background="@drawable/box" >
 
-                <!-- <fragment
+                <!--
+                     <fragment
                     android:id="@+id/mapFragment"
+                                    android:layout_width="fill_parent"
+                android:layout_height="fill_parent"
                     class="org.hedgewars.hedgeroid.netplay.MapFragment"
-                    tools:layout="@layout/fragment_map" /> -->
+                    tools:layout="@layout/fragment_map" />
+                -->
             </FrameLayout>
 
             <FrameLayout
@@ -44,10 +48,14 @@
                 android:layout_weight="1"
                 android:background="@drawable/box" >
 
-               <!-- <fragment
+                <!--
+                    <fragment
                     android:id="@+id/settingsFragment"
+                                    android:layout_width="fill_parent"
+                android:layout_height="fill_parent"
                     class="org.hedgewars.hedgeroid.netplay.SettingsFragment"
-                    tools:layout="@layout/fragment_settings" /> -->
+                    tools:layout="@layout/fragment_settings" />
+                -->
             </FrameLayout>
 
             <FrameLayout
@@ -57,11 +65,12 @@
                 android:layout_weight="1"
                 android:background="@drawable/box" >
 
-                <!-- <fragment
+                <fragment
                     android:id="@+id/teamsFragment"
-                    class="org.hedgewars.hedgeroid.netplay.TeamsFragment"
-                    tools:layout="@layout/fragment_teamlist" /> -->
-
+                    android:layout_width="fill_parent"
+                    android:layout_height="fill_parent"
+                    class="org.hedgewars.hedgeroid.netplay.TeamlistFragment"
+                    tools:layout="@layout/fragment_teamlist" />
             </FrameLayout>
         </LinearLayout>
 
@@ -74,12 +83,12 @@
             android:layout_below="@id/upperFrame"
             android:background="@drawable/box" >
 
-            <!-- <fragment
+            <fragment
                 android:id="@+id/playerListFragment"
                 android:layout_width="fill_parent"
                 android:layout_height="fill_parent"
-                class="org.hedgewars.hedgeroid.netplay.PlayerlistFragment"
-                tools:layout="@layout/lobby_players_fragment" /> -->
+                class="org.hedgewars.hedgeroid.netplay.RoomPlayerlistFragment"
+                tools:layout="@layout/fragment_playerlist" />
         </FrameLayout>
 
         <FrameLayout
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/res/layout/fragment_playerlist.xml	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <ListView
+        android:id="@id/android:list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:drawSelectorOnTop="false"
+        android:cacheColorHint="@android:color/transparent"
+        tools:listitem="@layout/listview_player" />
+
+    <TextView
+        android:id="@id/android:empty"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center"
+        android:text="@string/no_players_in_list" />
+</FrameLayout>
\ No newline at end of file
--- a/project_files/Android-build/SDL-android-project/res/layout/fragment_teamlist.xml	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/res/layout/fragment_teamlist.xml	Mon Aug 06 22:39:36 2012 +0200
@@ -6,7 +6,7 @@
     android:orientation="vertical" >
 
     <ListView 
-        android:id="@+id/teamList"
+        android:id="@android:id/list"
         android:layout_width="match_parent"
         android:layout_height="0dp"
         android:layout_weight="1" 
--- a/project_files/Android-build/SDL-android-project/res/layout/lobby_players_fragment.xml	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical" >
-
-    <ListView
-        android:id="@id/android:list"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:drawSelectorOnTop="false"
-        android:cacheColorHint="@android:color/transparent"
-        tools:listitem="@layout/listview_player" />
-
-    <TextView
-        android:id="@id/android:empty"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:gravity="center"
-        android:text="@string/no_players_in_list" />
-</FrameLayout>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/res/menu/room_playerlist_chief_context.xml	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,6 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+    <item
+        android:id="@+id/player_kick"
+        android:title="@string/playerlist_contextmenu_kick">
+    </item>
+</menu>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/res/menu/room_playerlist_context.xml	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,6 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+    <item
+        android:id="@+id/player_info"
+        android:title="@string/lobby_playerlist_contextmenu_info">
+    </item>
+</menu>
\ No newline at end of file
--- a/project_files/Android-build/SDL-android-project/res/raw/basicsettings.ini	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-[DamagePercent]
-checkOverMax=false
-times1000=false
-command=e$damagepct
-default=100
-image=Damage
-max=300
-min=10
-title=Damage Modifier
-
-[TurnTime]
-checkOverMax=true
-times1000=true
-command=e$turntime
-default=45
-image=Time
-max=100
-min=1
-title=Turn Time
-
-[InitialHealth]
-checkOverMax=false
-times1000=false
-command=inithealth
-default=200
-image=Health
-max=200
-min=50
-title=Initial Health
-
-[SuddenDeathTimeout]
-checkOverMax=true
-times1000=false
-command=e$sd_turns
-default=15
-image=SuddenDeath
-max=50
-min=0
-title=Sudden Death Timeout
-
-[CrateDropTurns]
-checkOverMax=false
-times1000=false
-command=e$casefreq
-default=5
-image=Box
-max=9
-min=0
-title=Crate Drop Turns
-
-[MinesTime]
-checkOverMax=false
-times1000=true
-command=e$minestime
-default=3
-image=Time
-max=5
-min=-1
-title=Mines Time
-
-[MinesNumber]
-checkOverMax=false
-times1000=false
-command=e$minesnum
-default=4
-image=Mine
-max=80
-min=0
-title=Mines Number
-
-[MinesDudPercent]
-checkOverMax=false
-times1000=false
-command=e$minedudpct
-default=0
-image=Dud
-max=100
-min=0
-title=Dud Mines Probability (%)
-
-[Explosives]
-checkOverMax=false
-times1000=false
-command=e$explosives
-default=2
-image=Damage
-max=40
-min=0
-title=Explosives
-
-[HealthCratePercent]
-checkOverMax=false
-times1000=false
-command=e$healthprob
-default=35
-image=Health
-max=100
-min=0
-title=Health Kit Probability (%)
-
-[HealthCrateHP]
-checkOverMax=false
-times1000=false
-command=e$hcaseamount
-default=25
-image=Health
-max=200
-min=0
-title=Health Amount in Kit
-
-[SuddenDeathWaterRise]
-checkOverMax=false
-times1000=false
-command=e$waterrise
-default=47
-image=SuddenDeath
-max=100
-min=0
-title=Water Rise Amount
-
-[SuddenDeathHealthDecrease]
-checkOverMax=false
-times1000=false
-command=e$healthdec
-default=5
-image=SuddenDeath
-max=100
-min=0
-title=Health Decrease
-
-[RopeLengthPercent]
-checkOverMax=false
-times1000=false
-command=e$ropepct
-default=100
-image=Rope
-max=999
-min=25
-title=Rope Length (%)
-
-[GetAwayTimePercent]
-checkOverMax=false
-times1000=false
-command=e$getawaytime
-default=100
-image=Time
-max=999
-min=0
-title=Get Away Time (%)
-
--- a/project_files/Android-build/SDL-android-project/res/raw/gamemods.ini	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-[SolidLand]
-bitmaskIndex=2
-
-[Border]
-bitmaskIndex=3
-
-[DivideTeams]
-bitmaskIndex=4
-
-[LowGravity]
-bitmaskIndex=5
-
-[LaserSight]
-bitmaskIndex=6
-
-[Invulnerable]
-bitmaskIndex=7
-
-[ResetHealth]
-bitmaskIndex=8
-
-[Vampiric]
-bitmaskIndex=9
-
-[Karma]
-bitmaskIndex=10
-
-[Artillery]
-bitmaskIndex=11
-
-[Forts]
-bitmaskIndex=12
-
-[RandomOrder]
-bitmaskIndex=13
-
-[King]
-bitmaskIndex=14
-
-[PlaceHog]
-bitmaskIndex=15
-
-[SharedAmmo]
-bitmaskIndex=16
-
-[DisableGirders]
-bitmaskIndex=17
-
-[DisableLandObjects]
-bitmaskIndex=18
-
-[AISurvival]
-bitmaskIndex=19
-
-[InfAttack]
-bitmaskIndex=20
-
-[ResetWeps]
-bitmaskIndex=21
-
-[PerHogAmmo]
-bitmaskIndex=22
-
-[DisableWind]
-bitmaskIndex=23
-
-[MoreWind]
-bitmaskIndex=24
-
-[TagTeam]
-bitmaskIndex=25
-
-[BottomBorder]
-bitmaskIndex=26
--- a/project_files/Android-build/SDL-android-project/res/raw/scheme_barrelmayhem.ini	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-[Scheme]
-name=Barrel Mayhem
-
-[BasicSettings]
-DamagePercent=100
-TurnTime=30
-InitialHealth=100
-SuddenDeathTimeout=15
-CrateDropTurns=0
-MinesTime=0
-MinesNumber=0
-MinesDudPercent=0
-Explosives=80
-HealthCratePercent=35
-HealthCrateHP=25
-SuddenDeathWaterRise=47
-SuddenDeathHealthDecrease=5
-RopeLengthPercent=100
-GetAwayTimePercent=100
-
-[GameMods]
-SolidLand=false
-Border=false
-DivideTeams=false
-LowGravity=false
-LaserSight=false
-Invulnerable=false
-ResetHealth=false
-Vampiric=false
-Karma=false
-Artillery=false
-Forts=false
-RandomOrder=true
-King=false
-PlaceHog=false
-SharedAmmo=true
-DisableGirders=false
-DisableLandObjects=false
-AISurvival=false
-InfAttack=false
-ResetWeps=false
-PerHogAmmo=false
-DisableWind=false
-MoreWind=false
-TagTeam=false
-BottomBorder=false
--- a/project_files/Android-build/SDL-android-project/res/raw/scheme_cleanslate.ini	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-[Scheme]
-name=Clean Slate
-
-[BasicSettings]
-DamagePercent=100
-TurnTime=45
-InitialHealth=100
-SuddenDeathTimeout=15
-CrateDropTurns=5
-MinesTime=3
-MinesNumber=4
-MinesDudPercent=0
-Explosives=2
-HealthCratePercent=35
-HealthCrateHP=25
-SuddenDeathWaterRise=47
-SuddenDeathHealthDecrease=5
-RopeLengthPercent=100
-GetAwayTimePercent=100
-
-[GameMods]
-SolidLand=false
-Border=false
-DivideTeams=false
-LowGravity=false
-LaserSight=false
-Invulnerable=false
-ResetHealth=true
-Vampiric=false
-Karma=false
-Artillery=false
-Forts=false
-RandomOrder=true
-King=false
-PlaceHog=false
-SharedAmmo=false
-DisableGirders=false
-DisableLandObjects=false
-AISurvival=false
-InfAttack=true
-ResetWeps=true
-PerHogAmmo=false
-DisableWind=false
-MoreWind=false
-TagTeam=false
-BottomBorder=false
--- a/project_files/Android-build/SDL-android-project/res/raw/scheme_default_scheme.ini	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-[Scheme]
-name=Default
-
-[BasicSettings]
-DamagePercent=100
-TurnTime=45
-InitialHealth=100
-SuddenDeathTimeout=15
-CrateDropTurns=5
-MinesTime=3
-MinesNumber=4
-MinesDudPercent=0
-Explosives=2
-HealthCratePercent=35
-HealthCrateHP=25
-SuddenDeathWaterRise=47
-SuddenDeathHealthDecrease=5
-RopeLengthPercent=100
-GetAwayTimePercent=100
-
-[GameMods]
-SolidLand=false
-Border=false
-DivideTeams=false
-LowGravity=false
-LaserSight=false
-Invulnerable=false
-ResetHealth=false
-Vampiric=false
-Karma=false
-Artillery=false
-Forts=false
-RandomOrder=true
-King=false
-PlaceHog=false
-SharedAmmo=false
-DisableGirders=false
-DisableLandObjects=false
-AISurvival=false
-InfAttack=false
-ResetWeps=false
-PerHogAmmo=false
-DisableWind=false
-MoreWind=false
-TagTeam=false
-BottomBorder=false
--- a/project_files/Android-build/SDL-android-project/res/raw/scheme_fortmode.ini	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-[Scheme]
-name=Fort Mode
-
-[BasicSettings]
-DamagePercent=100
-TurnTime=45
-InitialHealth=100
-SuddenDeathTimeout=15
-CrateDropTurns=5
-MinesTime=3
-MinesNumber=0
-MinesDudPercent=0
-Explosives=0
-HealthCratePercent=35
-HealthCrateHP=25
-SuddenDeathWaterRise=47
-SuddenDeathHealthDecrease=5
-RopeLengthPercent=100
-GetAwayTimePercent=100
-
-[GameMods]
-SolidLand=false
-Border=false
-DivideTeams=true
-LowGravity=true
-LaserSight=false
-Invulnerable=false
-ResetHealth=false
-Vampiric=false
-Karma=false
-Artillery=false
-Forts=true
-RandomOrder=true
-King=false
-PlaceHog=false
-SharedAmmo=false
-DisableGirders=false
-DisableLandObjects=false
-AISurvival=false
-InfAttack=false
-ResetWeps=false
-PerHogAmmo=false
-DisableWind=false
-MoreWind=false
-TagTeam=false
-BottomBorder=false
--- a/project_files/Android-build/SDL-android-project/res/raw/scheme_kingmode.ini	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-[Scheme]
-name=King Mode
-
-[BasicSettings]
-DamagePercent=100
-TurnTime=45
-InitialHealth=100
-SuddenDeathTimeout=15
-CrateDropTurns=5
-MinesTime=3
-MinesNumber=4
-MinesDudPercent=0
-Explosives=2
-HealthCratePercent=35
-HealthCrateHP=25
-SuddenDeathWaterRise=47
-SuddenDeathHealthDecrease=5
-RopeLengthPercent=100
-GetAwayTimePercent=100
-
-[GameMods]
-SolidLand=false
-Border=false
-DivideTeams=false
-LowGravity=false
-LaserSight=false
-Invulnerable=false
-ResetHealth=false
-Vampiric=false
-Karma=false
-Artillery=false
-Forts=false
-RandomOrder=true
-King=true
-PlaceHog=false
-SharedAmmo=false
-DisableGirders=false
-DisableLandObjects=false
-AISurvival=false
-InfAttack=false
-ResetWeps=false
-PerHogAmmo=false
-DisableWind=false
-MoreWind=false
-TagTeam=false
-BottomBorder=false
--- a/project_files/Android-build/SDL-android-project/res/raw/scheme_minefield.ini	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-[Scheme]
-name=Minefield
-
-[BasicSettings]
-DamagePercent=100
-TurnTime=30
-InitialHealth=50
-SuddenDeathTimeout=15
-CrateDropTurns=0
-MinesTime=0
-MinesNumber=80
-MinesDudPercent=0
-Explosives=0
-HealthCratePercent=35
-HealthCrateHP=25
-SuddenDeathWaterRise=47
-SuddenDeathHealthDecrease=5
-RopeLengthPercent=100
-GetAwayTimePercent=100
-
-[GameMods]
-SolidLand=false
-Border=false
-DivideTeams=false
-LowGravity=false
-LaserSight=false
-Invulnerable=false
-ResetHealth=false
-Vampiric=false
-Karma=false
-Artillery=false
-Forts=false
-RandomOrder=true
-King=false
-PlaceHog=false
-SharedAmmo=true
-DisableGirders=true
-DisableLandObjects=false
-AISurvival=false
-InfAttack=false
-ResetWeps=false
-PerHogAmmo=false
-DisableWind=false
-MoreWind=false
-TagTeam=false
-BottomBorder=false
--- a/project_files/Android-build/SDL-android-project/res/raw/scheme_promode.ini	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-[Scheme]
-name=Pro Mode
-
-[BasicSettings]
-DamagePercent=100
-TurnTime=15
-InitialHealth=100
-SuddenDeathTimeout=15
-CrateDropTurns=0
-MinesTime=3
-MinesNumber=0
-MinesDudPercent=0
-Explosives=2
-HealthCratePercent=35
-HealthCrateHP=25
-SuddenDeathWaterRise=47
-SuddenDeathHealthDecrease=5
-RopeLengthPercent=100
-GetAwayTimePercent=100
-
-[GameMods]
-SolidLand=false
-Border=false
-DivideTeams=false
-LowGravity=false
-LaserSight=false
-Invulnerable=false
-ResetHealth=false
-Vampiric=false
-Karma=false
-Artillery=false
-Forts=false
-RandomOrder=true
-King=false
-PlaceHog=false
-SharedAmmo=true
-DisableGirders=false
-DisableLandObjects=false
-AISurvival=false
-InfAttack=false
-ResetWeps=false
-PerHogAmmo=false
-DisableWind=false
-MoreWind=false
-TagTeam=false
-BottomBorder=false
--- a/project_files/Android-build/SDL-android-project/res/raw/scheme_shoppa.ini	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-[Scheme]
-name=Shoppa
-
-[BasicSettings]
-DamagePercent=100
-TurnTime=30
-InitialHealth=100
-SuddenDeathTimeout=50
-CrateDropTurns=1
-MinesTime=3
-MinesNumber=0
-MinesDudPercent=0
-Explosives=0
-HealthCratePercent=0
-HealthCrateHP=25
-SuddenDeathWaterRise=47
-SuddenDeathHealthDecrease=5
-RopeLengthPercent=100
-GetAwayTimePercent=100
-
-[GameMods]
-SolidLand=false
-Border=true
-DivideTeams=true
-LowGravity=false
-LaserSight=false
-Invulnerable=false
-ResetHealth=false
-Vampiric=false
-Karma=false
-Artillery=false
-Forts=false
-RandomOrder=true
-King=false
-PlaceHog=false
-SharedAmmo=true
-DisableGirders=true
-DisableLandObjects=false
-AISurvival=false
-InfAttack=false
-ResetWeps=false
-PerHogAmmo=false
-DisableWind=false
-MoreWind=false
-TagTeam=false
-BottomBorder=false
--- a/project_files/Android-build/SDL-android-project/res/raw/scheme_thinkingwithportals.ini	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-[Scheme]
-name=Thinking with Portals
-
-[BasicSettings]
-DamagePercent=100
-TurnTime=45
-InitialHealth=100
-SuddenDeathTimeout=15
-CrateDropTurns=2
-MinesTime=3
-MinesNumber=5
-MinesDudPercent=0
-Explosives=5
-HealthCratePercent=25
-HealthCrateHP=25
-SuddenDeathWaterRise=47
-SuddenDeathHealthDecrease=5
-RopeLengthPercent=100
-GetAwayTimePercent=100
-
-[GameMods]
-SolidLand=false
-Border=false
-DivideTeams=false
-LowGravity=false
-LaserSight=false
-Invulnerable=false
-ResetHealth=false
-Vampiric=false
-Karma=false
-Artillery=false
-Forts=true
-RandomOrder=true
-King=false
-PlaceHog=false
-SharedAmmo=false
-DisableGirders=false
-DisableLandObjects=false
-AISurvival=false
-InfAttack=false
-ResetWeps=false
-PerHogAmmo=false
-DisableWind=false
-MoreWind=false
-TagTeam=false
-BottomBorder=false
--- a/project_files/Android-build/SDL-android-project/res/raw/scheme_timeless.ini	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-[Scheme]
-name=Timeless
-
-[BasicSettings]
-DamagePercent=100
-TurnTime=9999
-InitialHealth=100
-SuddenDeathTimeout=15
-CrateDropTurns=5
-MinesTime=3
-MinesNumber=5
-MinesDudPercent=10
-Explosives=2
-HealthCratePercent=35
-HealthCrateHP=30
-SuddenDeathWaterRise=0
-SuddenDeathHealthDecrease=0
-RopeLengthPercent=100
-GetAwayTimePercent=100
-
-[GameMods]
-SolidLand=false
-Border=false
-DivideTeams=false
-LowGravity=false
-LaserSight=false
-Invulnerable=false
-ResetHealth=false
-Vampiric=false
-Karma=false
-Artillery=false
-Forts=false
-RandomOrder=true
-King=false
-PlaceHog=false
-SharedAmmo=true
-DisableGirders=false
-DisableLandObjects=false
-AISurvival=false
-InfAttack=false
-ResetWeps=false
-PerHogAmmo=true
-DisableWind=false
-MoreWind=false
-TagTeam=false
-BottomBorder=false
--- a/project_files/Android-build/SDL-android-project/res/raw/scheme_tunnelhogs.ini	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-[Scheme]
-name=Tunnelhogs
-
-[BasicSettings]
-DamagePercent=100
-TurnTime=30
-InitialHealth=100
-SuddenDeathTimeout=15
-CrateDropTurns=5
-MinesTime=3
-MinesNumber=10
-MinesDudPercent=10
-Explosives=10
-HealthCratePercent=35
-HealthCrateHP=25
-SuddenDeathWaterRise=47
-SuddenDeathHealthDecrease=5
-RopeLengthPercent=100
-GetAwayTimePercent=100
-
-[GameMods]
-SolidLand=false
-Border=false
-DivideTeams=true
-LowGravity=false
-LaserSight=false
-Invulnerable=false
-ResetHealth=false
-Vampiric=false
-Karma=false
-Artillery=false
-Forts=false
-RandomOrder=true
-King=false
-PlaceHog=false
-SharedAmmo=true
-DisableGirders=true
-DisableLandObjects=true
-AISurvival=false
-InfAttack=false
-ResetWeps=false
-PerHogAmmo=false
-DisableWind=false
-MoreWind=false
-TagTeam=false
-BottomBorder=false
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/res/raw/schemes_builtin.ini	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,456 @@
+
+[schemes]
+size                           = 11
+1\name                         = Default
+1\fortsmode                    = false
+1\divteams                     = false
+1\solidland                    = false
+1\border                       = false
+1\lowgrav                      = false
+1\laser                        = false
+1\invulnerability              = false
+1\resethealth                  = false
+1\vampiric                     = false
+1\karma                        = false
+1\artillery                    = false
+1\randomorder                  = false
+1\king                         = false
+1\placehog                     = false
+1\sharedammo                   = false
+1\disablegirders               = false
+1\disablelandobjects           = false
+1\aisurvival                   = false
+1\infattack                    = false
+1\resetweps                    = false
+1\perhogammo                   = false
+1\disablewind                  = false
+1\morewind                     = false
+1\tagteam                      = false
+1\bottomborder                 = false
+1\damagefactor                 = 100
+1\turntime                     = 45
+1\health                       = 100
+1\suddendeath                  = 15
+1\caseprobability              = 5
+1\minestime                    = 3
+1\minesnum                     = 4
+1\minedudpct                   = 0
+1\explosives                   = 2
+1\healthprobability            = 35
+1\healthcaseamount             = 25
+1\waterrise                    = 47
+1\healthdecrease               = 5
+1\ropepct                      = 100
+1\getawaytime                  = 100
+2\name                         = Pro Mode
+2\fortsmode                    = false
+2\divteams                     = false
+2\solidland                    = false
+2\border                       = false
+2\lowgrav                      = false
+2\laser                        = false
+2\invulnerability              = false
+2\resethealth                  = false
+2\vampiric                     = false
+2\karma                        = false
+2\artillery                    = false
+2\randomorder                  = true
+2\king                         = false
+2\placehog                     = false
+2\sharedammo                   = false
+2\disablegirders               = false
+2\disablelandobjects           = false
+2\aisurvival                   = false
+2\infattack                    = false
+2\resetweps                    = false
+2\perhogammo                   = false
+2\disablewind                  = false
+2\morewind                     = false
+2\tagteam                      = false
+2\bottomborder                 = false
+2\damagefactor                 = 100
+2\turntime                     = 45
+2\health                       = 100
+2\suddendeath                  = 15
+2\caseprobability              = 5
+2\minestime                    = 3
+2\minesnum                     = 4
+2\minedudpct                   = 0
+2\explosives                   = 2
+2\healthprobability            = 35
+2\healthcaseamount             = 25
+2\waterrise                    = 47
+2\healthdecrease               = 5
+2\ropepct                      = 100
+2\getawaytime                  = 100
+3\name                         = Shoppa
+3\fortsmode                    = false
+3\divteams                     = false
+3\solidland                    = false
+3\border                       = false
+3\lowgrav                      = false
+3\laser                        = false
+3\invulnerability              = false
+3\resethealth                  = false
+3\vampiric                     = false
+3\karma                        = false
+3\artillery                    = false
+3\randomorder                  = true
+3\king                         = false
+3\placehog                     = false
+3\sharedammo                   = true
+3\disablegirders               = false
+3\disablelandobjects           = false
+3\aisurvival                   = false
+3\infattack                    = false
+3\resetweps                    = false
+3\perhogammo                   = false
+3\disablewind                  = false
+3\morewind                     = false
+3\tagteam                      = false
+3\bottomborder                 = false
+3\damagefactor                 = 100
+3\turntime                     = 15
+3\health                       = 100
+3\suddendeath                  = 15
+3\caseprobability              = 0
+3\minestime                    = 3
+3\minesnum                     = 0
+3\minedudpct                   = 0
+3\explosives                   = 2
+3\healthprobability            = 35
+3\healthcaseamount             = 25
+3\waterrise                    = 47
+3\healthdecrease               = 5
+3\ropepct                      = 100
+3\getawaytime                  = 100
+4\name                         = Clean Slate
+4\fortsmode                    = false
+4\divteams                     = false
+4\solidland                    = true
+4\border                       = true
+4\lowgrav                      = false
+4\laser                        = false
+4\invulnerability              = false
+4\resethealth                  = false
+4\vampiric                     = false
+4\karma                        = false
+4\artillery                    = false
+4\randomorder                  = true
+4\king                         = false
+4\placehog                     = false
+4\sharedammo                   = true
+4\disablegirders               = true
+4\disablelandobjects           = false
+4\aisurvival                   = false
+4\infattack                    = false
+4\resetweps                    = true
+4\perhogammo                   = false
+4\disablewind                  = false
+4\morewind                     = false
+4\tagteam                      = false
+4\bottomborder                 = false
+4\damagefactor                 = 100
+4\turntime                     = 30
+4\health                       = 100
+4\suddendeath                  = 50
+4\caseprobability              = 1
+4\minestime                    = 3
+4\minesnum                     = 0
+4\minedudpct                   = 0
+4\explosives                   = 0
+4\healthprobability            = 0
+4\healthcaseamount             = 25
+4\waterrise                    = 47
+4\healthdecrease               = 5
+4\ropepct                      = 100
+4\getawaytime                  = 100
+5\name                         = Minefield
+5\fortsmode                    = false
+5\divteams                     = false
+5\solidland                    = false
+5\border                       = false
+5\lowgrav                      = false
+5\laser                        = false
+5\invulnerability              = false
+5\resethealth                  = true
+5\vampiric                     = false
+5\karma                        = false
+5\artillery                    = false
+5\randomorder                  = true
+5\king                         = false
+5\placehog                     = false
+5\sharedammo                   = false
+5\disablegirders               = false
+5\disablelandobjects           = false
+5\aisurvival                   = false
+5\infattack                    = true
+5\resetweps                    = true
+5\perhogammo                   = false
+5\disablewind                  = false
+5\morewind                     = false
+5\tagteam                      = false
+5\bottomborder                 = false
+5\damagefactor                 = 100
+5\turntime                     = 45
+5\health                       = 100
+5\suddendeath                  = 15
+5\caseprobability              = 5
+5\minestime                    = 3
+5\minesnum                     = 4
+5\minedudpct                   = 0
+5\explosives                   = 2
+5\healthprobability            = 35
+5\healthcaseamount             = 25
+5\waterrise                    = 47
+5\healthdecrease               = 5
+5\ropepct                      = 100
+5\getawaytime                  = 100
+6\name                         = Barrel Mayhem
+6\fortsmode                    = false
+6\divteams                     = false
+6\solidland                    = false
+6\border                       = false
+6\lowgrav                      = false
+6\laser                        = false
+6\invulnerability              = false
+6\resethealth                  = false
+6\vampiric                     = false
+6\karma                        = false
+6\artillery                    = false
+6\randomorder                  = true
+6\king                         = false
+6\placehog                     = false
+6\sharedammo                   = true
+6\disablegirders               = true
+6\disablelandobjects           = false
+6\aisurvival                   = false
+6\infattack                    = false
+6\resetweps                    = false
+6\perhogammo                   = false
+6\disablewind                  = false
+6\morewind                     = false
+6\tagteam                      = false
+6\bottomborder                 = false
+6\damagefactor                 = 100
+6\turntime                     = 30
+6\health                       = 50
+6\suddendeath                  = 15
+6\caseprobability              = 0
+6\minestime                    = 0
+6\minesnum                     = 80
+6\minedudpct                   = 0
+6\explosives                   = 0
+6\healthprobability            = 35
+6\healthcaseamount             = 25
+6\waterrise                    = 47
+6\healthdecrease               = 5
+6\ropepct                      = 100
+6\getawaytime                  = 100
+7\name                         = Tunnel Hogs
+7\fortsmode                    = false
+7\divteams                     = false
+7\solidland                    = false
+7\border                       = false
+7\lowgrav                      = false
+7\laser                        = false
+7\invulnerability              = false
+7\resethealth                  = false
+7\vampiric                     = false
+7\karma                        = false
+7\artillery                    = false
+7\randomorder                  = true
+7\king                         = false
+7\placehog                     = false
+7\sharedammo                   = true
+7\disablegirders               = false
+7\disablelandobjects           = false
+7\aisurvival                   = false
+7\infattack                    = false
+7\resetweps                    = false
+7\perhogammo                   = false
+7\disablewind                  = false
+7\morewind                     = false
+7\tagteam                      = false
+7\bottomborder                 = false
+7\damagefactor                 = 100
+7\turntime                     = 30
+7\health                       = 100
+7\suddendeath                  = 15
+7\caseprobability              = 0
+7\minestime                    = 0
+7\minesnum                     = 0
+7\minedudpct                   = 0
+7\explosives                   = 80
+7\healthprobability            = 35
+7\healthcaseamount             = 25
+7\waterrise                    = 47
+7\healthdecrease               = 5
+7\ropepct                      = 100
+7\getawaytime                  = 100
+8\name                         = Fort Mode
+8\fortsmode                    = false
+8\divteams                     = false
+8\solidland                    = false
+8\border                       = true
+8\lowgrav                      = false
+8\laser                        = false
+8\invulnerability              = false
+8\resethealth                  = false
+8\vampiric                     = false
+8\karma                        = false
+8\artillery                    = false
+8\randomorder                  = true
+8\king                         = false
+8\placehog                     = false
+8\sharedammo                   = true
+8\disablegirders               = true
+8\disablelandobjects           = true
+8\aisurvival                   = false
+8\infattack                    = false
+8\resetweps                    = false
+8\perhogammo                   = false
+8\disablewind                  = false
+8\morewind                     = false
+8\tagteam                      = false
+8\bottomborder                 = false
+8\damagefactor                 = 100
+8\turntime                     = 30
+8\health                       = 100
+8\suddendeath                  = 15
+8\caseprobability              = 5
+8\minestime                    = 3
+8\minesnum                     = 10
+8\minedudpct                   = 10
+8\explosives                   = 10
+8\healthprobability            = 35
+8\healthcaseamount             = 25
+8\waterrise                    = 47
+8\healthdecrease               = 5
+8\ropepct                      = 100
+8\getawaytime                  = 100
+9\name                         = Timeless
+9\fortsmode                    = true
+9\divteams                     = true
+9\solidland                    = false
+9\border                       = false
+9\lowgrav                      = true
+9\laser                        = false
+9\invulnerability              = false
+9\resethealth                  = false
+9\vampiric                     = false
+9\karma                        = false
+9\artillery                    = false
+9\randomorder                  = true
+9\king                         = false
+9\placehog                     = false
+9\sharedammo                   = false
+9\disablegirders               = false
+9\disablelandobjects           = false
+9\aisurvival                   = false
+9\infattack                    = false
+9\resetweps                    = false
+9\perhogammo                   = false
+9\disablewind                  = false
+9\morewind                     = false
+9\tagteam                      = false
+9\bottomborder                 = false
+9\damagefactor                 = 100
+9\turntime                     = 45
+9\health                       = 100
+9\suddendeath                  = 15
+9\caseprobability              = 5
+9\minestime                    = 3
+9\minesnum                     = 0
+9\minedudpct                   = 0
+9\explosives                   = 0
+9\healthprobability            = 35
+9\healthcaseamount             = 25
+9\waterrise                    = 47
+9\healthdecrease               = 5
+9\ropepct                      = 100
+9\getawaytime                  = 100
+10\name                        = Thinking with Portals
+10\fortsmode                   = false
+10\divteams                    = false
+10\solidland                   = false
+10\border                      = false
+10\lowgrav                     = false
+10\laser                       = false
+10\invulnerability             = false
+10\resethealth                 = false
+10\vampiric                    = false
+10\karma                       = false
+10\artillery                   = false
+10\randomorder                 = true
+10\king                        = false
+10\placehog                    = false
+10\sharedammo                  = false
+10\disablegirders              = false
+10\disablelandobjects          = false
+10\aisurvival                  = false
+10\infattack                   = false
+10\resetweps                   = false
+10\perhogammo                  = true
+10\disablewind                 = false
+10\morewind                    = false
+10\tagteam                     = false
+10\bottomborder                = false
+10\damagefactor                = 100
+10\turntime                    = 9999
+10\health                      = 100
+10\suddendeath                 = 15
+10\caseprobability             = 5
+10\minestime                   = 3
+10\minesnum                    = 5
+10\minedudpct                  = 10
+10\explosives                  = 2
+10\healthprobability           = 35
+10\healthcaseamount            = 30
+10\waterrise                   = 0
+10\healthdecrease              = 0
+10\ropepct                     = 100
+10\getawaytime                 = 100
+11\name                        = King Mode
+11\fortsmode                   = false
+11\divteams                    = false
+11\solidland                   = false
+11\border                      = false
+11\lowgrav                     = false
+11\laser                       = false
+11\invulnerability             = false
+11\resethealth                 = false
+11\vampiric                    = false
+11\karma                       = false
+11\artillery                   = true
+11\randomorder                 = true
+11\king                        = false
+11\placehog                    = false
+11\sharedammo                  = false
+11\disablegirders              = false
+11\disablelandobjects          = false
+11\aisurvival                  = false
+11\infattack                   = false
+11\resetweps                   = false
+11\perhogammo                  = false
+11\disablewind                 = false
+11\morewind                    = false
+11\tagteam                     = false
+11\bottomborder                = false
+11\damagefactor                = 100
+11\turntime                    = 45
+11\health                      = 100
+11\suddendeath                 = 15
+11\caseprobability             = 2
+11\minestime                   = 3
+11\minesnum                    = 5
+11\minedudpct                  = 0
+11\explosives                  = 5
+11\healthprobability           = 25
+11\healthcaseamount            = 25
+11\waterrise                   = 47
+11\healthdecrease              = 5
+11\ropepct                     = 100
+11\getawaytime                 = 100
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/res/raw/team_one.hwt	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,74 @@
+[Team]
+Name=Team 1
+Grave=Bone
+Fort=Lego
+Voicepack=Classic
+Flag=hedgewars
+Difficulty=0
+Rounds=0
+Wins=0
+CampaignProgress=0
+
+[Hedgehog0]
+Name=Leonidas
+Hat=NoHat
+Rounds=0
+Kills=0
+Deaths=0
+Suicides=0
+
+[Hedgehog1]
+Name=Pipo
+Hat=NoHat
+Rounds=0
+Kills=0
+Deaths=0
+Suicides=0
+
+[Hedgehog2]
+Name=Sonic
+Hat=NoHat
+Rounds=0
+Kills=0
+Deaths=0
+Suicides=0
+
+[Hedgehog3]
+Name=Xin
+Hat=NoHat
+Rounds=0
+Kills=0
+Deaths=0
+Suicides=0
+
+[Hedgehog4]
+Name=Arnold
+Hat=NoHat
+Rounds=0
+Kills=0
+Deaths=0
+Suicides=0
+
+[Hedgehog5]
+Name=Jack
+Hat=NoHat
+Rounds=0
+Kills=0
+Deaths=0
+Suicides=0
+
+[Hedgehog6]
+Name=Tom
+Hat=NoHat
+Rounds=0
+Kills=0
+Deaths=0
+Suicides=0
+
+[Hedgehog7]
+Name=Goldie
+Hat=NoHat
+Rounds=0
+Kills=0
+Deaths=0
+Suicides=0
--- a/project_files/Android-build/SDL-android-project/res/raw/team_one.xml	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
-<team>
-  <name>Team 1</name>
-  <flag>hedgewars</flag>
-  <fort>Lego</fort>
-  <grave>Bone</grave>
-  <voice>Classic</voice>
-  <hash>0</hash>
-  <hog>
-    <name>Leonidas</name>
-    <hat>NoHat</hat>
-    <level>0</level>
-  </hog>
-  <hog>
-    <name>Pipo</name>
-    <hat>NoHat</hat>
-    <level>0</level>
-  </hog>
-  <hog>
-    <name>Sonic</name>
-    <hat>NoHat</hat>
-    <level>0</level>
-  </hog>
-  <hog>
-    <name>Xin</name>
-    <hat>NoHat</hat>
-    <level>0</level>
-  </hog>
-  <hog>
-    <name>Arnold</name>
-    <hat>NoHat</hat>
-    <level>0</level>
-  </hog>
-  <hog>
-    <name>Jack</name>
-    <hat>NoHat</hat>
-    <level>0</level>
-  </hog>
-  <hog>
-    <name>Tom</name>
-    <hat>NoHat</hat>
-    <level>0</level>
-  </hog>
-  <hog>
-    <name>Goldie</name>
-    <hat>NoHat</hat>
-    <level>0</level>
-  </hog>
-</team>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/res/raw/team_two.hwt	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,74 @@
+[Team]
+Name=Team 2
+Grave=Bone
+Fort=Lego
+Voicepack=Classic
+Flag=cm_binary
+Difficulty=2
+Rounds=0
+Wins=0
+CampaignProgress=0
+
+[Hedgehog0]
+Name=Paris
+Hat=NoHat
+Rounds=0
+Kills=0
+Deaths=0
+Suicides=0
+
+[Hedgehog1]
+Name=Knut
+Hat=NoHat
+Rounds=0
+Kills=0
+Deaths=0
+Suicides=0
+
+[Hedgehog2]
+Name=Ash
+Hat=NoHat
+Rounds=0
+Kills=0
+Deaths=0
+Suicides=0
+
+[Hedgehog3]
+Name=Woad
+Hat=NoHat
+Rounds=0
+Kills=0
+Deaths=0
+Suicides=0
+
+[Hedgehog4]
+Name=Bob
+Hat=NoHat
+Rounds=0
+Kills=0
+Deaths=0
+Suicides=0
+
+[Hedgehog5]
+Name=Corky
+Hat=NoHat
+Rounds=0
+Kills=0
+Deaths=0
+Suicides=0
+
+[Hedgehog6]
+Name=Bea
+Hat=NoHat
+Rounds=0
+Kills=0
+Deaths=0
+Suicides=0
+
+[Hedgehog7]
+Name=Silvia
+Hat=NoHat
+Rounds=0
+Kills=0
+Deaths=0
+Suicides=0
--- a/project_files/Android-build/SDL-android-project/res/raw/team_two.xml	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
-<team>
-  <name>Team 2</name>
-  <flag>cm_binary</flag>
-  <fort>Lego</fort>
-  <grave>Bone</grave>
-  <voice>Classic</voice>
-  <hash>0</hash>
-  <hog>
-    <name>Paris</name>
-    <hat>NoHat</hat>
-    <level>2</level>
-  </hog>
-  <hog>
-    <name>Knut</name>
-    <hat>NoHat</hat>
-    <level>2</level>
-  </hog>
-  <hog>
-    <name>Ash</name>
-    <hat>NoHat</hat>
-    <level>2</level>
-  </hog>
-  <hog>
-    <name>Woad</name>
-    <hat>NoHat</hat>
-    <level>2</level>
-  </hog>
-  <hog>
-    <name>Bob</name>
-    <hat>NoHat</hat>
-    <level>2</level>
-  </hog>
-  <hog>
-    <name>Corky</name>
-    <hat>NoHat</hat>
-    <level>2</level>
-  </hog>
-  <hog>
-    <name>Bea</name>
-    <hat>NoHat</hat>
-    <level>2</level>
-  </hog>
-  <hog>
-    <name>Silvia</name>
-    <hat>NoHat</hat>
-    <level>2</level>
-  </hog>
-</team>
\ No newline at end of file
--- a/project_files/Android-build/SDL-android-project/res/values/frontend_data_pointers.xml	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/res/values/frontend_data_pointers.xml	Mon Aug 06 22:39:36 2012 +0200
@@ -1,22 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
 
-<array name="schemes">
-	<item>@raw/basicsettings</item>
-    <item>@raw/gamemods</item>
-	<item>@raw/scheme_default_scheme</item>
-	<item>@raw/scheme_barrelmayhem</item>
-	<item>@raw/scheme_cleanslate</item>
-	<item>@raw/scheme_fortmode</item>
-	<item>@raw/scheme_kingmode</item>
-	<item>@raw/scheme_minefield</item>
-	<item>@raw/scheme_promode</item>
-	<item>@raw/scheme_shoppa</item>
-	<item>@raw/scheme_thinkingwithportals</item>
-	<item>@raw/scheme_timeless</item>
-	<item>@raw/scheme_tunnelhogs</item>
-</array>
-
 <array name="weapons">
     <item>@raw/weapon_default</item>
     <item>@raw/weapon_clean</item>
@@ -30,6 +14,5 @@
 <array name="teams">
 	<item>@raw/team_one</item>
 	<item>@raw/team_two</item>
-
 </array>
 </resources>
--- a/project_files/Android-build/SDL-android-project/res/values/strings.xml	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/res/values/strings.xml	Mon Aug 06 22:39:36 2012 +0200
@@ -104,6 +104,7 @@
     <string name="start_netgame_dialog_message">Please select a username.</string>
     <string name="start_netgame_dialog_playername_hint">Username</string>
     
+    <string name="playerlist_contextmenu_kick">Kick</string>
     <string name="lobby_playerlist_contextmenu_info">Info (shown in chat)</string>
     <string name="lobby_playerlist_contextmenu_follow">Follow</string>
     <string name="lobby_roomlistmenu_create">Create room</string>
@@ -121,6 +122,8 @@
     <string name="error_server_too_old">The server you tried to connect to is using an incompatible protocol.</string>
     <string name="error_auth_failed">Unable to authenticate for your username.</string>
     <string name="error_connection_lost">The connection to the server was lost.</string>
+    <string name="error_save_failed">Saving has failed.</string>
+    
     
     <!-- Dialogs -->
     <string name="dialog_connecting_title">Please wait</string>
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/FrontendDataUtils.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/FrontendDataUtils.java	Mon Aug 06 22:39:36 2012 +0200
@@ -26,13 +26,13 @@
 import java.util.List;
 
 import org.hedgewars.hedgeroid.R;
+import org.hedgewars.hedgeroid.StartGameActivity;
 import org.hedgewars.hedgeroid.Utils;
 import org.hedgewars.hedgeroid.Datastructures.Map.MapType;
 
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import java.nio.ByteBuffer;
 
 public class FrontendDataUtils {
 
@@ -73,16 +73,11 @@
 		return list;
 	}
 
-	public static List<Scheme> getSchemes(Context c){
-		List<Scheme> list = Scheme.getSchemes(c);
-		Collections.sort(list);
-		return list;
-	}
-
 	public static List<Weapon> getWeapons(Context c){
-		List<Weapon> list = Weapon.getWeapons(c);
-		Collections.sort(list);
-		return list;
+		// TODO stub, re-implement
+		/*List<Weapon> list = Weapon.getWeapons(c);
+		Collections.sort(list);*/
+		return Collections.emptyList();
 	}
 
 	public static ArrayList<HashMap<String, ?>> getGraves(Context c){
@@ -171,50 +166,24 @@
 		return data;
 	}
 
-	public static List<HashMap<String, Object>> getTeams(Context c){
-		List<HashMap<String, Object>> ret = new ArrayList<HashMap<String, Object>>();
-
-		File teamsDir = new File(c.getFilesDir().getAbsolutePath() + '/' + Team.DIRECTORY_TEAMS);
+	public static List<TeamFile> getTeamFiles(Context c) {
+		List<TeamFile> ret = new ArrayList<TeamFile>();
+		
+		File teamsDir = new File(c.getFilesDir(), Team.DIRECTORY_TEAMS);
 		File[] teamFileNames = teamsDir.listFiles();
 		if(teamFileNames != null){
-			for(File s : teamFileNames){
-				Team t = Team.getTeamFromXml(s.getAbsolutePath());
-				if(t != null){
-					t.file = s.getName();
-					ret.add(teamToMap(t));
+			for(File file : teamFileNames){
+				Team team = Team.load(file);
+				if(team != null){
+					ret.add(new TeamFile(team, file));
 				}
 			}
 		}
 		return ret;
 	}
 
-	public static HashMap<String, Object> teamToMap(Team t){
-		HashMap<String, Object> hashmap = new HashMap<String, Object>();
-		hashmap.put("team", t);
-		hashmap.put("txt", t.name);
-		hashmap.put("color", t.color);
-		hashmap.put("count", t.hogCount);
-		switch(t.levels[0]){
-		case 0:
-			hashmap.put("img", R.drawable.human);
-			break;
-		case 1:
-			hashmap.put("img", R.drawable.bot5);
-			break;
-		case 2:
-			hashmap.put("img", R.drawable.bot4);
-			break;
-		case 3:
-			hashmap.put("img", R.drawable.bot3);
-			break;
-		case 4:
-			hashmap.put("img", R.drawable.bot2);
-			break;
-		default:
-		case 5:
-			hashmap.put("img", R.drawable.bot1);
-			break;
-		}
-		return hashmap;
+	public static Scheme[] getSchemes(StartGameActivity startGameActivity) {
+		// TODO Auto-generated method stub
+		return null;
 	}
 }
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/GameMode.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/GameMode.java	Mon Aug 06 22:39:36 2012 +0200
@@ -20,5 +20,5 @@
 package org.hedgewars.hedgeroid.Datastructures;
 
 public enum GameMode {
-		MODE_LOCAL, MODE_DEMO, MODE_NET, MODE_SAVE
+	MODE_LOCAL, MODE_DEMO, MODE_NET, MODE_SAVE
 }
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Grave.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Grave.java	Mon Aug 06 22:39:36 2012 +0200
@@ -19,18 +19,17 @@
 
 package org.hedgewars.hedgeroid.Datastructures;
 
-public class Grave{
-
+public final class Grave{
 	public final String name;
 	public final String path;
 	
-	public Grave(String _name, String _path) {
-		name = _name;
-		path = _path;
+	public Grave(String name, String path) {
+		this.name = name;
+		this.path = path;
 	}
 
-	public String toString(){
-		return name;
+	@Override
+	public String toString() {
+		return "Grave [name=" + name + ", path=" + path + "]";
 	}
-	
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Hog.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,17 @@
+package org.hedgewars.hedgeroid.Datastructures;
+
+public final class Hog {
+	public final String name, hat;
+	public final int level;
+	
+	public Hog(String name, String hat, int level) {
+		this.name = name;
+		this.hat = hat;
+		this.level = level;
+	}
+
+	@Override
+	public String toString() {
+		return "Hog [name=" + name + ", hat=" + hat + ", level=" + level + "]";
+	}
+}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Map.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Map.java	Mon Aug 06 22:39:36 2012 +0200
@@ -19,17 +19,11 @@
 package org.hedgewars.hedgeroid.Datastructures;
 
 import java.io.File;
-import java.io.IOException;
-
-import org.hedgewars.hedgeroid.EngineProtocol.EngineProtocolNetwork;
-
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
-import android.os.Parcel;
-import android.os.Parcelable;
 
-public class Map implements Comparable<Map>, Parcelable{
+public class Map implements Comparable<Map> {
 
 	private static final String MISSION_PREFIX = "Mission: ";
 
@@ -60,10 +54,6 @@
 
 		
 	}
-	
-	public Map(Parcel in){
-		readFromParcel(in);
-	}
 
 	public String toString(){
 		switch(type){
@@ -77,10 +67,6 @@
 		}
 	}
 	
-	public void sendToEngine(EngineProtocolNetwork epn) throws IOException{
-		epn.sendToEngine(String.format("emap %s",name));
-	}
-	
 	public MapType getType(){
 		return type;
 	}
@@ -133,31 +119,4 @@
 	public enum MapType{
 		TYPE_DEFAULT, TYPE_MISSION, TYPE_GENERATED
 	}
-
-	public int describeContents() {
-		return 0;
-	}
-	
-	public void writeToParcel(Parcel dest, int flags) {
-		dest.writeString(name);
-		dest.writeString(path);
-		dest.writeString(previewPath);
-		dest.writeString(type.name());
-	}
-	
-	private void readFromParcel(Parcel src){
-		name = src.readString();
-		path = src.readString();
-		previewPath = src.readString();
-		type = MapType.valueOf(src.readString());
-	}
-	public static final Parcelable.Creator<Map> CREATOR = new Parcelable.Creator<Map>() {
-		public Map createFromParcel(Parcel source) {
-			return new Map(source);
-		}
-		public Map[] newArray(int size) {
-			return new Map[size];
-		}
-		
-	};
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/MetaScheme.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,59 @@
+package org.hedgewars.hedgeroid.Datastructures;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public final class MetaScheme {
+	public static final class Mod {
+		public final String name;
+		public final int bitmaskIndex;
+		
+		public Mod(String name, int bitmaskIndex) {
+			this.name = name;
+			this.bitmaskIndex = bitmaskIndex;
+		}
+
+		@Override
+		public String toString() {
+			return "MetaScheme$Mod [name=" + name + ", bitmaskIndex=" + bitmaskIndex + "]";
+		}
+	}
+	
+	public static final class Setting {
+		public final String name, engineCommand;
+		public final boolean maxMeansInfinity, times1000;
+		public final int min, max, def;
+		
+		public Setting(String name, String engineCommand, boolean maxMeansInfinity, boolean times1000, int min, int max, int def) {
+			this.name = name;
+			this.engineCommand = engineCommand;
+			this.maxMeansInfinity = maxMeansInfinity;
+			this.times1000 = times1000;
+			this.min = min;
+			this.max = max;
+			this.def = def;
+		}
+
+		@Override
+		public String toString() {
+			return "MetaScheme$Setting [name=" + name + ", engineCommand=" + engineCommand
+					+ ", maxMeansInfinite=" + maxMeansInfinity + ", times1000="
+					+ times1000 + ", min=" + min + ", max=" + max + ", def="
+					+ def + "]";
+		}
+	}
+	
+	public final List<Mod> mods;
+	public final List<Setting> settings;
+	
+	public MetaScheme(List<Mod> mods, List<Setting> settings) {
+		this.mods = Collections.unmodifiableList(new ArrayList<Mod>(mods));
+		this.settings = Collections.unmodifiableList(new ArrayList<Setting>(settings));
+	}
+
+	@Override
+	public String toString() {
+		return "MetaScheme [\nmods=" + mods + ", \nsettings=" + settings + "\n]";
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Player.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,14 @@
+package org.hedgewars.hedgeroid.Datastructures;
+
+public final class Player {
+	public final String name;
+	
+	public Player(String name) {
+		this.name = name;
+	}
+
+	@Override
+	public String toString() {
+		return "Player [name=" + name + "]";
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/RoomlistRoom.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,52 @@
+package org.hedgewars.hedgeroid.Datastructures;
+
+import org.hedgewars.hedgeroid.R;
+
+import android.content.res.Resources;
+
+public final class RoomlistRoom {
+	public static final String MAP_REGULAR = "+rnd+";
+	public static final String MAP_MAZE = "+maze+";
+	public static final String MAP_DRAWN = "+drawn+";
+	
+	public final String name, map, scheme, weapons, owner;
+	public final int playerCount, teamCount;
+	public final boolean inProgress;
+	
+	public RoomlistRoom(String name, String map, String scheme, String weapons,
+			String owner, int playerCount, int teamCount, boolean inProgress) {
+		this.name = name;
+		this.map = map;
+		this.scheme = scheme;
+		this.weapons = weapons;
+		this.owner = owner;
+		this.playerCount = playerCount;
+		this.teamCount = teamCount;
+		this.inProgress = inProgress;
+	}
+	
+	public static String formatMapName(Resources res, String map) {
+		if(map.charAt(0)=='+') {
+			if(map.equals(MAP_REGULAR)) {
+				return res.getString(R.string.map_regular);
+			} else if(map.equals(MAP_MAZE)) {
+				return res.getString(R.string.map_maze);
+			} else if(map.equals(MAP_DRAWN)) {
+				return res.getString(R.string.map_drawn);
+			}
+		}
+		return map;
+	}
+	
+	public String formatMapName(Resources res) {
+		return formatMapName(res, map);
+	}
+
+	@Override
+	public String toString() {
+		return "RoomlistRoom [name=" + name + ", map=" + map + ", scheme="
+				+ scheme + ", weapons=" + weapons + ", owner=" + owner
+				+ ", playerCount=" + playerCount + ", teamCount=" + teamCount
+				+ ", inProgress=" + inProgress + "]";
+	}
+}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Scheme.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Scheme.java	Mon Aug 06 22:39:36 2012 +0200
@@ -19,247 +19,37 @@
 
 package org.hedgewars.hedgeroid.Datastructures;
 
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
 import java.util.Map;
 
-import java.io.File;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.TreeMap;
-
-import org.hedgewars.hedgeroid.EngineProtocol.EngineProtocolNetwork;
-import org.ini4j.Ini;
-import org.ini4j.InvalidFileFormatException;
-import org.ini4j.Profile.Section;
-
-import android.content.Context;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-public class Scheme implements Parcelable, Comparable<Scheme>{
-	public static final String DIRECTORY_SCHEME = "schemes";
-	private static final Map<String, BasicSettingMeta> basicSettingsMeta = new TreeMap<String, BasicSettingMeta>();
-	private static final Map<String, GameModMeta> gameModsMeta = new TreeMap<String, GameModMeta>();
-
-	private final String name;
-	private final int gamemod;
-	private final Map<String, Integer> basic = new TreeMap<String, Integer>();
+public final class Scheme {
+	public final MetaScheme metascheme;
+	public final String name;
+	public final Map<String, Integer> settings;
+	public final Map<String, Boolean> mods;
 		
-	public Scheme(String _name, Map<String, Integer> _basic, int _gamemod) {
-		name = _name;
-		gamemod = _gamemod;
-		basic.putAll(_basic);
-	}
-	
-	public Scheme(Parcel in){
-		name = in.readString();
-		gamemod = in.readInt();
-		in.readMap(basic, Integer.class.getClassLoader());
-	}
-
-	public int getHealth() {
-		return basic.get("InitialHealth");
-	}
-	
-	public void sendToEngine(EngineProtocolNetwork epn) throws IOException{ 
-		epn.sendToEngine(String.format("e$gmflags %d", gamemod));
-
-		for(Map.Entry<String, Integer> entry : basic.entrySet()) {
-			BasicSettingMeta basicflag = basicSettingsMeta.get(entry.getKey());
-			
-			//Health is a special case, it doesn't need to be send 				                             
-			//to the engine yet, we'll do that with the other HH info
-			if(!basicflag.command.equals("inithealth")){
-				epn.sendToEngine(String.format("%s %d", basicflag.command, entry.getValue()));
-			}
-		}
+	public Scheme(MetaScheme metascheme, String name, Map<String, Integer> settings, Map<String, Boolean> mods) {
+		this.metascheme = metascheme;
+		this.name = name;
+		this.settings = Collections.unmodifiableMap(new HashMap<String, Integer>(settings));
+		this.mods = Collections.unmodifiableMap(new HashMap<String, Boolean>(mods));
 	}
 	
-	public String toString(){
-		return name;
-	}
-
-	public static List<Scheme> getSchemes(Context c) throws IllegalArgumentException {
-		File schemeDir = new File(c.getFilesDir(), DIRECTORY_SCHEME);
-		File[] files = schemeDir.listFiles(new FilenameFilter() {
-			public boolean accept(File dir, String filename) {
-				return filename.toLowerCase().startsWith("scheme_");
-			}
-		});
-		if(files == null) files = new File[0];
-		Arrays.sort(files);
-		List<Scheme> schemes = new ArrayList<Scheme>();
-
-		for(File file : files) {
-			try {
-				Ini ini = new Ini(file);
-				
-				String name = ini.get("Scheme", "name");
-				if(name==null) {
-					name = file.getName();
-				}
-				Section basicSettingsSection = ini.get("BasicSettings");
-				Section gameModsSection = ini.get("GameMods");
-				if(basicSettingsSection == null || gameModsSection == null) {
-					Log.e(Scheme.class.getCanonicalName(), "Scheme file "+file+" is missing the BasicSettings or GameMods section - skipping.");
-					continue;
-				}
-				
-				Map<String, Integer> basicSettings = new TreeMap<String, Integer>();
-				for(Entry<String, BasicSettingMeta> entry : basicSettingsMeta.entrySet()) {
-					String key = entry.getKey();
-					BasicSettingMeta settingMeta = entry.getValue();
-					Integer value = null;
-					if(basicSettingsSection.containsKey(key)) {
-						try {
-							value = Integer.valueOf(basicSettingsSection.get(key));						
-						} catch (NumberFormatException e) {
-							// ignore
-						}
-					}
-					
-					if(value==null) {
-						Log.w(Scheme.class.getCanonicalName(), "Scheme file "+file+" setting "+key+" is missing or invalid, using default.");
-						value = settingMeta.def;
-					}
-					
-					if(settingMeta.checkOverMax) {
-						value = Math.min(value, settingMeta.max);
-					}
-					if(settingMeta.times1000) {
-						value *= 1000;
-					}
-					
-					basicSettings.put(key, value);						
-				}
-				
-				int gamemods = 0;
-				for(Entry<String, GameModMeta> entry : gameModsMeta.entrySet()) {
-					String key = entry.getKey();
-					GameModMeta modMeta = entry.getValue();
-					if(Boolean.parseBoolean(gameModsSection.get(key))) {
-						gamemods |= (1 << modMeta.bitmaskIndex);
-					}
-				}
-				
-				schemes.add(new Scheme(name, basicSettings, gamemods));
-			} catch (InvalidFileFormatException e) {
-				throw new RuntimeException(e);
-			} catch (IOException e) {
-				throw new RuntimeException(e);
-			}
-		}
-		return schemes;
-	}
-	
-	/**
-	 * This method will parse the basic flags from a prespecified ini file.
-	 * In the future we could use one provided by the Data folder.
-	 */
-	public static void parseConfiguration(Context c) {
-		File schemeDir = new File(c.getFilesDir(), DIRECTORY_SCHEME);
-		File settingsFile = new File(schemeDir, "basicsettings");
-		File gameModsFile = new File(schemeDir, "gamemods");
-		
-		try {
-			Ini ini = new Ini(settingsFile);
-			for(Entry<String, Section> sectionEntry : ini.entrySet()) {
-				basicSettingsMeta.put(sectionEntry.getKey(), new BasicSettingMeta(sectionEntry.getValue()));
-			}
-			
-			ini = new Ini(gameModsFile);
-			for(Entry<String, Section> sectionEntry : ini.entrySet()) {
-				gameModsMeta.put(sectionEntry.getKey(), new GameModMeta(sectionEntry.getValue()));
-			}
-		} catch (InvalidFileFormatException e) {
-			throw new RuntimeException(e);
-		} catch (IOException e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-	public int describeContents() {
-		return 0;
-	}
-
-	public void writeToParcel(Parcel dest, int flags) {
-		dest.writeString(name);
-		dest.writeInt(gamemod);
-		dest.writeMap(basic);
-	}
-
-	public static final Parcelable.Creator<Scheme> CREATOR = new Parcelable.Creator<Scheme>() {
-		public Scheme createFromParcel(Parcel source) {
-			return new Scheme(source);
-		}
-		public Scheme[] newArray(int size) {
-			return new Scheme[size];
-		}
-		
-	};
-
-	public int compareTo(Scheme another) {
-		return name.compareTo(another.name);
-	}
-}
-
-class BasicSettingMeta {
-	final String command;
-	final String title;
-	final int def;
-	final int min;
-	final int max;
-	final boolean times1000;
-	final boolean checkOverMax;
-	
-	public BasicSettingMeta(Ini.Section section) {
-		command = getRequired(section, "command");
-		title = section.get("title", "");
-		def = Integer.parseInt(getRequired(section, "default"));
-		min = Integer.parseInt(getRequired(section, "min"));
-		max = Integer.parseInt(getRequired(section, "max"));
-		times1000 = Boolean.parseBoolean(section.get("times1000", "false"));
-		checkOverMax = Boolean.parseBoolean(section.get("checkOverMax", "false"));
-	}
-	
-	private String getRequired(Ini.Section section, String key) {
-		String result = section.get(key);
-		if(result==null) {
-			throw new IllegalArgumentException("basicsettings.ini, section "+section.getName()+" is missing required setting "+key+".");
-		}
-		return result;
+	public int getHealth() {
+		return settings.get("health");
 	}
 
 	@Override
 	public String toString() {
-		return String
-				.format("BasicSettingMeta [command=%s, title=%s, def=%s, min=%s, max=%s, times1000=%s, checkOverMax=%s]",
-						command, title, def, min, max, times1000, checkOverMax);
-	}
-}
-
-// TODO: Extend with additional metadata
-class GameModMeta {
-	final int bitmaskIndex;
-	
-	public GameModMeta(Ini.Section section) {
-		bitmaskIndex = Integer.parseInt(getRequired(section, "bitmaskIndex"));
+		return "Scheme [metascheme=" + metascheme + ", name=" + name
+				+ ", settings=" + settings + ", mods=" + mods + "]";
 	}
 	
-	private String getRequired(Ini.Section section, String key) {
-		String result = section.get(key);
-		if(result==null) {
-			throw new IllegalArgumentException("gamemods.ini, section "+section.getName()+" is missing required setting "+key+".");
+	public static final Comparator<Scheme> caseInsensitiveNameComparator = new Comparator<Scheme>() {
+		public int compare(Scheme lhs, Scheme rhs) {
+			return lhs.name.compareToIgnoreCase(rhs.name);
 		}
-		return result;
-	}
-
-	@Override
-	public String toString() {
-		return String.format("GameModMeta [bitmaskIndex=%s]", bitmaskIndex);
-	}
+	};
 }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Schemes.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,82 @@
+package org.hedgewars.hedgeroid.Datastructures;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.hedgewars.hedgeroid.Utils;
+import org.hedgewars.hedgeroid.frontlib.Flib;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.MetaschemePtr;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.SchemelistPtr;
+
+import android.content.Context;
+
+/**
+ * Functions for handling the persistent list of schemes.
+ * Schemes in that list are identified by name (case sensitive).
+ */
+public final class Schemes {
+	private Schemes() {
+		throw new AssertionError("This class is not meant to be instantiated");
+	}
+	
+	public static File getUserSchemesFile(Context c) {
+		return new File(c.getFilesDir(), "schemes_user.ini");
+	}
+	
+	public static File getBuiltinSchemesFile(Context c) {
+		return new File(c.getFilesDir(), "schemes_builtin.ini");
+	}
+	
+	public static Map<String, Scheme> loadUserSchemes(Context c) throws IOException {
+		return loadSchemes(c, getUserSchemesFile(c));
+	}
+	
+	public static Map<String, Scheme> loadBuiltinSchemes(Context c) throws IOException {
+		return loadSchemes(c, getBuiltinSchemesFile(c));
+	}
+	
+	public static Map<String, Scheme> loadSchemes(Context c, File schemeFile) throws IOException {
+		Map<String, Scheme> result = new TreeMap<String, Scheme>();
+		String metaschemePath = new File(Utils.getDataPathFile(c), "metasettings.ini").getAbsolutePath();
+		if(!schemeFile.isFile()) {
+			// No schemes file == no schemes, no error
+			return new TreeMap<String, Scheme>();
+		}
+		MetaschemePtr meta = null;
+		SchemelistPtr schemeListPtr = null;
+		try {
+			meta = Flib.INSTANCE.flib_metascheme_from_ini(metaschemePath);
+			if(meta==null) {
+				throw new IOException("Unable to read metascheme");
+			}
+			schemeListPtr = Flib.INSTANCE.flib_schemelist_from_ini(meta, schemeFile.getAbsolutePath());
+			if(schemeListPtr == null) {
+				throw new IOException("Unable to read schemelist");
+			}
+			List<Scheme> schemeList = schemeListPtr.deref();
+			for(Scheme scheme : schemeList) {
+				result.put(scheme.name, scheme);
+			}
+			return result;
+		} finally {
+			if(schemeListPtr != null) {
+				Flib.INSTANCE.flib_schemelist_destroy(schemeListPtr);
+			}
+			if(meta != null) {
+				Flib.INSTANCE.flib_metascheme_release(meta);
+			}
+		}
+	}
+	
+	public static void saveUserSchemes(Context c, Map<String, Scheme> schemes) throws IOException {
+		List<Scheme> schemeList = new ArrayList<Scheme>(schemes.values());
+		Collections.sort(schemeList, Scheme.caseInsensitiveNameComparator);
+		SchemelistPtr ptr = SchemelistPtr.createJavaOwned(schemeList);
+		Flib.INSTANCE.flib_schemelist_to_ini(getUserSchemesFile(c).getAbsolutePath(), ptr);
+	}
+}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Team.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Team.java	Mon Aug 06 22:39:36 2012 +0200
@@ -18,365 +18,62 @@
 
 package org.hedgewars.hedgeroid.Datastructures;
 
-import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
 import java.io.IOException;
-import java.io.OutputStream;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
-import org.hedgewars.hedgeroid.EngineProtocol.EngineProtocolNetwork;
 import org.hedgewars.hedgeroid.EngineProtocol.PascalExports;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
-import org.xmlpull.v1.XmlSerializer;
+import org.hedgewars.hedgeroid.frontlib.Flib;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.TeamPtr;
 
-import android.content.Context;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Xml;
+import android.util.Log;
 
-public class Team implements Parcelable{
-
+public final class Team {
 	public static final String DIRECTORY_TEAMS = "teams";
-	private static final Integer[] TEAM_COLORS = {
-		0xd12b42, /* red    */ 
-		0x4980c1, /* blue   */ 
-		0x6ab530, /* green  */ 
-		0xbc64c4, /* purple */ 
-		0xe76d14, /* orange */ 
-		0x3fb6e6, /* cyan   */ 
-		0xe3e90c, /* yellow */ 
-		0x61d4ac, /* mint   */ 
-		0xf1c3e1, /* pink   */ 
-		/* add new colors here */
-	};
 
-//	private static final Integer[] TEAM_COLORS = {
-//		0xff0000, /* red    */ 
-//		0x00ff00, /* blue   */ 
-//		0x0000ff, /* green  */ 
-//	};
+	public static final int maxNumberOfHogs = PascalExports.HWgetMaxNumberOfHogs();
+	public static final int maxNumberOfTeams = PascalExports.HWgetMaxNumberOfTeams();
+
+	public final String name, grave, flag, voice, fort;
+	public final List<Hog> hogs;
 
-	private static final int STATE_START = 0;
-	private static final int STATE_ROOT = 1;
-	private static final int STATE_HOG_ROOT = 2;
-
-	public String name, grave, flag, voice, fort, hash;
-	public String file = null;
-
-	public static int maxNumberOfHogs = 0;
-	public static int maxNumberOfTeams = 0;
-
-	static{
-		maxNumberOfHogs = PascalExports.HWgetMaxNumberOfHogs();
-		maxNumberOfTeams = PascalExports.HWgetMaxNumberOfTeams();
-	}
-	public String[] hats = new String[maxNumberOfHogs];
-	public String[] hogNames = new String[maxNumberOfHogs];
-	public int[] levels = new int[maxNumberOfHogs];
-
-	public int hogCount = 4;
-	public int color = TEAM_COLORS[0];
-
-	public Team(){
+	public Team(String name, String grave, String flag, String voice, String fort, List<Hog> hogs) {
+		if(hogs.size() != maxNumberOfHogs) {
+			throw new IllegalArgumentException("A team must consist of "+maxNumberOfHogs+" hogs.");
+		}
+		this.name = name;
+		this.grave = grave;
+		this.flag = flag;
+		this.voice = voice;
+		this.fort = fort;
+		this.hogs = Collections.unmodifiableList(new ArrayList<Hog>(hogs));
 	}
 
-	public Team(Parcel in){
-		readFromParcel(in);
-	}
-
-	@Override
-	public boolean equals(Object o){
-		if(super.equals(o)) return true;
-		else if(o instanceof Team){
-			Team t = (Team)o;
-			boolean ret = name.equals(t.name);
-			ret &= grave.equals(t.grave);
-			ret &= flag.equals(t.flag);
-			ret &= voice.equals(t.voice);
-			ret &= fort.equals(t.fort);
-			ret &= hash.equals(t.hash);
-			return ret;
-		}else{
-			return false;
-		}
-	}
-	
-	@Override
-	public int hashCode() {
-		final int prime = 31;
-		int result = 1;
-		result = prime * result + ((name == null) ? 0 : name.hashCode());
-		result = prime * result + ((grave == null) ? 0 : grave.hashCode());
-		result = prime * result + ((flag == null) ? 0 : flag.hashCode());
-		result = prime * result + ((voice == null) ? 0 : voice.hashCode());
-		result = prime * result + ((fort == null) ? 0 : fort.hashCode());
-		result = prime * result + ((hash == null) ? 0 : hash.hashCode());
-		return result;
-	}
-
-	public void setRandomColor(int[] illegalcolors){
-		Integer[] colorsToPickFrom = TEAM_COLORS;
-		if(illegalcolors != null){
-			ArrayList<Integer> colors = new ArrayList<Integer>();
-			for(int color : TEAM_COLORS){
-				boolean validColor = true;
-				for(int illegal : illegalcolors){
-					if(color == illegal) validColor = false;
-				}
-				if(validColor) colors.add(color);
-			}
-			if(colors.size() != 0) colorsToPickFrom = colors.toArray(new Integer[1]);
-		}
-		int index = (int)Math.round(Math.random()*(colorsToPickFrom.length-1));
-		color = colorsToPickFrom[index];
-	}
-
-
-	public void sendToEngine(EngineProtocolNetwork epn, int hogCount, int health) throws IOException{
-		epn.sendToEngine(String.format("eaddteam %s %d %s", hash, color, name));
-		epn.sendToEngine(String.format("egrave %s", grave));
-		epn.sendToEngine(String.format("efort %s", fort));
-		epn.sendToEngine(String.format("evoicepack %s", voice));
-		epn.sendToEngine(String.format("eflag %s", flag));
-
-		for(int i = 0; i < hogCount; i++){
-			epn.sendToEngine(String.format("eaddhh %d %d %s", levels[i], health, hogNames[i]));
-			epn.sendToEngine(String.format("ehat %s", hats[i]));
+	public void save(File f) throws IOException {
+		Log.d("Team", "saving to "+f.getAbsolutePath());
+		TeamPtr teamPtr = TeamPtr.createJavaOwned(this);
+		if(Flib.INSTANCE.flib_team_to_ini(f.getAbsolutePath(), teamPtr) != 0) {
+			throw new IOException("Error saving team "+name);
 		}
 	}
 
-	public void setFileName(Context c){
-		if(file == null){
-		  	file = validFileName(c, name);
-		}
-	}
-	private String validFileName(Context c, String fileName){
-		String absolutePath = String.format("%s/%s", c.getFilesDir(), fileName);
-		File f = new File(absolutePath);
-		if(f.exists()){
-			String newFileName = fileName + (int)(Math.random()*10);
-			return validFileName(c, newFileName);
-		}else{
-			return fileName;
+	public static Team load(File f) {
+		TeamPtr teamPtr = Flib.INSTANCE.flib_team_from_ini(f.getAbsolutePath());
+		if(teamPtr != null) {
+			Team team = teamPtr.deref().team;
+			Flib.INSTANCE.flib_team_destroy(teamPtr);
+			return team;
+		} else {
+			return null;
 		}
 	}
-	
-	/*
-	 * XML METHODS
-	 */
-
-	/**
-	 * Read the xml file path and convert it to a Team object
-	 * @param path absolute path to the xml file
-	 * @return
-	 */
-	public static Team getTeamFromXml(String path){
-		try {
-			XmlPullParserFactory xmlPullFactory = XmlPullParserFactory.newInstance();
-			XmlPullParser xmlPuller = xmlPullFactory.newPullParser();
-
-			BufferedReader br = new BufferedReader(new FileReader(path), 1024);
-			xmlPuller.setInput(br);
-			Team team = new Team();
-			int hogCounter = 0;
-
-			int eventType = xmlPuller.getEventType();
-			int state = STATE_START;
-			while(eventType != XmlPullParser.END_DOCUMENT){
-				switch(state){
-				case STATE_START:
-					if(eventType == XmlPullParser.START_TAG && xmlPuller.getName().equals("team")) state = STATE_ROOT;
-					else if(eventType != XmlPullParser.START_DOCUMENT) throwException(path, eventType);
-					break;
-				case STATE_ROOT:
-					if(eventType == XmlPullParser.START_TAG){
-						if(xmlPuller.getName().toLowerCase().equals("name")){
-							team.name = getXmlText(xmlPuller, "name");
-						}else if(xmlPuller.getName().toLowerCase().equals("flag")){
-							team.flag= getXmlText(xmlPuller, "flag");
-						}else if(xmlPuller.getName().toLowerCase().equals("voice")){
-							team.voice = getXmlText(xmlPuller, "voice");
-						}else if(xmlPuller.getName().toLowerCase().equals("grave")){
-							team.grave = getXmlText(xmlPuller, "grave");
-						}else if(xmlPuller.getName().toLowerCase().equals("fort")){
-							team.fort = getXmlText(xmlPuller, "fort");
-						}else if(xmlPuller.getName().toLowerCase().equals("hash")){
-							team.hash = getXmlText(xmlPuller, "hash");
-						}else if(xmlPuller.getName().toLowerCase().equals("hog")){
-							state = STATE_HOG_ROOT;
-						}else throwException(xmlPuller.getName(), eventType);
-					}else if(eventType == XmlPullParser.END_TAG) state = STATE_START;
-					else throwException(xmlPuller.getText(), eventType);
-					break;
-				case STATE_HOG_ROOT:
-					if(eventType == XmlPullParser.START_TAG){
-						if(xmlPuller.getName().toLowerCase().equals("name")){
-							team.hogNames[hogCounter] = getXmlText(xmlPuller, "name");
-						}else if(xmlPuller.getName().toLowerCase().equals("hat")){
-							team.hats[hogCounter] = getXmlText(xmlPuller, "hat");
-						}else if(xmlPuller.getName().toLowerCase().equals("level")){
-							team.levels[hogCounter] = Integer.parseInt(getXmlText(xmlPuller, "level"));
-						}else throwException(xmlPuller.getText(), eventType);
-					}else if(eventType == XmlPullParser.END_TAG){
-						hogCounter++;
-						state = STATE_ROOT;
-					}else throwException(xmlPuller.getText(), eventType);
-					break;
-				}
-				eventType = getEventType(xmlPuller);
-			}//end while(eventtype != END_DOCUMENT
-			return team;
-		} catch (NumberFormatException e){
-			e.printStackTrace();
-		} catch (XmlPullParserException e) {
-			e.printStackTrace();
-		} catch (FileNotFoundException e) {
-			e.printStackTrace();
-		} catch (IOException e) {
-			e.printStackTrace();
-		}
-		return null;
-	}
-
-	private static String getXmlText(XmlPullParser xmlPuller, String parentTag)throws XmlPullParserException, IOException{
-		if(getEventType(xmlPuller) == XmlPullParser.TEXT){
-			String txt = xmlPuller.getText();
-			if(getEventType(xmlPuller) == XmlPullParser.END_TAG && xmlPuller.getName().toLowerCase().equals(parentTag)){
-				return txt;
-			}
-		}
-		throw new XmlPullParserException("malformed xml file on string read from tag: " + parentTag);
-	}
-
-	/**
-	 * Skips whitespaces..
-	 */
-	private static int getEventType(XmlPullParser xmlPuller)throws XmlPullParserException, IOException{
-		int eventType = xmlPuller.next();
-		while(eventType == XmlPullParser.TEXT && xmlPuller.isWhitespace()){
-			eventType = xmlPuller.next();
-		}
-		return eventType;
-	}
 
-	private static void throwException(String file, int eventType){
-		throw new IllegalArgumentException(String.format("Xml file: %s malformed with error: %d.", file, eventType));
-	}
-
-	public void writeToXml(OutputStream os){
-		XmlSerializer serializer = Xml.newSerializer();
-		try{
-			serializer.setOutput(os, "UTF-8");	
-			serializer.startDocument("UTF-8", true);
-			serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
-
-			serializer.startTag(null, "team");
-			serializer.startTag(null, "name");
-			serializer.text(name);
-			serializer.endTag(null, "name");
-			serializer.startTag(null, "flag");
-			serializer.text(flag);
-			serializer.endTag(null, "flag");
-			serializer.startTag(null, "fort");
-			serializer.text(fort);
-			serializer.endTag(null, "fort");
-			serializer.startTag(null, "grave");
-			serializer.text(grave);
-			serializer.endTag(null, "grave");
-			serializer.startTag(null, "voice");
-			serializer.text(voice);
-			serializer.endTag(null, "voice");
-			serializer.startTag(null, "hash");
-			serializer.text(hash);
-			serializer.endTag(null, "hash");
-
-			for(int i = 0; i < maxNumberOfHogs; i++){
-				serializer.startTag(null, "hog");
-				serializer.startTag(null, "name");
-				serializer.text(hogNames[i]);
-				serializer.endTag(null, "name");
-				serializer.startTag(null, "hat");
-				serializer.text(hats[i]);
-				serializer.endTag(null, "hat");
-				serializer.startTag(null, "level");
-				serializer.text(String.valueOf(levels[i]));
-				serializer.endTag(null, "level");
-
-				serializer.endTag(null, "hog");
-			}
-			serializer.endTag(null, "team");
-			serializer.endDocument();
-			serializer.flush();
-
-		} catch (IOException e) {
-			e.printStackTrace();
-		}finally{
-			try {
-				os.close();
-			} catch (IOException e) {}
-		}
+	@Override
+	public String toString() {
+		return "Team [name=" + name + ", grave=" + grave + ", flag=" + flag
+				+ ", voice=" + voice + ", fort=" + fort + ", hogs=" + hogs
+				+ "]";
 	}
-	/*
-	 * END XML METHODS
-	 */
-
-
-
-	/*
-	 * PARCABLE METHODS
-	 */
-
-	public int describeContents() {
-		return 0;
-	}
-
-	public void writeToParcel(Parcel dest, int flags) {
-		dest.writeString(name);
-		dest.writeString(grave);
-		dest.writeString(flag);
-		dest.writeString(voice);
-		dest.writeString(fort);
-		dest.writeString(hash);
-		dest.writeStringArray(hats);
-		dest.writeStringArray(hogNames);
-		dest.writeIntArray(levels);
-		dest.writeInt(color);
-		dest.writeInt(hogCount);
-		dest.writeString(file);
-	}
-
-
-	public void readFromParcel(Parcel src){
-		name = src.readString();
-		grave = src.readString();
-		flag = src.readString();
-		voice = src.readString();
-		fort = src.readString();
-		hash = src.readString();
-		src.readStringArray(hats);
-		src.readStringArray(hogNames);
-		src.readIntArray(levels);
-		color = src.readInt();
-		hogCount = src.readInt();
-		file = src.readString();
-	}
-
-	public static final Parcelable.Creator<Team> CREATOR = new Parcelable.Creator<Team>() {
-		public Team createFromParcel(Parcel source) {
-			return new Team(source);
-		}
-		public Team[] newArray(int size) {
-			return new Team[size];
-		}
-
-	};
-
-	/*
-	 * END PARCABLE METHODS
-	 */
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/TeamFile.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,18 @@
+package org.hedgewars.hedgeroid.Datastructures;
+
+import java.io.File;
+
+public final class TeamFile {
+	public final Team team;
+	public final File file;
+	
+	public TeamFile(Team team, File file) {
+		this.team = team;
+		this.file = file;
+	}
+
+	@Override
+	public String toString() {
+		return "TeamFile [team=" + team + ", file=" + file + "]";
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/TeamInGame.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,15 @@
+package org.hedgewars.hedgeroid.Datastructures;
+
+public final class TeamInGame {
+	public final Team team;
+	public final TeamIngameAttributes ingameAttribs;
+	
+	public TeamInGame(Team team, TeamIngameAttributes ingameAttribs) {
+		this.team = team;
+		this.ingameAttribs = ingameAttribs;
+	}
+	
+	public TeamInGame withAttribs(TeamIngameAttributes attribs) {
+		return new TeamInGame(team, attribs);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/TeamIngameAttributes.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,61 @@
+package org.hedgewars.hedgeroid.Datastructures;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+public final class TeamIngameAttributes {
+	public static final int[] TEAM_COLORS = {
+		0xd12b42, /* red    */ 
+		0x4980c1, /* blue   */ 
+		0x6ab530, /* green  */ 
+		0xbc64c4, /* purple */ 
+		0xe76d14, /* orange */ 
+		0x3fb6e6, /* cyan   */ 
+		0xe3e90c, /* yellow */ 
+		0x61d4ac, /* mint   */ 
+		0xf1c3e1, /* pink   */ 
+		/* add new colors here */
+	};
+	
+	public final String ownerName;
+	public final int colorIndex, hogCount;
+	public final boolean remoteDriven;
+	
+	public TeamIngameAttributes(String ownerName, int colorIndex, int hogCount, boolean remoteDriven) {
+		this.ownerName = ownerName;
+		this.colorIndex = colorIndex;
+		this.hogCount = hogCount;
+		this.remoteDriven = remoteDriven;
+	}
+	
+	public static int randomColorIndex(int[] illegalColors){
+		Random rnd = new Random();
+		ArrayList<Integer> legalcolors = new ArrayList<Integer>();
+		for(int i=0; i<TEAM_COLORS.length; i++) {
+			legalcolors.add(i);
+		}
+		for(int illegalColor : illegalColors) {
+			legalcolors.remove(Integer.valueOf(illegalColor));
+		}
+		if(legalcolors.isEmpty()) {
+			return rnd.nextInt(TEAM_COLORS.length);
+		} else {
+			return legalcolors.get(rnd.nextInt(legalcolors.size()));
+		}
+	}
+	
+	public TeamIngameAttributes withColorIndex(int colorIndex) {
+		return new TeamIngameAttributes(ownerName, colorIndex, hogCount, remoteDriven);
+	}
+	
+	public TeamIngameAttributes withHogCount(int hogCount) {
+		return new TeamIngameAttributes(ownerName, colorIndex, hogCount, remoteDriven);
+	}
+
+	@Override
+	public String toString() {
+		return "TeamIngameAttributes [ownerName=" + ownerName + ", colorIndex="
+				+ colorIndex + ", hogCount=" + hogCount + ", remoteDriven="
+				+ remoteDriven + "]";
+	}
+}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Weapon.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Weapon.java	Mon Aug 06 22:39:36 2012 +0200
@@ -18,37 +18,17 @@
 
 package org.hedgewars.hedgeroid.Datastructures;
 
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.ArrayList;
+import org.hedgewars.hedgeroid.EngineProtocol.PascalExports;
 
-import org.hedgewars.hedgeroid.EngineProtocol.EngineProtocolNetwork;
-import org.hedgewars.hedgeroid.EngineProtocol.PascalExports;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
-
-import android.content.Context;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-public class Weapon implements Parcelable, Comparable<Weapon>{
-
+public class Weapon implements Comparable<Weapon>{
 	public static final String DIRECTORY_WEAPON = "weapons";
+	public static final int maxWeapons = PascalExports.HWgetNumberOfWeapons();
 	
 	private String name;
 	private String QT;
 	private String prob;
 	private String delay;
 	private String crate;
-	private static int maxWeapons;
-	
-	static{
-		maxWeapons = PascalExports.HWgetNumberOfWeapons();
-	}
 	
 	public Weapon(String _name, String _QT, String _prob, String _delay, String _crate){
 		name = _name;
@@ -65,154 +45,11 @@
 		crate = String.format("e%s %s%s", "ammreinf", _crate, sb);
 	}
 	
-	public Weapon(Parcel in){
-		readFromParcel(in);
-	}
-	
 	public String toString(){
 		return name;
 	}
-	
-	public void sendToEngine(EngineProtocolNetwork epn, int teamsCount) throws IOException{
-		epn.sendToEngine(QT);//command prefix is already in string 
-		epn.sendToEngine(prob);
-		epn.sendToEngine(delay);
-		epn.sendToEngine(crate);
 		
-		for(int i = 0; i < teamsCount; i++){
-			epn.sendToEngine("eammstore");
-		}
-	}
-	
-	public static final int STATE_START = 0;
-	public static final int STATE_ROOT = 1;
-	public static final int STATE_NAME = 2;
-	public static final int STATE_QT = 3;
-	public static final int STATE_PROBABILITY = 4;
-	public static final int STATE_DELAY = 5;
-	public static final int STATE_CRATE = 6;
-	
-	public static ArrayList<Weapon> getWeapons(Context c) throws IllegalArgumentException{
-		String dir = c.getFilesDir().getAbsolutePath() + '/' + DIRECTORY_WEAPON + '/';
-		String[] files = new File(dir).list();
-		if(files == null) files = new String[]{};
-		
-		ArrayList<Weapon> weapons = new ArrayList<Weapon>();
-
-		try {
-			XmlPullParserFactory xmlPullFactory = XmlPullParserFactory.newInstance();
-			XmlPullParser xmlPuller = xmlPullFactory.newPullParser();
-			
-			for(String file : files){
-				BufferedReader br = new BufferedReader(new FileReader(dir + file), 1024);
-				xmlPuller.setInput(br);
-				String name = null;
-				String qt = null;
-				String prob = null;
-				String delay = null;
-				String crate = null;
-				
-				int eventType = xmlPuller.getEventType();
-				int state = STATE_START;
-				while(eventType != XmlPullParser.END_DOCUMENT){
-					switch(state){
-					case STATE_START:
-						if(eventType == XmlPullParser.START_TAG && xmlPuller.getName().equals("weapon")) state = STATE_ROOT;
-						else if(eventType != XmlPullParser.START_DOCUMENT) throwException(file, eventType);
-						break;
-					case STATE_ROOT:
-						if(eventType == XmlPullParser.START_TAG){
-							if(xmlPuller.getName().toLowerCase().equals("qt")) state = STATE_QT;
-							else if(xmlPuller.getName().toLowerCase().equals("name")) state = STATE_NAME;
-							else if(xmlPuller.getName().toLowerCase().equals("probability")) state = STATE_PROBABILITY;
-							else if(xmlPuller.getName().toLowerCase().equals("delay")) state = STATE_DELAY;
-							else if(xmlPuller.getName().toLowerCase().equals("crate")) state = STATE_CRATE;
-							else throwException(file, eventType);
-						}else if(eventType == XmlPullParser.END_TAG) state = STATE_START;
-						else throwException(xmlPuller.getText(), eventType);
-						break;
-					case STATE_NAME:
-						if(eventType == XmlPullParser.TEXT) name = xmlPuller.getText().trim();
-						else if(eventType == XmlPullParser.END_TAG) state = STATE_ROOT;
-						else throwException(file, eventType);
-						break;
-					case STATE_QT:
-						if(eventType == XmlPullParser.TEXT) qt = xmlPuller.getText().trim();
-						else if(eventType == XmlPullParser.END_TAG) state = STATE_ROOT;
-						else throwException(file, eventType);
-						break;
-					case STATE_PROBABILITY:
-						if(eventType == XmlPullParser.TEXT) prob = xmlPuller.getText().trim();
-						else if(eventType == XmlPullParser.END_TAG) state = STATE_ROOT;
-						else throwException(file, eventType);
-						break;
-					case STATE_DELAY:
-						if(eventType == XmlPullParser.TEXT) delay = xmlPuller.getText().trim();
-						else if(eventType == XmlPullParser.END_TAG) state = STATE_ROOT;
-						else throwException(file, eventType);
-						break;
-					case STATE_CRATE:
-						if(eventType == XmlPullParser.TEXT) crate = xmlPuller.getText().trim();
-						else if(eventType == XmlPullParser.END_TAG) state = STATE_ROOT;
-						else throwException(file, eventType);
-						break;
-					}
-					eventType = xmlPuller.next();
-					while(eventType == XmlPullParser.TEXT && xmlPuller.isWhitespace()){//Skip whitespaces
-						eventType = xmlPuller.next();
-					}
-				}//end while(eventtype != END_DOCUMENT
-				weapons.add(new Weapon(name, qt, prob, delay, crate));
-			}//end for(string file : files
-			return weapons;
-			
-		} catch (XmlPullParserException e) {
-			e.printStackTrace();
-		} catch (FileNotFoundException e) {
-			e.printStackTrace();
-		} catch (IOException e) {
-			e.printStackTrace();
-		}
-		return new ArrayList<Weapon>();//TODO handle correctly
-	}
-	
-	private static void throwException(String file, int eventType){
-		throw new IllegalArgumentException(String.format("Xml file: %s malformed with eventType: %d.", file, eventType));
-	}
-
-	public int describeContents() {
-		return 0;
-	}
-
-	public void writeToParcel(Parcel dest, int flags) {
-		dest.writeString(name);
-		dest.writeString(QT);
-		dest.writeString(prob);
-		dest.writeString(delay);
-		dest.writeString(crate);
-	}
-	
-	private void readFromParcel(Parcel src){
-		name = src.readString();
-		QT = src.readString();
-		prob = src.readString();
-		delay = src.readString();
-		crate = src.readString();
-	}
-	
-	public static final Parcelable.Creator<Weapon> CREATOR = new Parcelable.Creator<Weapon>() {
-		public Weapon createFromParcel(Parcel source) {
-			return new Weapon(source);
-		}
-		public Weapon[] newArray(int size) {
-			return new Weapon[size];
-		}
-		
-	};
-
 	public int compareTo(Weapon another) {
 		return name.compareTo(another.name);
 	}
-	
-	
 }
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadAssets.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadAssets.java	Mon Aug 06 22:39:36 2012 +0200
@@ -8,6 +8,7 @@
 import org.hedgewars.hedgeroid.R;
 import org.hedgewars.hedgeroid.Utils;
 import org.hedgewars.hedgeroid.Datastructures.Scheme;
+import org.hedgewars.hedgeroid.Datastructures.Schemes;
 import org.hedgewars.hedgeroid.Datastructures.Team;
 import org.hedgewars.hedgeroid.Datastructures.Weapon;
 
@@ -44,7 +45,7 @@
 	@Override
 	protected Boolean doInBackground(Object... params) {
 		try {
-			Utils.resRawToFilesDir(act, R.array.schemes, Scheme.DIRECTORY_SCHEME);
+			Utils.writeStreamToFile(act.getResources().openRawResource(R.raw.schemes_builtin), Schemes.getBuiltinSchemesFile(act));
 			Utils.resRawToFilesDir(act, R.array.weapons, Weapon.DIRECTORY_WEAPON);
 			Utils.resRawToFilesDir(act, R.array.teams, Team.DIRECTORY_TEAMS);
 			copyFileOrDir(act.getAssets(), Utils.getDataPathFile(act), "Data");
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/EngineProtocol/EngineProtocolNetwork.java	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +0,0 @@
-/*
- * Hedgewars for Android. An Android port of Hedgewars, a free turn based strategy game
- * Copyright (c) 2011-2012 Richard Deurwaarder <xeli@xelification.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-
-package org.hedgewars.hedgeroid.EngineProtocol;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.UnknownHostException;
-
-public class EngineProtocolNetwork extends Thread {
-
-	public static final String GAMEMODE_LOCAL = "TL";
-	public static final String GAMEMODE_DEMO = "TD";
-	public static final String GAMEMODE_NET = "TN";
-	public static final String GAMEMODE_SAVE = "TS";
-	
-	public static final int BUFFER_SIZE = 255; //From iOS code which got it from the origional frontend
-	
-	public static final int MODE_GENLANDPREVIEW = 0;
-	public static final int MODE_GAME = 1;
-
-	private ServerSocket serverSocket;
-	private InputStream input;
-	private OutputStream output;
-	public int port;
-	private final GameConfig config;
-	private boolean clientQuit = false;
-
-	public EngineProtocolNetwork(GameConfig _config){
-		config = _config;
-		try {
-			serverSocket = new ServerSocket(0);
-			port = serverSocket.getLocalPort();
-			Thread ipcThread = new Thread(this, "IPC - Thread");			
-			ipcThread.start();
-		} catch (UnknownHostException e) {
-			e.printStackTrace();
-		} catch (IOException e) {
-			e.printStackTrace();
-		}
-	}
-	
-	public void run(){
-		//if(mode == MODE_GENLANDPREVIEW) genLandPreviewIPC();
-		/*else if (mode == MODE_GAME)*/ gameIPC();
-	}
-	
-	private void gameIPC(){
-		Socket sock = null;
-		try{
-			sock = serverSocket.accept();
-			input = sock.getInputStream();
-			output = sock.getOutputStream();
-			
-			int msgSize = 0;
-			byte[] buffer = new byte[BUFFER_SIZE];
-
-			while(!clientQuit){
-				msgSize = 0;
-
-				input.read(buffer, 0, 1);
-				msgSize = buffer[0];
-
-				input.read(buffer, 0, msgSize);
-				System.out.println("IPC" + (char)buffer[0] + " : " + new String(buffer, 1,msgSize-1, "US_ASCII"));
-				switch(buffer[0]){
-				case 'C'://game init
-					config.sendToEngine(this);
-					break;
-				case '?'://ping - pong
-					sendToEngine("!");
-					break;
-				case 'e'://Send protocol version
-					System.out.println(new String(buffer));
-					break;
-				case 'i'://game statistics
-					switch(buffer[1]){
-					case 'r'://winning team
-						break;
-					case 'D'://best shot
-						break;
-					case 'k'://best hedgehog
-						break;
-					case 'K'://# hogs killed
-						break;
-					case 'H'://team health graph
-						break;
-					case 'T':// local team stats
-						break;
-					case 'P'://teams ranking
-						break;
-					case 's'://self damage
-						break;
-					case 'S'://friendly fire
-						break;
-					case 'B'://turn skipped
-						break;
-					default:
-					}
-					break;
-				case 'E'://error - quits game
-					System.out.println(new String(buffer));
-					return;
-				case 'q'://game ended remove save file
-
-				    return;
-				case 'Q'://game ended but not finished
-
-					return;
-				}
-
-			}
-		}catch(IOException e){
-			e.printStackTrace();
-		}finally{
-			try {
-				if(sock != null) sock.close();
-			} catch (IOException e) {}
-			try{
-				if(serverSocket != null) serverSocket.close();
-			} catch (IOException e) {}
-		}
-	}
-
-	public void sendToEngine(String s){
-		int length = s.length();
-		
-		try {
-			output.write(length);
-			output.write(s.getBytes(), 0, length);
-		} catch (IOException e) {
-			e.printStackTrace();
-		}
-	}
-	
-	public void quitIPC(){
-		clientQuit = true;
-	}
-	
-}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/EngineProtocol/GameConfig.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/EngineProtocol/GameConfig.java	Mon Aug 06 22:39:36 2012 +0200
@@ -18,9 +18,7 @@
 
 package org.hedgewars.hedgeroid.EngineProtocol;
 
-import java.io.IOException;
 import java.util.ArrayList;
-import java.util.UUID;
 
 import org.hedgewars.hedgeroid.Datastructures.GameMode;
 import org.hedgewars.hedgeroid.Datastructures.Map;
@@ -28,12 +26,7 @@
 import org.hedgewars.hedgeroid.Datastructures.Team;
 import org.hedgewars.hedgeroid.Datastructures.Weapon;
 
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-public class GameConfig implements Parcelable{
-	
+public class GameConfig {
 	public GameMode mode = GameMode.MODE_LOCAL;
 	public Map map = null;
 	public String theme = null;
@@ -49,79 +42,4 @@
 	public GameConfig(){
 		
 	}
-	
-	public GameConfig(Parcel in){
-		readFromParcel(in);	
-	}
-	
-
-	
-	public void sendToEngine(EngineProtocolNetwork epn) throws IOException{
-		Log.d("HW_Frontend", "Sending Gameconfig...");
-		int teamCount = 4;
-		epn.sendToEngine("TL"); //Write game mode
-		if(training != null) epn.sendToEngine(String.format("escript Scripts/Training/%s.lua", training));
-		else if(style != null) epn.sendToEngine(String.format("escript Scripts/Multiplayer/%s.lua", style));
-		
-		//seed info
-		epn.sendToEngine(String.format("eseed {%s}", UUID.randomUUID().toString()));
-		
-		map.sendToEngine(epn);
-		//dimensions of the map
-		//templatefilter_command
-		//mapgen_command
-		//mazesize_command
-		
-		epn.sendToEngine(String.format("etheme %s", theme));
-		
-		scheme.sendToEngine(epn);
-		
-		weapon.sendToEngine(epn, teamCount);
-		
-		for(Team t : teams){
-			if(t != null)t.sendToEngine(epn, teamCount, scheme.getHealth());
-		}
-	}
-	
-	public int describeContents() {
-		return 0;
-	}
-
-	public void writeToParcel(Parcel dest, int flags) {
-		dest.writeString(mode.name());
-		dest.writeParcelable(map, flags);
-		dest.writeString(theme);
-		dest.writeParcelable(scheme, flags);
-		dest.writeParcelable(weapon, flags);
-		dest.writeString(style);
-		dest.writeString(training);
-		dest.writeString(seed);
-		dest.writeParcelableArray((Team[])teams.toArray(new Team[1]), 0);
-	}
-	
-	private void readFromParcel(Parcel src){
-		mode = GameMode.valueOf(src.readString());
-		map = src.readParcelable(Map.class.getClassLoader());
-		theme = src.readString();
-		scheme = src.readParcelable(Scheme.class.getClassLoader());
-		weapon = src.readParcelable(Weapon.class.getClassLoader());
-		style = src.readString();
-		training = src.readString();
-		seed = src.readString();
-		Parcelable[] parcelables = src.readParcelableArray(Team[].class.getClassLoader());
-		for(Parcelable team : parcelables){
-			teams.add((Team)team);
-		}
-		
-	}
-	
-	public static final Parcelable.Creator<GameConfig> CREATOR = new Parcelable.Creator<GameConfig>() {
-		public GameConfig createFromParcel(Parcel source) {
-			return new GameConfig(source);
-		}
-		public GameConfig[] newArray(int size) {
-			return new GameConfig[size];
-		}
-	};
-	
 }
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/EngineProtocol/PascalExports.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/EngineProtocol/PascalExports.java	Mon Aug 06 22:39:36 2012 +0200
@@ -36,5 +36,5 @@
 	public static native int HWgetNumberOfWeapons();
 	public static native int HWgetMaxNumberOfTeams();
 	public static native int HWgetMaxNumberOfHogs();
-        public static native int HWterminate(boolean b);	
+    public static native int HWterminate(boolean b);	
 }
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SDLActivity.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SDLActivity.java	Mon Aug 06 22:39:36 2012 +0200
@@ -6,9 +6,12 @@
 import javax.microedition.khronos.egl.EGLDisplay;
 import javax.microedition.khronos.egl.EGLSurface;
 
-import org.hedgewars.hedgeroid.EngineProtocol.EngineProtocolNetwork;
 import org.hedgewars.hedgeroid.EngineProtocol.GameConfig;
 import org.hedgewars.hedgeroid.EngineProtocol.PascalExports;
+import org.hedgewars.hedgeroid.frontlib.Flib;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.GameSetupPtr;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.GameconnPtr;
+import org.hedgewars.hedgeroid.netplay.TickHandler;
 
 import android.app.Activity;
 import android.content.Context;
@@ -23,6 +26,7 @@
 import android.media.AudioTrack;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.Message;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -37,13 +41,19 @@
     SDL Activity
  */
 public class SDLActivity extends Activity {
-
+	/**
+	 * Set startConfig to the desired config when starting this activity. This avoids having to parcel all
+	 * the config objects into the Intent. Not particularly elegant, but it's actually a recommended
+	 * way to do this (http://developer.android.com/guide/faq/framework.html#3)
+	 */
+	public static volatile GameConfig startConfig;
+	
 	// Main components
 	public static SDLActivity mSingleton;
 	private static SDLSurface mSurface;
 
 	// This is what SDL runs in. It invokes SDL_main(), eventually
-	private static Thread mSDLThread;
+	private static Thread mSDLThread; // Guarded by SDLActivity.class
 
 	// Audio
 	private static Thread mAudioThread;
@@ -74,11 +84,8 @@
 		mSingleton = this;
 
 		// Set up the surface
-		GameConfig config = getIntent().getParcelableExtra("config");
-
-		mSurface = new SDLSurface(getApplication(), config);
+		mSurface = new SDLSurface(getApplication(), startConfig);
 		setContentView(mSurface);
-		SurfaceHolder holder = mSurface.getHolder();
 	}
 
 	// Events
@@ -108,15 +115,15 @@
 		SDLActivity.nativeQuit();
 
 		// Now wait for the SDL thread to quit
-		if (mSDLThread != null) {
-			try {
-				mSDLThread.join();
-			} catch(Exception e) {
-				Log.v("SDL", "Problem stopping thread: " + e);
+		synchronized(SDLActivity.class) {
+			if (mSDLThread != null) {
+				try {
+					mSDLThread.join();
+				} catch(Exception e) {
+					Log.w("SDL", "Problem stopping thread: " + e);
+				}
+				mSDLThread = null;
 			}
-			mSDLThread = null;
-
-			//Log.v("SDL", "Finished waiting for SDL thread");
 		}
 	}
 
@@ -175,13 +182,14 @@
 	}
 
 	public static void startApp(int width, int height, GameConfig config) {
-		// Start up the C app thread
-		if (mSDLThread == null) {
-			mSDLThread = new Thread(new SDLMain(width, height, config), "SDLThread");
-			mSDLThread.start();
-		}
-		else {
-			SDLActivity.nativeResume();
+		synchronized(SDLActivity.class) {
+			// Start up the C app thread
+			if (mSDLThread == null) {
+				mSDLThread = new Thread(new SDLMain(width, height, config), "SDLThread");
+				mSDLThread.start();
+			} else {
+				SDLActivity.nativeResume();
+			}
 		}
 	}
 
@@ -425,23 +433,34 @@
 
 	public void run() {
 		//Set up the IPC socket server to communicate with the engine
-		EngineProtocolNetwork ipc = new EngineProtocolNetwork(config);
+		HandlerThread thread = new HandlerThread("IPC thread");
+		thread.start(); // TODO ensure it gets stopped
+		final GameconnPtr conn = Flib.INSTANCE.flib_gameconn_create("Xeli", GameSetupPtr.createJavaOwned(config), false);
+		if(conn == null) {
+			throw new AssertionError();
+		}
+		int port = Flib.INSTANCE.flib_gameconn_getport(conn);
 
 		String path = Utils.getDataPath(SDLActivity.mSingleton);//This represents the data directory
 		path = path.substring(0, path.length()-1);//remove the trailing '/'
 
-
 		// Runs SDL_main() with added parameters
-		SDLActivity.nativeInit(new String[] { String.valueOf(ipc.port),
+		SDLActivity.nativeInit(new String[] { String.valueOf(port),
 				String.valueOf(surfaceWidth), String.valueOf(surfaceHeight),
 				"0", "en.txt", "xeli", "1", "1", "1", path, ""  });
 
+		new TickHandler(thread.getLooper(), 50, new Runnable() {
+			public void run() {
+				Flib.INSTANCE.flib_gameconn_tick(conn);
+			}
+		});
 		try {
-			ipc.quitIPC();
-			ipc.join();
+			thread.quit();
+			thread.join();
 		} catch (InterruptedException e) {
-			e.printStackTrace();
+			throw new AssertionError();
 		}
+		Flib.INSTANCE.flib_gameconn_destroy(conn);
 		Log.v("SDL", "SDL thread terminated");
 	}
 }
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/StartGameActivity.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/StartGameActivity.java	Mon Aug 06 22:39:36 2012 +0200
@@ -45,7 +45,7 @@
 public class StartGameActivity extends Activity {
 
 	public static final int ACTIVITY_TEAM_SELECTOR = 0;
-
+	
 	private GameConfig config = null;
 	private ImageButton start, back, team;
 	private Spinner maps, gameplay, gamescheme, weapons, themes;
@@ -53,8 +53,6 @@
 
 	public void onCreate(Bundle savedInstanceState){
 		super.onCreate(savedInstanceState);
-
-		Scheme.parseConfiguration(this);
 		config = new GameConfig();
 
 		setContentView(R.layout.starting_game);
@@ -132,7 +130,7 @@
 
 	private void startTeamsActivity(){
 		Intent i = new Intent(StartGameActivity.this, TeamSelectionActivity.class);
-		i.putParcelableArrayListExtra("teams", config.teams);
+		// TODO i.putParcelableArrayListExtra("teams", config.teams);
 		startActivityForResult(i, ACTIVITY_TEAM_SELECTOR);
 	}
 
@@ -143,7 +141,7 @@
 				Parcelable[] parcelables = (Parcelable[])data.getParcelableArrayExtra("teams");
 				config.teams.clear();
 				for(Parcelable t : parcelables){
-					config.teams.add((Team)t);
+					// TODO config.teams.add((Team)t);
 				}
 				teamCount.getDrawable().setLevel(config.teams.size());
 			}
@@ -209,11 +207,11 @@
 			if(config.teams.size() < 2){
 				Toast.makeText(StartGameActivity.this, R.string.not_enough_teams, Toast.LENGTH_LONG).show();
 				startTeamsActivity();
-			}
-			else{
+			} else {
+				SDLActivity.startConfig = config;
 				Intent i = new Intent(StartGameActivity.this, SDLActivity.class);
-				i.putExtra("config", config);
-				startActivity(i);}
+				startActivity(i);
+			}
 		}
 	};
 
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamCreatorActivity.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamCreatorActivity.java	Mon Aug 06 22:39:36 2012 +0200
@@ -20,14 +20,14 @@
 package org.hedgewars.hedgeroid;
 
 import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.hedgewars.hedgeroid.Datastructures.FrontendDataUtils;
+import org.hedgewars.hedgeroid.Datastructures.Hog;
 import org.hedgewars.hedgeroid.Datastructures.Team;
 
 import android.app.Activity;
@@ -247,22 +247,12 @@
 
 	private OnClickListener saveClicker = new OnClickListener() {
 		public void onClick(View v) {
-			Toast.makeText(TeamCreatorActivity.this, R.string.saved, Toast.LENGTH_SHORT).show();
-			saved = true;
-			Team team = new Team();
-			team.name = name.getText().toString();
-			HashMap<String, Object> hashmap = (HashMap<String, Object>) flag.getSelectedItem();
-
-			team.flag = (String) hashmap.get("txt");
-			team.fort = fort.getSelectedItem().toString();
-			hashmap = (HashMap<String, Object>) grave.getSelectedItem();
-			team.grave = hashmap.get("txt").toString();
-			team.hash = "0";
-			team.voice = voice.getSelectedItem().toString();
-			team.file = fileName;
-
-			hashmap = ((HashMap<String, Object>) difficulty.getSelectedItem());
-			String levelString = hashmap.get("txt").toString();
+			String teamName = name.getText().toString();
+			String teamFlag = (String)((Map<String, Object>) flag.getSelectedItem()).get("txt");
+			String teamFort = fort.getSelectedItem().toString();
+			String teamGrave = (String)((Map<String, Object>) grave.getSelectedItem()).get("txt");
+			String teamVoice = voice.getSelectedItem().toString();
+			String levelString = (String)((Map<String, Object>) difficulty.getSelectedItem()).get("txt");
 			int levelInt;
 			if (levelString.equals(getString(R.string.human))) {
 				levelInt = 0;
@@ -277,28 +267,39 @@
 			} else {
 				levelInt = 5;
 			}
-
+			
+			List<Hog> hogs = new ArrayList<Hog>();
 			for (int i = 0; i < hogName.size(); i++) {
-				team.hogNames[i] = hogName.get(i).getText().toString();
-				hashmap = (HashMap<String, Object>) hogHat.get(i).getSelectedItem();
-				team.hats[i] = hashmap.get("txt").toString();
-				team.levels[i] = levelInt;
+				String name = hogName.get(i).getText().toString();
+				String hat = ((Map<String, Object>) hogHat.get(i).getSelectedItem()).get("txt").toString();
+				hogs.add(new Hog(name, hat, levelInt));
+			}
+			
+			Team team = new Team(teamName, teamGrave, teamFlag, teamVoice, teamFort, hogs);
+			File teamsDir = new File(getFilesDir(), Team.DIRECTORY_TEAMS);
+			if (!teamsDir.exists()) teamsDir.mkdir();
+			if(fileName == null){
+				fileName = createNewFilename(Utils.replaceBadChars(team.name));
 			}
 			try {
-				File teamsDir = new File(getFilesDir().getAbsolutePath() + '/' + Team.DIRECTORY_TEAMS);
-				if (!teamsDir.exists()) teamsDir.mkdir();
-				if(team.file == null){
-					team.setFileName(TeamCreatorActivity.this);
-				}
-				FileOutputStream fos = new FileOutputStream(String.format("%s/%s", teamsDir.getAbsolutePath(), team.file));
-				team.writeToXml(fos);
-			} catch (FileNotFoundException e) {
-				e.printStackTrace();
+				team.save(new File(teamsDir, fileName));
+				Toast.makeText(TeamCreatorActivity.this, R.string.saved, Toast.LENGTH_SHORT).show();
+				saved = true;
+			} catch(IOException e) {
+				Toast.makeText(getApplicationContext(), R.string.error_save_failed, Toast.LENGTH_SHORT).show();
 			}
 		}
-
 	};
 
+	private String createNewFilename(String suggestedName){
+		File f = new File(getFilesDir(), suggestedName);
+		if(f.exists()){
+			return createNewFilename(suggestedName + (int)(Math.random()*10));
+		} else {
+			return suggestedName + (int)(Math.random()*10);
+		}
+	}
+	
 	private OnItemSelectedListener fortSelector = new OnItemSelectedListener() {
 		public void onItemSelected(AdapterView<?> arg0, View arg1,
 				int position, long arg3) {
@@ -362,7 +363,7 @@
 
 			position = 0;
 			for (HashMap<String, ?> hashmap : typesData) {
-				if (hashmap.get("txt").equals(t.levels[0])) {
+				if (t.hogs.get(0) != null && hashmap.get("txt").equals(t.hogs.get(0).level)) {
 					difficulty.setSelection(position);
 					break;
 				}
@@ -387,14 +388,14 @@
 			for (int i = 0; i < Team.maxNumberOfHogs; i++) {
 				position = 0;
 				for (HashMap<String, ?> hashmap : hatsData) {
-					if (hashmap.get("txt").equals(t.hats[i])) {
+					if (hashmap.get("txt").equals(t.hogs.get(i).hat)) {
 						hogHat.get(i).setSelection(position);
 					}
 				}
 
-				hogName.get(i).setText(t.hogNames[i]);
+				hogName.get(i).setText(t.hogs.get(i).name);
 			}
-			this.fileName = t.file;
+			//this.fileName = t.file;
 		}
 	}
 
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamSelectionActivity.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamSelectionActivity.java	Mon Aug 06 22:39:36 2012 +0200
@@ -26,11 +26,16 @@
 
 import org.hedgewars.hedgeroid.Datastructures.FrontendDataUtils;
 import org.hedgewars.hedgeroid.Datastructures.Team;
+import org.hedgewars.hedgeroid.Datastructures.TeamFile;
+import org.hedgewars.hedgeroid.Datastructures.TeamInGame;
+import org.hedgewars.hedgeroid.Datastructures.TeamIngameAttributes;
 
 import android.app.Activity;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.Parcelable;
+import android.util.Pair;
 import android.view.ContextMenu;
 import android.view.MenuItem;
 import android.view.View;
@@ -47,8 +52,10 @@
 import android.widget.TextView;
 
 public class TeamSelectionActivity extends Activity implements Runnable{
-
 	private static final int ACTIVITY_TEAMCREATION = 0;
+	
+	private static volatile List<Pair<TeamFile, TeamIngameAttributes>> activityParams;
+	private static volatile List<Pair<TeamFile, TeamIngameAttributes>> activityReturn;
 
 	private ImageButton addTeam, back;
 	private ListView availableTeams, selectedTeams;
@@ -86,14 +93,14 @@
 	}
 
 	public void run(){
-		List<HashMap<String, Object>> teamsList = FrontendDataUtils.getTeams(this);//teams from xml
-		ArrayList<Team> teamsStartGame = getIntent().getParcelableArrayListExtra("teams");//possible selected teams
+		List<HashMap<String, Object>> teamsList = getTeams(this);//teams from xml
+		ArrayList<String> teamsStartGame = getIntent().getStringArrayListExtra("selectedTeamNames");
 
 		for(HashMap<String, Object> hashmap : teamsList){
 			boolean added = false;
-			for(Team t : teamsStartGame){
-				if(((Team)hashmap.get("team")).equals(t)){//add to available or add to selected
-					selectedTeamsList.add(FrontendDataUtils.teamToMap(t));//create a new hashmap to ensure all variables are entered into the map
+			for(String teamName : teamsStartGame){
+				if(((Team)hashmap.get("team")).name.equals(teamName)){ // add to available or add to selected
+					selectedTeamsList.add(hashmap);
 					added = true;
 					break;
 				}
@@ -139,7 +146,7 @@
 	 */
 	private void updateListViews(){
 		unregisterForContextMenu(availableTeams);
-		availableTeamsList = FrontendDataUtils.getTeams(this);
+		availableTeamsList = getTeams(this);
 		ArrayList<HashMap<String, Object>> toBeRemoved = new ArrayList<HashMap<String, Object>>();
 		for(HashMap<String, Object> hashmap : selectedTeamsList){
 			String name = (String)hashmap.get("txt");
@@ -253,21 +260,19 @@
 	public boolean onContextItemSelected(MenuItem item){
 		AdapterView.AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) item.getMenuInfo();
 		int position = menuInfo.position;
+		TeamFile teamfile = (TeamFile)availableTeamsList.get(position).get("teamfile");
 		switch(item.getItemId()){
 		case 0://select
 			selectAvailableTeamsItem(position);
 			return true;
 		case 1://delete
-			Team team = (Team)availableTeamsList.get(position).get("team");
-			File f = new File(String.format("%s/%s/%s", TeamSelectionActivity.this.getFilesDir(), Team.DIRECTORY_TEAMS, team.file));
-			f.delete();
+			teamfile.file.delete();
 			availableTeamsList.remove(position);
 			((SimpleAdapter)availableTeams.getAdapter()).notifyDataSetChanged();
 			return true;
 		case 2://edit
 			Intent i = new Intent(TeamSelectionActivity.this, TeamCreatorActivity.class);
-			Team t = (Team)availableTeamsList.get(position).get("team");
-			i.putExtra("team", t);
+			i.putExtra("teamfile", teamfile.file);
 			startActivityForResult(i, ACTIVITY_TEAMCREATION);
 			return true;
 		}
@@ -304,4 +309,36 @@
 		setResult(Activity.RESULT_OK, i);
 
 	}
+	
+	private static List<HashMap<String, Object>> getTeams(Context c){
+		List<HashMap<String, Object>> ret = new ArrayList<HashMap<String, Object>>();
+		List<TeamFile> teamfiles = FrontendDataUtils.getTeamFiles(c);
+		for(TeamFile tf : teamfiles) {
+			ret.add(teamfileToMap(tf));
+		}
+		return ret;
+	}
+	
+	private static final int[] botlevelDrawables = new int[] {
+		R.drawable.human, R.drawable.bot5, R.drawable.bot4, R.drawable.bot3, R.drawable.bot2, R.drawable.bot1
+	};
+	
+	private static HashMap<String, Object> teamfileToMap(TeamFile tf){
+		HashMap<String, Object> hashmap = new HashMap<String, Object>();
+		Team t = tf.team;
+		hashmap.put("team", t);
+		hashmap.put("teamfile", tf);
+		hashmap.put("txt", t.name);
+		hashmap.put("color", t.color);
+		hashmap.put("count", t.hogCount);
+		
+		int botlevel = t.hogs.get(0).level;
+		if(botlevel<0 || botlevel>=botlevelDrawables.length) {
+			hashmap.put("img", R.drawable.bot1);
+		} else {
+			hashmap.put("img", botlevelDrawables[botlevel]);
+		}
+		return hashmap;
+		return null;
+	}
 }
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Utils.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Utils.java	Mon Aug 06 22:39:36 2012 +0200
@@ -270,4 +270,24 @@
 			closeQuietly(is);
 		}
 	}
+	
+	private static final char[] badFilenameChars = new char[] { '/', '\\', ':', '*', '?', '\"', '<', '>', '|', '.', '\0' };
+	
+	/**
+	 * Modify the given String so that it can be used as part of a filename
+	 * without causing problems from illegal/special characters.
+	 * 
+	 * The result should be similar to the input, but isn't necessarily
+	 * reversible.
+	 */
+	public static String replaceBadChars(String name) {
+		if (name == null || name.trim().length()==0) {
+			return "_";
+		}
+		name = name.trim();
+		for (char badChar : badFilenameChars) {
+			name = name.replace(badChar, '_');
+		}
+		return name;
+	}
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/Flib.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,35 @@
+package org.hedgewars.hedgeroid.frontlib;
+
+import java.util.Collections;
+
+import android.util.Log;
+
+import com.sun.jna.Library;
+import com.sun.jna.Native;
+
+public class Flib {
+	static {
+		System.loadLibrary("SDL_net");
+		System.setProperty("jna.encoding", "UTF8"); // Ugly global setting, but it seems JNA doesn't allow setting this per-library... 
+	}
+	public static final Frontlib INSTANCE = (Frontlib)Native.loadLibrary("frontlib", Frontlib.class, Collections.singletonMap(Library.OPTION_TYPE_MAPPER, FrontlibTypeMapper.INSTANCE));
+	
+	// Hook frontlib logging into Android logging
+	private static final Frontlib.LogCallback logCb = new Frontlib.LogCallback() {
+		public void callback(int level, String message) {
+			if(level >= Frontlib.FLIB_LOGLEVEL_ERROR) {
+				Log.e("Frontlib", message);
+			} else if(level == Frontlib.FLIB_LOGLEVEL_WARNING){
+				Log.w("Frontlib", message);
+			} else if(level == Frontlib.FLIB_LOGLEVEL_INFO){
+				Log.i("Frontlib", message);
+			} else if(level <= Frontlib.FLIB_LOGLEVEL_DEBUG){
+				Log.d("Frontlib", message);
+			}
+		}
+	};
+	static {
+		INSTANCE.flib_log_setLevel(Frontlib.FLIB_LOGLEVEL_ALL);
+		INSTANCE.flib_log_setCallback(logCb);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/Frontlib.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,793 @@
+package org.hedgewars.hedgeroid.frontlib;
+import java.nio.Buffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.hedgewars.hedgeroid.Datastructures.Hog;
+import org.hedgewars.hedgeroid.Datastructures.MetaScheme;
+import org.hedgewars.hedgeroid.Datastructures.MetaScheme.Mod;
+import org.hedgewars.hedgeroid.Datastructures.MetaScheme.Setting;
+import org.hedgewars.hedgeroid.Datastructures.RoomlistRoom;
+import org.hedgewars.hedgeroid.Datastructures.Scheme;
+import org.hedgewars.hedgeroid.Datastructures.Team;
+import org.hedgewars.hedgeroid.Datastructures.TeamInGame;
+import org.hedgewars.hedgeroid.Datastructures.TeamIngameAttributes;
+import org.hedgewars.hedgeroid.EngineProtocol.GameConfig;
+
+import com.sun.jna.Callback;
+import com.sun.jna.Library;
+import com.sun.jna.Memory;
+import com.sun.jna.NativeLong;
+import com.sun.jna.Pointer;
+import com.sun.jna.PointerType;
+import com.sun.jna.Structure;
+
+public interface Frontlib extends Library {
+	static final int NATIVE_INT_SIZE = 4;
+	static final int NATIVE_BOOL_SIZE = 1;
+	
+	static final int NETCONN_STATE_CONNECTING = 0;
+	static final int NETCONN_STATE_LOBBY = 1;
+	static final int NETCONN_STATE_ROOM = 2;
+	static final int NETCONN_STATE_INGAME = 3;
+	static final int NETCONN_STATE_DISCONNECTED = 10;
+	
+	static final int NETCONN_DISCONNECT_NORMAL = 0;
+	static final int NETCONN_DISCONNECT_SERVER_TOO_OLD = 1;
+	static final int NETCONN_DISCONNECT_AUTH_FAILED = 2;
+	static final int NETCONN_DISCONNECT_CONNLOST = 3;
+	static final int NETCONN_DISCONNECT_INTERNAL_ERROR = 100;
+	
+	static final int NETCONN_ROOMLEAVE_ABANDONED = 0;
+	static final int NETCONN_ROOMLEAVE_KICKED = 1;
+	
+	static final int NETCONN_MSG_TYPE_PLAYERINFO = 0;
+	static final int NETCONN_MSG_TYPE_SERVERMESSAGE = 1;
+	static final int NETCONN_MSG_TYPE_WARNING = 2;
+	static final int NETCONN_MSG_TYPE_ERROR = 3;
+	
+	static final int NETCONN_MAPCHANGE_FULL = 0;
+	static final int NETCONN_MAPCHANGE_MAP = 1;
+	static final int NETCONN_MAPCHANGE_MAPGEN = 2;
+	static final int NETCONN_MAPCHANGE_DRAWNMAP = 3;
+	static final int NETCONN_MAPCHANGE_MAZE_SIZE = 4;
+	static final int NETCONN_MAPCHANGE_TEMPLATE = 5;
+	static final int NETCONN_MAPCHANGE_THEME = 6;
+	static final int NETCONN_MAPCHANGE_SEED = 7;
+	
+	static final int GAME_END_FINISHED = 0;
+	static final int GAME_END_INTERRUPTED = 1;
+	static final int GAME_END_HALTED = 2;
+	static final int GAME_END_ERROR = 3;
+	
+	static final int HEDGEHOGS_PER_TEAM = 8;
+	
+	public static class NetconnPtr extends PointerType { }
+	public static class MapconnPtr extends PointerType { }
+	public static class GameconnPtr extends PointerType { }
+	public static class MetaschemePtr extends PointerType { }
+	
+	public static class RoomArrayPtr extends PointerType { 
+		/**
+		 * Returns the (native-owned) rooms in this list
+		 */
+		public RoomlistRoom[] getRooms(int count) {
+			Pointer ptr = getPointer();
+			if(ptr == null) {
+				return new RoomlistRoom[0];
+			}
+			Pointer[] untypedPtrs = ptr.getPointerArray(0, count);
+			RoomlistRoom[] result = new RoomlistRoom[count];
+			for(int i=0; i<count; i++) {
+				result[i] = RoomPtr.deref(untypedPtrs[i]);
+			}
+			return result;
+		}
+	}
+	
+	public static class RoomPtr extends PointerType {
+		public RoomPtr() { super(); }
+		public RoomPtr(Pointer ptr) { super(ptr); }
+		
+		public RoomlistRoom deref() {
+			return deref(getPointer());
+		}
+		
+		public static RoomlistRoom deref(Pointer p) {
+			RoomStruct r = new RoomStruct(p);
+			r.read();
+			return new RoomlistRoom(r.name, r.map, r.scheme, r.weapons, r.owner, r.playerCount, r.teamCount, r.inProgress);
+		}
+	}
+	
+	public static class TeamPtr extends PointerType {
+		public TeamInGame deref() {
+			return deref(getPointer());
+		}
+		
+		public static TeamInGame deref(Pointer p) {
+			TeamStruct ts = new TeamStruct(p);
+			ts.read();
+			List<Hog> hogs = new ArrayList<Hog>();
+			for(int i=0; i<ts.hogs.length; i++) {
+				HogStruct hog = ts.hogs[i];
+				hogs.add(new Hog(hog.name, hog.hat, hog.difficulty));
+			}
+			Team team = new Team(ts.name, ts.grave, ts.flag, ts.voicepack, ts.fort, hogs);
+			TeamIngameAttributes attrs = new TeamIngameAttributes(ts.ownerName, ts.colorIndex, ts.hogsInGame, ts.remoteDriven);
+			return new TeamInGame(team, attrs);
+		}
+
+		public static TeamPtr createJavaOwned(Team t) {
+			return createJavaOwned(new TeamInGame(t, null));
+		}
+		
+		public static TeamPtr createJavaOwned(TeamInGame ingameTeam) {
+			TeamStruct ts = TeamStruct.from(ingameTeam.team, ingameTeam.ingameAttribs);
+			ts.write();
+			TeamPtr result = new TeamPtr();
+			result.setPointer(ts.getPointer());
+			return result;
+		}
+	}
+	
+	public static class WeaponsetPtr extends PointerType { }
+	public static class MapRecipePtr extends PointerType { }
+	public static class SchemePtr extends PointerType { }
+	public static class SchemelistPtr extends PointerType {
+		private SchemelistStruct javaOwnedInstance;
+		
+		public List<Scheme> deref() {
+			return deref(getPointer());
+		}
+		
+		public static List<Scheme> deref(Pointer p) {
+			SchemelistStruct sls = new SchemelistStruct(p);
+			sls.read();
+			return sls.toSchemeList();
+		}
+		
+		public static SchemelistPtr createJavaOwned(List<Scheme> schemes) {
+			SchemelistPtr result = new SchemelistPtr();
+			result.javaOwnedInstance = new SchemelistStruct();
+			result.javaOwnedInstance.fillFrom(schemes);
+			result.javaOwnedInstance.autoWrite();
+			result.setPointer(result.javaOwnedInstance.getPointer());
+			return result;
+		}
+	}
+	
+	public static class GameSetupPtr extends PointerType {
+		public static GameSetupPtr createJavaOwned(GameConfig conf) {
+			GameSetupStruct gss = GameSetupStruct.from(conf);
+			gss.write();
+			GameSetupPtr result = new GameSetupPtr();
+			result.setPointer(gss.getPointer());
+			return result;
+		}
+	}
+	
+	static class HogStruct extends Structure {
+		public static class ByVal extends HogStruct implements Structure.ByValue {}
+		public static class ByRef extends HogStruct implements Structure.ByReference {}
+		private static String[] FIELD_ORDER = new String[] {"name", "hat", "rounds", "kills", "deaths", "suicides", "difficulty", "initialHealth", "weaponset"};
+
+		public HogStruct() { super(); setFieldOrder(FIELD_ORDER); }
+		public HogStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
+		
+		public static HogStruct from(Hog hog) {
+			HogStruct hs = new HogStruct();
+			hs.difficulty = hog.level;
+			hs.hat = hog.hat;
+			hs.name = hog.name;
+			// TODO weaponset
+			// TODO initialHealth
+			return hs;
+		}
+		
+		public String name;
+		public String hat;
+		
+		public int rounds;
+		public int kills;
+		public int deaths;
+		public int suicides;
+	
+		public int difficulty;
+		
+		public int initialHealth;
+		public WeaponsetPtr weaponset;
+	}
+	
+	static class TeamStruct extends Structure {
+		public static class ByVal extends TeamStruct implements Structure.ByValue {}
+		public static class ByRef extends TeamStruct implements Structure.ByReference {}
+		private static String[] FIELD_ORDER = new String[] {"hogs", "name", "grave", "fort", "voicepack", "flag", "bindings", "bindingCount", "rounds", "wins", "campaignProgress", "colorIndex", "hogsInGame", "remoteDriven", "ownerName"};
+
+		public TeamStruct() { super(); setFieldOrder(FIELD_ORDER); }
+		public TeamStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
+		
+		public static TeamStruct from(Team team, TeamIngameAttributes attrs) {
+			TeamStruct ts = new TeamStruct();
+			if(team != null) {
+				ts.name = team.name;
+				ts.grave = team.grave;
+				ts.flag = team.flag;
+				ts.voicepack = team.voice;
+				ts.fort = team.fort;
+				if(team.hogs.size() != HEDGEHOGS_PER_TEAM) {
+					throw new IllegalArgumentException();
+				}
+				for(int i=0; i<ts.hogs.length; i++) {
+					ts.hogs[i] = HogStruct.from(team.hogs.get(i));
+				}
+			}
+			
+			if(attrs != null) {
+				ts.hogsInGame = attrs.hogCount;
+				ts.ownerName = attrs.ownerName;
+				ts.colorIndex = attrs.colorIndex;
+				ts.remoteDriven = attrs.remoteDriven;
+			}
+			return ts;
+		}
+		
+		public HogStruct[] hogs = new HogStruct[HEDGEHOGS_PER_TEAM];
+		public String name;
+		public String grave;
+		public String fort;
+		public String voicepack;
+		public String flag;
+		
+		public Pointer bindings;
+		public int bindingCount;
+		
+		public int rounds;
+		public int wins;
+		public int campaignProgress;
+		
+		public int colorIndex;
+		public int hogsInGame;
+		public boolean remoteDriven;
+		public String ownerName;
+	}
+	
+	static class RoomStruct extends Structure {
+		public static class ByVal extends RoomStruct implements Structure.ByValue {}
+		public static class ByRef extends RoomStruct implements Structure.ByReference {}
+		private static String[] FIELD_ORDER = new String[] {"inProgress", "name", "playerCount", "teamCount", "owner", "map", "scheme", "weapons"};
+		
+		public RoomStruct() { super(); setFieldOrder(FIELD_ORDER); }
+		public RoomStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
+		
+	    public boolean inProgress;
+	    public String name;
+	    public int playerCount;
+	    public int teamCount;
+	    public String owner;
+	    public String map;
+	    public String scheme;
+	    public String weapons;
+	}
+	
+	static class MapRecipeStruct extends Structure {
+		public static class ByVal extends MapRecipeStruct implements Structure.ByValue {}
+		public static class ByRef extends MapRecipeStruct implements Structure.ByReference {}
+		private static String[] FIELD_ORDER = new String[] {"_referenceCount", "mapgen", "name", "seed", "theme", "drawData", "drawDataSize", "templateFilter", "mazeSize"};
+		
+		public MapRecipeStruct() { super(); setFieldOrder(FIELD_ORDER); }
+		public MapRecipeStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
+		
+		public int _referenceCount;
+		public int mapgen;
+		public String name;
+		public String seed;
+		public String theme;
+		public Pointer drawData;
+		public int drawDataSize;
+		public int templateFilter;
+		public int mazeSize;
+	}
+	
+	static class MetaschemeSettingStruct extends Structure {
+		public static class ByVal extends MetaschemeSettingStruct implements Structure.ByValue {}
+		public static class ByRef extends MetaschemeSettingStruct implements Structure.ByReference {}
+		private static String[] FIELD_ORDER = new String[] {"name", "engineCommand", "maxMeansInfinity", "times1000", "min", "max", "def"};
+		
+		public MetaschemeSettingStruct() { super(); setFieldOrder(FIELD_ORDER); }
+		public MetaschemeSettingStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
+		
+		public void fillFrom(Setting setting) {
+			name = setting.name;
+			engineCommand = setting.engineCommand;
+			maxMeansInfinity = setting.maxMeansInfinity;
+			times1000 = setting.times1000;
+			min = setting.min;
+			max = setting.max;
+			def = setting.def;
+		}
+		
+		public MetaScheme.Setting toMetaSchemeSetting() {
+			return new MetaScheme.Setting(name, engineCommand, maxMeansInfinity, times1000, min, max, def);
+		}
+		
+		public String name;
+		public String engineCommand;
+		public boolean maxMeansInfinity;
+		public boolean times1000;
+		public int min;
+		public int max;
+		public int def;
+	}
+	
+	static class MetaschemeModStruct extends Structure {
+		public static class ByVal extends MetaschemeModStruct implements Structure.ByValue {}
+		public static class ByRef extends MetaschemeModStruct implements Structure.ByReference {}
+		private static String[] FIELD_ORDER = new String[] {"name", "bitmaskIndex"};
+		
+		public MetaschemeModStruct() { super(); setFieldOrder(FIELD_ORDER); }
+		public MetaschemeModStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
+		
+		public void fillFrom(Mod mod) {
+			name = mod.name;
+			bitmaskIndex = mod.bitmaskIndex;
+		}
+		
+		public MetaScheme.Mod toMetaSchemeMod() {
+			return new MetaScheme.Mod(name, bitmaskIndex);
+		}
+
+		public String name;
+		public int bitmaskIndex;
+
+	}
+	
+	static class MetaschemeStruct extends Structure {
+		public static class ByVal extends MetaschemeStruct implements Structure.ByValue {}
+		public static class ByRef extends MetaschemeStruct implements Structure.ByReference {}
+
+		private static String[] FIELD_ORDER = new String[] {"_referenceCount", "settingCount", "modCount", "settings", "mods"};
+		
+		public MetaschemeStruct() { super(); setFieldOrder(FIELD_ORDER); }
+		public MetaschemeStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
+		
+		public void fillFrom(MetaScheme metascheme) {
+			settingCount = metascheme.settings.size();
+			modCount = metascheme.mods.size();
+			
+			settings = new MetaschemeSettingStruct.ByRef();
+			Structure[] settingStructs = settings.toArray(settingCount);
+			mods = new MetaschemeModStruct.ByRef();
+			Structure[] modStructs = mods.toArray(modCount);
+			
+			for(int i=0; i<settingCount; i++) {
+				MetaschemeSettingStruct mss = (MetaschemeSettingStruct)settingStructs[i];
+				mss.fillFrom(metascheme.settings.get(i));
+			}
+			
+			for(int i=0; i<modCount; i++) {
+				MetaschemeModStruct mms = (MetaschemeModStruct)modStructs[i];
+				mms.fillFrom(metascheme.mods.get(i));
+			}
+		}
+		
+		/**
+		 * Only use on native-owned structs!
+		 * Calling this method on a Java-owned struct could cause garbage collection of referenced
+		 * structures.
+		 */
+		public MetaScheme toMetaScheme() {
+			List<MetaScheme.Setting> settingList = new ArrayList<MetaScheme.Setting>(settingCount);
+			List<MetaScheme.Mod> modList = new ArrayList<MetaScheme.Mod>(modCount);
+			
+			Structure[] settingStructs = settings.toArray(settingCount);
+			Structure[] modStructs = mods.toArray(modCount);
+			
+			for(int i=0; i<settingCount; i++) {
+				MetaschemeSettingStruct mss = (MetaschemeSettingStruct)settingStructs[i];
+				settingList.add(mss.toMetaSchemeSetting());
+			}
+			
+			for(int i=0; i<modCount; i++) {
+				MetaschemeModStruct mms = (MetaschemeModStruct)modStructs[i];
+				modList.add(mms.toMetaSchemeMod());
+			}
+			
+			return new MetaScheme(modList, settingList);
+		}
+		
+		public int _referenceCount;
+		public int settingCount;
+		public int modCount;
+		public MetaschemeSettingStruct.ByRef settings;
+		public MetaschemeModStruct.ByRef mods;
+	}
+	
+	static class SchemeStruct extends Structure {
+		public static class ByVal extends SchemeStruct implements Structure.ByValue {}
+		public static class ByRef extends SchemeStruct implements Structure.ByReference {}
+		private static String[] FIELD_ORDER = new String[] {"_referenceCount", "meta", "name", "settings", "mod"};
+		
+		public SchemeStruct() { super(); setFieldOrder(FIELD_ORDER); }
+		public SchemeStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
+		
+		public void fillFrom(Scheme scheme) {
+			meta = new MetaschemeStruct.ByRef();
+			meta.fillFrom(scheme.metascheme);
+			name = scheme.name;
+			settings = new Memory(NATIVE_INT_SIZE * scheme.metascheme.settings.size());
+			for(int i=0; i<scheme.metascheme.settings.size(); i++) {
+				Integer value = scheme.settings.get(scheme.metascheme.settings.get(i).name);
+				settings.setInt(NATIVE_INT_SIZE*i, value);
+			}
+			mods = new Memory(NATIVE_BOOL_SIZE * scheme.metascheme.mods.size());
+			for(int i=0; i<scheme.metascheme.mods.size(); i++) {
+				Boolean value = scheme.mods.get(scheme.metascheme.mods.get(i).name);
+				mods.setByte(NATIVE_BOOL_SIZE*i, (byte)(value ? 1 : 0));
+			}
+		}
+
+		public Scheme toScheme() {
+			MetaScheme metaScheme = meta.toMetaScheme();
+			Map<String, Integer> settingsMap = new HashMap<String, Integer>();
+			for(int i=0; i<metaScheme.settings.size(); i++) {
+				settingsMap.put(metaScheme.settings.get(i).name, settings.getInt(NATIVE_INT_SIZE*i));
+			}
+			Map<String, Boolean> modsMap = new HashMap<String, Boolean>();
+			for(int i=0; i<metaScheme.mods.size(); i++) {
+				modsMap.put(metaScheme.mods.get(i).name, mods.getByte(i) != 0 ? Boolean.TRUE : Boolean.FALSE);
+			}
+			return new Scheme(metaScheme, name, settingsMap, modsMap);
+		}
+		
+		public int _referenceCount;
+		public MetaschemeStruct.ByRef meta;
+		public String name;
+		public Pointer settings;
+		public Pointer mods;
+	}
+	
+	/**
+	 * Represents a flib_scheme*, for use as part of a flib_scheme**
+	 */
+	static class SchemePointerByReference extends Structure implements Structure.ByReference {
+		private static String[] FIELD_ORDER = new String[] {"scheme"};
+		
+		public SchemePointerByReference() { super(); setFieldOrder(FIELD_ORDER); }
+		public SchemePointerByReference(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
+		
+		public SchemeStruct.ByRef scheme;
+	}
+	
+	static class SchemelistStruct extends Structure {
+		public static class ByVal extends SchemelistStruct implements Structure.ByValue {}
+		public static class ByRef extends SchemelistStruct implements Structure.ByReference {}
+		private static String[] FIELD_ORDER = new String[] {"schemeCount", "schemes"};
+		
+		public SchemelistStruct() { super(); setFieldOrder(FIELD_ORDER); }
+		public SchemelistStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
+		
+		/**
+		 * Only use on native-owned structs!
+		 * Calling this method on a Java-owned struct could cause garbage collection of referenced
+		 * structures.
+		 */
+		public List<Scheme> toSchemeList() {
+			if(schemeCount<=0) {
+				return new ArrayList<Scheme>();
+			} else {
+				List<Scheme> schemeList = new ArrayList<Scheme>(schemeCount);
+				
+				Structure[] schemePtrStructs = schemes.toArray(schemeCount);
+				
+				for(int i=0; i<schemeCount; i++) {
+					SchemePointerByReference spbr2 = (SchemePointerByReference)schemePtrStructs[i];
+					schemeList.add(spbr2.scheme.toScheme());
+				}
+				return schemeList;
+			}
+		}
+		
+		public void fillFrom(List<Scheme> schemeList) {
+			schemeCount = schemeList.size();
+			schemes = new SchemePointerByReference();
+			Structure[] schemePtrStructs = schemes.toArray(schemeCount);
+			
+			for(int i=0; i<this.schemeCount; i++) {
+				SchemePointerByReference spbr = (SchemePointerByReference)schemePtrStructs[i];
+				spbr.scheme = new SchemeStruct.ByRef();
+				spbr.scheme.fillFrom(schemeList.get(i));
+			}
+		}
+		
+		public int schemeCount;
+		public SchemePointerByReference schemes;
+	}
+	
+	static class TeamlistStruct extends Structure {
+		public static class ByVal extends TeamlistStruct implements Structure.ByValue {}
+		public static class ByRef extends TeamlistStruct implements Structure.ByReference {}
+		private static String[] FIELD_ORDER = new String[] {"teamCount", "teams"};
+		
+		public TeamlistStruct() { super(); setFieldOrder(FIELD_ORDER); }
+		public TeamlistStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
+		
+		public int teamCount;
+		public Pointer teams;
+	}
+	
+	static class GameSetupStruct extends Structure {
+		public static class ByVal extends GameSetupStruct implements Structure.ByValue {}
+		public static class ByRef extends GameSetupStruct implements Structure.ByReference {}
+		private static String[] FIELD_ORDER = new String[] {"script", "gamescheme", "map", "teamlist"};
+		
+		public GameSetupStruct() { super(); setFieldOrder(FIELD_ORDER); }
+		public GameSetupStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
+		
+		public static GameSetupStruct from(GameConfig conf) {
+			GameSetupStruct gss = new GameSetupStruct();
+			gss.gamescheme = new SchemeStruct.ByRef();
+			gss.gamescheme.fillFrom(conf.scheme);
+			gss.map = new MapRecipeStruct.ByRef();
+			// TODO gss.map.fillFrom(conf.map, conf.seed, conf.theme);
+			gss.script = conf.style;
+			gss.teamlist = new TeamlistStruct.ByRef();
+			// TODO gss.teamlist.fillFrom(conf.teams, conf.weapon);
+			return gss;
+		}
+
+		public String script;
+		public SchemeStruct.ByRef gamescheme;
+		public MapRecipeStruct.ByRef map;
+		public TeamlistStruct.ByRef teamlist;
+	}
+	
+	public static interface VoidCallback extends Callback {
+		void callback(Pointer context);
+	}
+	
+	public static interface StrCallback extends Callback {
+		void callback(Pointer context, String arg1);
+	}
+	
+	public static interface IntCallback extends Callback {
+		void callback(Pointer context, int arg1);
+	}
+	
+	public static interface IntStrCallback extends Callback {
+		void callback(Pointer context, int arg1, String arg2);
+	}
+	
+	public static interface StrIntCallback extends Callback {
+		void callback(Pointer context, String arg1, int arg2);
+	}
+	
+	public static interface StrStrCallback extends Callback {
+		void callback(Pointer context, String arg1, String arg2);
+	}
+	
+	public static interface RoomCallback extends Callback {
+		void callback(Pointer context, RoomPtr arg1);
+	}
+	
+	public static interface RoomListCallback extends Callback {
+		void callback(Pointer context, RoomArrayPtr arg1, int count);
+	}
+	
+	public static interface StrRoomCallback extends Callback {
+		void callback(Pointer context, String arg1, RoomPtr arg2);
+	}
+	
+	public static interface BoolCallback extends Callback {
+		void callback(Pointer context, boolean arg1);
+	}
+	
+	public static interface StrBoolCallback extends Callback {
+		void callback(Pointer context, String arg1, boolean arg2);
+	}
+	
+	public static interface TeamCallback extends Callback {
+		void callback(Pointer context, TeamPtr arg1);
+	}
+	
+	public static interface BytesCallback extends Callback {
+		void callback(Pointer context, Pointer buffer, NativeLong size);
+	}
+	
+	public static interface BytesBoolCallback extends Callback {
+		void callback(Pointer context, Pointer buffer, NativeLong size, boolean arg3);
+	}
+	
+	public static interface SchemeCallback extends Callback {
+		void callback(Pointer context, SchemePtr arg1);
+	}
+	
+	public static interface MapIntCallback extends Callback {
+		void callback(Pointer context, MapRecipePtr arg1, int arg2);
+	}
+	
+	public static interface WeaponsetCallback extends Callback {
+		void callback(Pointer context, WeaponsetPtr arg1);
+	}
+	
+	public static interface MapimageCallback extends Callback {
+		void callback(Pointer context, Pointer buffer, int hedgehogCount);
+	}
+	
+	public static interface LogCallback extends Callback {
+		void callback(int level, String logMessage);
+	}
+	
+    int flib_init();
+    void flib_quit();
+	
+	NetconnPtr flib_netconn_create(String playerName, MetaschemePtr meta, String dataDirPath, String host, int port);
+	void flib_netconn_destroy(NetconnPtr conn);
+
+	void flib_netconn_tick(NetconnPtr conn);
+	boolean flib_netconn_is_chief(NetconnPtr conn);
+	boolean flib_netconn_is_in_room_context(NetconnPtr conn);
+	String flib_netconn_get_playername(NetconnPtr conn);
+	GameSetupPtr flib_netconn_create_gamesetup(NetconnPtr conn);
+	int flib_netconn_send_quit(NetconnPtr conn, String quitmsg);
+	int flib_netconn_send_chat(NetconnPtr conn, String chat);
+	int flib_netconn_send_teamchat(NetconnPtr conn, String msg);
+	int flib_netconn_send_password(NetconnPtr conn, String passwd);
+	int flib_netconn_send_nick(NetconnPtr conn, String nick);
+	int flib_netconn_send_request_roomlist(NetconnPtr conn);
+	int flib_netconn_send_joinRoom(NetconnPtr conn, String room);
+	int flib_netconn_send_createRoom(NetconnPtr conn, String room);
+	int flib_netconn_send_renameRoom(NetconnPtr conn, String roomName);
+	int flib_netconn_send_leaveRoom(NetconnPtr conn, String msg);
+	int flib_netconn_send_toggleReady(NetconnPtr conn);
+	int flib_netconn_send_addTeam(NetconnPtr conn, TeamPtr team);
+	int flib_netconn_send_removeTeam(NetconnPtr conn, String teamname);
+	int flib_netconn_send_engineMessage(NetconnPtr conn, Buffer message, NativeLong size); // TODO check if NativeLong==size_t
+	int flib_netconn_send_teamHogCount(NetconnPtr conn, String teamname, int hogcount);
+	int flib_netconn_send_teamColor(NetconnPtr conn, String teamname, int colorIndex);
+	int flib_netconn_send_weaponset(NetconnPtr conn, WeaponsetPtr weaponset);
+	int flib_netconn_send_map(NetconnPtr conn, MapRecipePtr map);
+	int flib_netconn_send_mapName(NetconnPtr conn, String mapName);
+	int flib_netconn_send_mapGen(NetconnPtr conn, int mapGen);
+	int flib_netconn_send_mapTemplate(NetconnPtr conn, int templateFilter);
+	int flib_netconn_send_mapMazeSize(NetconnPtr conn, int mazeSize);
+	int flib_netconn_send_mapSeed(NetconnPtr conn, String seed);
+	int flib_netconn_send_mapTheme(NetconnPtr conn, String theme);
+	int flib_netconn_send_mapDrawdata(NetconnPtr conn, Buffer drawData, NativeLong size);
+	int flib_netconn_send_script(NetconnPtr conn, String scriptName);
+	int flib_netconn_send_scheme(NetconnPtr conn, SchemePtr scheme);
+	int flib_netconn_send_roundfinished(NetconnPtr conn, boolean withoutError);
+	int flib_netconn_send_ban(NetconnPtr conn, String playerName);
+	int flib_netconn_send_kick(NetconnPtr conn, String playerName);
+	int flib_netconn_send_playerInfo(NetconnPtr conn, String playerName);
+	int flib_netconn_send_playerFollow(NetconnPtr conn, String playerName);
+	int flib_netconn_send_startGame(NetconnPtr conn);
+	int flib_netconn_send_toggleRestrictJoins(NetconnPtr conn);
+	int flib_netconn_send_toggleRestrictTeams(NetconnPtr conn);
+	int flib_netconn_send_clearAccountsCache(NetconnPtr conn);
+	int flib_netconn_send_setServerVar(NetconnPtr conn, String name, String value);
+	int flib_netconn_send_getServerVars(NetconnPtr conn);
+	
+	void flib_netconn_onMessage(NetconnPtr conn, IntStrCallback callback, Pointer context);
+	void flib_netconn_onChat(NetconnPtr conn, StrStrCallback callback, Pointer context);
+	void flib_netconn_onConnected(NetconnPtr conn, VoidCallback callback, Pointer context);
+	void flib_netconn_onDisconnected(NetconnPtr conn, IntStrCallback callback, Pointer context);
+	void flib_netconn_onRoomlist(NetconnPtr conn, RoomListCallback callback, Pointer context);
+	void flib_netconn_onRoomAdd(NetconnPtr conn, RoomCallback callback, Pointer context);
+	void flib_netconn_onRoomDelete(NetconnPtr conn, StrCallback callback, Pointer context);
+	void flib_netconn_onRoomUpdate(NetconnPtr conn, StrRoomCallback callback, Pointer context);
+	void flib_netconn_onLobbyJoin(NetconnPtr conn, StrCallback callback, Pointer context);
+	void flib_netconn_onLobbyLeave(NetconnPtr conn, StrStrCallback callback, Pointer context);
+	void flib_netconn_onNickTaken(NetconnPtr conn, StrCallback callback, Pointer context);
+	void flib_netconn_onPasswordRequest(NetconnPtr conn, StrCallback callback, Pointer context);
+	void flib_netconn_onEnterRoom(NetconnPtr conn, BoolCallback callback, Pointer context);
+	void flib_netconn_onRoomChiefStatus(NetconnPtr conn, BoolCallback callback, Pointer context);
+	void flib_netconn_onReadyState(NetconnPtr conn, StrBoolCallback callback, Pointer context);
+	void flib_netconn_onLeaveRoom(NetconnPtr conn, IntStrCallback callback, Pointer context);
+	void flib_netconn_onTeamAdd(NetconnPtr conn, TeamCallback callback, Pointer context);
+	void flib_netconn_onTeamDelete(NetconnPtr conn, StrCallback callback, Pointer context);
+	void flib_netconn_onRoomJoin(NetconnPtr conn, StrCallback callback, Pointer context);
+	void flib_netconn_onRoomLeave(NetconnPtr conn, StrStrCallback callback, Pointer context);
+	void flib_netconn_onRunGame(NetconnPtr conn, VoidCallback callback, Pointer context);
+	void flib_netconn_onTeamAccepted(NetconnPtr conn, StrCallback callback, Pointer context);
+	void flib_netconn_onHogCountChanged(NetconnPtr conn, StrIntCallback callback, Pointer context);
+	void flib_netconn_onTeamColorChanged(NetconnPtr conn, StrIntCallback callback, Pointer context);
+	void flib_netconn_onEngineMessage(NetconnPtr conn, BytesCallback callback, Pointer context);
+	void flib_netconn_onCfgScheme(NetconnPtr conn, SchemeCallback callback, Pointer context);
+	void flib_netconn_onMapChanged(NetconnPtr conn, MapIntCallback callback, Pointer context);
+	void flib_netconn_onScriptChanged(NetconnPtr conn, StrCallback callback, Pointer context);
+	void flib_netconn_onWeaponsetChanged(NetconnPtr conn, WeaponsetCallback callback, Pointer context);
+	void flib_netconn_onAdminAccess(NetconnPtr conn, VoidCallback callback, Pointer context);
+	void flib_netconn_onServerVar(NetconnPtr conn, StrStrCallback callback, Pointer context);
+
+	// Gameconn
+	GameconnPtr flib_gameconn_create(String playerName, GameSetupPtr setup, boolean netgame);
+	GameconnPtr flib_gameconn_create_playdemo(Buffer demo, NativeLong size);
+	GameconnPtr flib_gameconn_create_loadgame(String playerName, Buffer save, NativeLong size);
+	GameconnPtr flib_gameconn_create_campaign(String playerName, String seed, String script);
+
+	void flib_gameconn_destroy(GameconnPtr conn);
+	int flib_gameconn_getport(GameconnPtr conn);
+	void flib_gameconn_tick(GameconnPtr conn);
+
+	int flib_gameconn_send_enginemsg(GameconnPtr conn, Buffer data, NativeLong len);
+	int flib_gameconn_send_textmsg(GameconnPtr conn, int msgtype, String msg);
+	int flib_gameconn_send_chatmsg(GameconnPtr conn, String playername, String msg);
+	
+	void flib_gameconn_onConnect(GameconnPtr conn, VoidCallback callback, Pointer context);
+	void flib_gameconn_onDisconnect(GameconnPtr conn, IntCallback callback, Pointer context);
+	void flib_gameconn_onErrorMessage(GameconnPtr conn, StrCallback callback, Pointer context);
+	void flib_gameconn_onChat(GameconnPtr conn, StrBoolCallback callback, Pointer context);
+	void flib_gameconn_onGameRecorded(GameconnPtr conn, BytesBoolCallback callback, Pointer context);
+	void flib_gameconn_onEngineMessage(GameconnPtr conn, BytesCallback callback, Pointer context);
+	
+	// MapConn
+	MapconnPtr flib_mapconn_create(MapRecipePtr mapdesc);
+	void flib_mapconn_destroy(MapconnPtr conn);
+	int flib_mapconn_getport(MapconnPtr conn);
+	void flib_mapconn_onSuccess(MapconnPtr conn, MapimageCallback callback, Pointer context);
+	void flib_mapconn_onFailure(MapconnPtr conn, StrCallback callback, Pointer context);
+	void flib_mapconn_tick(MapconnPtr conn);
+	
+	// GameSetup
+	void flib_gamesetup_destroy(GameSetupPtr gamesetup);
+	GameSetupPtr flib_gamesetup_copy(GameSetupPtr gamesetup);
+	
+	// MapRecipe
+	public static final int MAPGEN_REGULAR = 0;
+	public static final int MAPGEN_MAZE = 1;
+	public static final int MAPGEN_DRAWN = 2;
+	public static final int MAPGEN_NAMED = 3;
+
+	public static final int TEMPLATEFILTER_ALL = 0;
+	public static final int TEMPLATEFILTER_SMALL = 1;
+	public static final int TEMPLATEFILTER_MEDIUM = 2;
+	public static final int TEMPLATEFILTER_LARGE = 3;
+	public static final int TEMPLATEFILTER_CAVERN = 4;
+	public static final int TEMPLATEFILTER_WACKY = 5;
+
+	public static final int MAZE_SIZE_SMALL_TUNNELS = 0;
+	public static final int MAZE_SIZE_MEDIUM_TUNNELS = 1;
+	public static final int MAZE_SIZE_LARGE_TUNNELS = 2;
+	public static final int MAZE_SIZE_SMALL_ISLANDS = 3;
+	public static final int MAZE_SIZE_MEDIUM_ISLANDS = 4;
+	public static final int MAZE_SIZE_LARGE_ISLANDS = 5;
+	
+	MapRecipePtr flib_map_create_regular(String seed, String theme, int templateFilter);
+	MapRecipePtr flib_map_create_maze(String seed, String theme, int mazeSize);
+	MapRecipePtr flib_map_create_named(String seed, String name);
+	MapRecipePtr flib_map_create_drawn(String seed, String theme, Buffer drawData, NativeLong drawDataSize);
+	MapRecipePtr flib_map_copy(MapRecipePtr map);
+	MapRecipePtr flib_map_retain(MapRecipePtr map);
+	void flib_map_release(MapRecipePtr map);
+	
+	// Metascheme
+	MetaschemePtr flib_metascheme_from_ini(String filename);
+	MetaschemePtr flib_metascheme_retain(MetaschemePtr metainfo);
+	void flib_metascheme_release(MetaschemePtr metainfo);
+
+	// Scheme lists
+	SchemelistPtr flib_schemelist_from_ini(MetaschemePtr meta, String filename);
+	int flib_schemelist_to_ini(String filename, SchemelistPtr list);
+	void flib_schemelist_destroy(SchemelistPtr list);
+	
+	// Team
+	void flib_team_destroy(TeamPtr team);
+	TeamPtr flib_team_from_ini(String filename);
+	int flib_team_to_ini(String filename, TeamPtr team);
+	void flib_team_set_weaponset(TeamPtr team, WeaponsetPtr set);
+	void flib_team_set_health(TeamPtr team, int health);
+	
+	// Logging
+	public static final int FLIB_LOGLEVEL_ALL = -100;
+	public static final int FLIB_LOGLEVEL_DEBUG = -1;
+	public static final int FLIB_LOGLEVEL_INFO = 0;
+	public static final int FLIB_LOGLEVEL_WARNING = 1;
+	public static final int FLIB_LOGLEVEL_ERROR = 2;
+	public static final int FLIB_LOGLEVEL_NONE = 100;
+	
+    void flib_log_setLevel(int level);
+    void flib_log_setCallback(LogCallback callback);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/FrontlibTypeMapper.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,27 @@
+package org.hedgewars.hedgeroid.frontlib;
+
+import com.sun.jna.DefaultTypeMapper;
+import com.sun.jna.FromNativeContext;
+import com.sun.jna.ToNativeContext;
+import com.sun.jna.TypeConverter;
+import com.sun.jna.TypeMapper;
+
+class FrontlibTypeMapper extends DefaultTypeMapper {
+    public static final TypeMapper INSTANCE = new FrontlibTypeMapper();
+    
+    protected FrontlibTypeMapper() {
+        addTypeConverter(Boolean.class, new BooleanConverter());
+    }
+}
+
+class BooleanConverter implements TypeConverter {
+    public Class<Byte> nativeType() {
+        return Byte.class;
+    }
+	public Object fromNative(Object value, FromNativeContext context) {
+		return ((Byte)value).intValue() != 0 ? Boolean.TRUE : Boolean.FALSE;
+	}
+	public Object toNative(Object value, ToNativeContext context) {
+		return Byte.valueOf((byte)(Boolean.TRUE.equals(value) ? 1 : 0));
+	}
+}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/FrontlibTypeMapper.java	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-package org.hedgewars.hedgeroid.netplay;
-
-import java.io.UnsupportedEncodingException;
-
-import com.sun.jna.DefaultTypeMapper;
-import com.sun.jna.FromNativeContext;
-import com.sun.jna.FromNativeConverter;
-import com.sun.jna.Native;
-import com.sun.jna.Pointer;
-import com.sun.jna.ToNativeContext;
-import com.sun.jna.ToNativeConverter;
-import com.sun.jna.TypeConverter;
-import com.sun.jna.TypeMapper;
-
-public class FrontlibTypeMapper extends DefaultTypeMapper {
-    public static final TypeMapper INSTANCE = new FrontlibTypeMapper();
-    
-    protected FrontlibTypeMapper() {
-        addTypeConverter(Boolean.class, new BooleanConverter());
-		addToNativeConverter(String.class, new StringToNativeConverter());
-		addFromNativeConverter(String.class, new StringFromNativeConverter());
-    }
-}
-
-class BooleanConverter implements TypeConverter {
-    public Class<Byte> nativeType() {
-        return Byte.class;
-    }
-	public Object fromNative(Object value, FromNativeContext context) {
-		return ((Byte)value).intValue() != 0 ? Boolean.TRUE : Boolean.FALSE;
-	}
-	public Object toNative(Object value, ToNativeContext context) {
-		return Byte.valueOf((byte)(Boolean.TRUE.equals(value) ? 1 : 0));
-	}
-}
-
-class StringToNativeConverter implements ToNativeConverter {
-	public byte[] toNative(Object value, ToNativeContext context) {
-    	try {
-			return value==null ? null : Native.toByteArray((String)value, "UTF-8");
-		} catch (UnsupportedEncodingException e) {
-			throw new AssertionError(e); // Never happens
-		}
-	}
-	
-	public Class<byte[]> nativeType() {
-		return byte[].class;
-	}
-}
-
-class StringFromNativeConverter implements FromNativeConverter {
-	public String fromNative(Object value, FromNativeContext context) {
-		Pointer p = (Pointer)value;
-		if(p==null) {
-			return null;
-		}
-		int i=0;
-		while(p.getByte(i) != 0) {
-			i++;
-		}
-    	try {
-			return new String(p.getByteArray(0, i), "UTF-8");
-		} catch (UnsupportedEncodingException e) {
-			throw new AssertionError(e); // Never happens
-		}
-	}
-	
-	public Class<Pointer> nativeType() {
-		return Pointer.class;
-	}
-}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/JnaFrontlib.java	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,371 +0,0 @@
-package org.hedgewars.hedgeroid.netplay;
-import java.nio.Buffer;
-import java.util.Collections;
-
-import android.util.Log;
-
-import com.sun.jna.Callback;
-import com.sun.jna.Library;
-import com.sun.jna.Native;
-import com.sun.jna.NativeLong;
-import com.sun.jna.Pointer;
-import com.sun.jna.PointerType;
-import com.sun.jna.Structure;
-
-class Flib {
-	static {
-		System.loadLibrary("SDL_net");
-	}
-	public static final JnaFrontlib INSTANCE = (JnaFrontlib)Native.loadLibrary("frontlib", JnaFrontlib.class, Collections.singletonMap(Library.OPTION_TYPE_MAPPER, FrontlibTypeMapper.INSTANCE));
-	
-	// Hook frontlib logging into Android logging
-	private static final JnaFrontlib.LogCallback logCb = new JnaFrontlib.LogCallback() {
-		public void callback(int level, String message) {
-			if(level >= JnaFrontlib.FLIB_LOGLEVEL_ERROR) {
-				Log.e("Frontlib", message);
-			} else if(level == JnaFrontlib.FLIB_LOGLEVEL_WARNING){
-				Log.w("Frontlib", message);
-			} else if(level == JnaFrontlib.FLIB_LOGLEVEL_INFO){
-				Log.i("Frontlib", message);
-			} else if(level <= JnaFrontlib.FLIB_LOGLEVEL_DEBUG){
-				Log.d("Frontlib", message);
-			}
-		}
-	};
-	static {
-		INSTANCE.flib_log_setLevel(JnaFrontlib.FLIB_LOGLEVEL_WARNING);
-		INSTANCE.flib_log_setCallback(logCb);
-	}
-}
-
-public interface JnaFrontlib extends Library {
-	static final int NETCONN_STATE_CONNECTING = 0;
-	static final int NETCONN_STATE_LOBBY = 1;
-	static final int NETCONN_STATE_ROOM = 2;
-	static final int NETCONN_STATE_INGAME = 3;
-	static final int NETCONN_STATE_DISCONNECTED = 10;
-	
-	static final int NETCONN_DISCONNECT_NORMAL = 0;
-	static final int NETCONN_DISCONNECT_SERVER_TOO_OLD = 1;
-	static final int NETCONN_DISCONNECT_AUTH_FAILED = 2;
-	static final int NETCONN_DISCONNECT_CONNLOST = 3;
-	static final int NETCONN_DISCONNECT_INTERNAL_ERROR = 100;
-	
-	static final int NETCONN_ROOMLEAVE_ABANDONED = 0;
-	static final int NETCONN_ROOMLEAVE_KICKED = 1;
-	
-	static final int NETCONN_MSG_TYPE_PLAYERINFO = 0;
-	static final int NETCONN_MSG_TYPE_SERVERMESSAGE = 1;
-	static final int NETCONN_MSG_TYPE_WARNING = 2;
-	static final int NETCONN_MSG_TYPE_ERROR = 3;
-	
-	static final int NETCONN_MAPCHANGE_FULL = 0;
-	static final int NETCONN_MAPCHANGE_MAP = 1;
-	static final int NETCONN_MAPCHANGE_MAPGEN = 2;
-	static final int NETCONN_MAPCHANGE_DRAWNMAP = 3;
-	static final int NETCONN_MAPCHANGE_MAZE_SIZE = 4;
-	static final int NETCONN_MAPCHANGE_TEMPLATE = 5;
-	static final int NETCONN_MAPCHANGE_THEME = 6;
-	static final int NETCONN_MAPCHANGE_SEED = 7;
-	
-	static final int  GAME_END_FINISHED = 0;
-	static final int  GAME_END_INTERRUPTED = 1;
-	static final int  GAME_END_HALTED = 2;
-	static final int  GAME_END_ERROR = 3;
-	
-	static class NetconnPtr extends PointerType { }
-	static class MapconnPtr extends PointerType { }
-	static class GameconnPtr extends PointerType { }
-	static class MetaschemePtr extends PointerType { }
-	
-	static class RoomArrayPtr extends PointerType { 
-		/**
-		 * Returns the (native-owned) rooms in this list
-		 */
-		public Room[] getRooms(int count) {
-			Pointer ptr = getPointer();
-			if(ptr == null) {
-				return new Room[0];
-			}
-			Pointer[] untypedPtrs = ptr.getPointerArray(0, count);
-			Room[] result = new Room[count];
-			for(int i=0; i<count; i++) {
-				result[i] = RoomPtr.deref(untypedPtrs[i]);
-			}
-			return result;
-		}
-	}
-	
-	static class RoomPtr extends PointerType {
-		public RoomPtr() { super(); }
-		public RoomPtr(Pointer ptr) { super(ptr); }
-		
-		public Room deref() {
-			return deref(getPointer());
-		}
-		
-		public static Room deref(Pointer p) {
-			RoomStruct r = new RoomStruct(p);
-			r.read();
-			return new Room(r.name, r.map, r.scheme, r.weapons, r.owner, r.playerCount, r.teamCount, r.inProgress);
-		}
-	}
-	
-	static class TeamPtr extends PointerType { }
-	static class WeaponsetPtr extends PointerType { }
-	static class MapRecipePtr extends PointerType { }
-	static class SchemePtr extends PointerType { }
-	static class GameSetupPtr extends PointerType { }
-	
-	static class RoomStruct extends Structure {
-		public static class byVal extends RoomStruct implements Structure.ByValue {}
-		public static class byRef extends RoomStruct implements Structure.ByReference {}
-		private static String[] FIELD_ORDER = new String[] {"inProgress", "name", "playerCount", "teamCount", "owner", "map", "scheme", "weapons"};
-		
-		public RoomStruct() { super(); setFieldOrder(FIELD_ORDER); }
-		public RoomStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
-		
-	    public boolean inProgress;
-	    public String name;
-	    public int playerCount;
-	    public int teamCount;
-	    public String owner;
-	    public String map;
-	    public String scheme;
-	    public String weapons;
-	}
-	
-	public static interface VoidCallback extends Callback {
-		void callback(Pointer context);
-	}
-	
-	public static interface StrCallback extends Callback {
-		void callback(Pointer context, String arg1);
-	}
-	
-	public static interface IntCallback extends Callback {
-		void callback(Pointer context, int arg1);
-	}
-	
-	public static interface IntStrCallback extends Callback {
-		void callback(Pointer context, int arg1, String arg2);
-	}
-	
-	public static interface StrIntCallback extends Callback {
-		void callback(Pointer context, String arg1, int arg2);
-	}
-	
-	public static interface StrStrCallback extends Callback {
-		void callback(Pointer context, String arg1, String arg2);
-	}
-	
-	public static interface RoomCallback extends Callback {
-		void callback(Pointer context, RoomPtr arg1);
-	}
-	
-	public static interface RoomListCallback extends Callback {
-		void callback(Pointer context, RoomArrayPtr arg1, int count);
-	}
-	
-	public static interface StrRoomCallback extends Callback {
-		void callback(Pointer context, String arg1, RoomPtr arg2);
-	}
-	
-	public static interface BoolCallback extends Callback {
-		void callback(Pointer context, boolean arg1);
-	}
-	
-	public static interface StrBoolCallback extends Callback {
-		void callback(Pointer context, String arg1, boolean arg2);
-	}
-	
-	public static interface TeamCallback extends Callback {
-		void callback(Pointer context, TeamPtr arg1);
-	}
-	
-	public static interface BytesCallback extends Callback {
-		void callback(Pointer context, Pointer buffer, NativeLong size);
-	}
-	
-	public static interface BytesBoolCallback extends Callback {
-		void callback(Pointer context, Pointer buffer, NativeLong size, boolean arg3);
-	}
-	
-	public static interface SchemeCallback extends Callback {
-		void callback(Pointer context, SchemePtr arg1);
-	}
-	
-	public static interface MapIntCallback extends Callback {
-		void callback(Pointer context, MapRecipePtr arg1, int arg2);
-	}
-	
-	public static interface WeaponsetCallback extends Callback {
-		void callback(Pointer context, WeaponsetPtr arg1);
-	}
-	
-	public static interface MapimageCallback extends Callback {
-		void callback(Pointer context, Pointer buffer, int hedgehogCount);
-	}
-	
-	public static interface LogCallback extends Callback {
-		void callback(int level, String logMessage);
-	}
-	
-    int flib_init();
-    void flib_quit();
-	
-	NetconnPtr flib_netconn_create(String playerName, MetaschemePtr meta, String dataDirPath, String host, int port);
-	void flib_netconn_destroy(NetconnPtr conn);
-
-	void flib_netconn_tick(NetconnPtr conn);
-	boolean flib_netconn_is_chief(NetconnPtr conn);
-	boolean flib_netconn_is_in_room_context(NetconnPtr conn);
-	String flib_netconn_get_playername(NetconnPtr conn);
-	GameSetupPtr flib_netconn_create_gamesetup(NetconnPtr conn);
-	int flib_netconn_send_quit(NetconnPtr conn, String quitmsg);
-	int flib_netconn_send_chat(NetconnPtr conn, String chat);
-	int flib_netconn_send_teamchat(NetconnPtr conn, String msg);
-	int flib_netconn_send_password(NetconnPtr conn, String passwd);
-	int flib_netconn_send_nick(NetconnPtr conn, String nick);
-	int flib_netconn_send_request_roomlist(NetconnPtr conn);
-	int flib_netconn_send_joinRoom(NetconnPtr conn, String room);
-	int flib_netconn_send_createRoom(NetconnPtr conn, String room);
-	int flib_netconn_send_renameRoom(NetconnPtr conn, String roomName);
-	int flib_netconn_send_leaveRoom(NetconnPtr conn, String msg);
-	int flib_netconn_send_toggleReady(NetconnPtr conn);
-	int flib_netconn_send_addTeam(NetconnPtr conn, TeamPtr team);
-	int flib_netconn_send_removeTeam(NetconnPtr conn, String teamname);
-	int flib_netconn_send_engineMessage(NetconnPtr conn, Buffer message, NativeLong size); // TODO check if NativeLong==size_t
-	int flib_netconn_send_teamHogCount(NetconnPtr conn, String teamname, int hogcount);
-	int flib_netconn_send_teamColor(NetconnPtr conn, String teamname, int colorIndex);
-	int flib_netconn_send_weaponset(NetconnPtr conn, WeaponsetPtr weaponset);
-	int flib_netconn_send_map(NetconnPtr conn, MapRecipePtr map);
-	int flib_netconn_send_mapName(NetconnPtr conn, String mapName);
-	int flib_netconn_send_mapGen(NetconnPtr conn, int mapGen);
-	int flib_netconn_send_mapTemplate(NetconnPtr conn, int templateFilter);
-	int flib_netconn_send_mapMazeSize(NetconnPtr conn, int mazeSize);
-	int flib_netconn_send_mapSeed(NetconnPtr conn, String seed);
-	int flib_netconn_send_mapTheme(NetconnPtr conn, String theme);
-	int flib_netconn_send_mapDrawdata(NetconnPtr conn, Buffer drawData, NativeLong size);
-	int flib_netconn_send_script(NetconnPtr conn, String scriptName);
-	int flib_netconn_send_scheme(NetconnPtr conn, SchemePtr scheme);
-	int flib_netconn_send_roundfinished(NetconnPtr conn, boolean withoutError);
-	int flib_netconn_send_ban(NetconnPtr conn, String playerName);
-	int flib_netconn_send_kick(NetconnPtr conn, String playerName);
-	int flib_netconn_send_playerInfo(NetconnPtr conn, String playerName);
-	int flib_netconn_send_playerFollow(NetconnPtr conn, String playerName);
-	int flib_netconn_send_startGame(NetconnPtr conn);
-	int flib_netconn_send_toggleRestrictJoins(NetconnPtr conn);
-	int flib_netconn_send_toggleRestrictTeams(NetconnPtr conn);
-	int flib_netconn_send_clearAccountsCache(NetconnPtr conn);
-	int flib_netconn_send_setServerVar(NetconnPtr conn, String name, String value);
-	int flib_netconn_send_getServerVars(NetconnPtr conn);
-	
-	void flib_netconn_onMessage(NetconnPtr conn, IntStrCallback callback, Pointer context);
-	void flib_netconn_onChat(NetconnPtr conn, StrStrCallback callback, Pointer context);
-	void flib_netconn_onConnected(NetconnPtr conn, VoidCallback callback, Pointer context);
-	void flib_netconn_onDisconnected(NetconnPtr conn, IntStrCallback callback, Pointer context);
-	void flib_netconn_onRoomlist(NetconnPtr conn, RoomListCallback callback, Pointer context);
-	void flib_netconn_onRoomAdd(NetconnPtr conn, RoomCallback callback, Pointer context);
-	void flib_netconn_onRoomDelete(NetconnPtr conn, StrCallback callback, Pointer context);
-	void flib_netconn_onRoomUpdate(NetconnPtr conn, StrRoomCallback callback, Pointer context);
-	void flib_netconn_onLobbyJoin(NetconnPtr conn, StrCallback callback, Pointer context);
-	void flib_netconn_onLobbyLeave(NetconnPtr conn, StrStrCallback callback, Pointer context);
-	void flib_netconn_onNickTaken(NetconnPtr conn, StrCallback callback, Pointer context);
-	void flib_netconn_onPasswordRequest(NetconnPtr conn, StrCallback callback, Pointer context);
-	void flib_netconn_onEnterRoom(NetconnPtr conn, BoolCallback callback, Pointer context);
-	void flib_netconn_onRoomChiefStatus(NetconnPtr conn, BoolCallback callback, Pointer context);
-	void flib_netconn_onReadyState(NetconnPtr conn, StrBoolCallback callback, Pointer context);
-	void flib_netconn_onLeaveRoom(NetconnPtr conn, IntStrCallback callback, Pointer context);
-	void flib_netconn_onTeamAdd(NetconnPtr conn, TeamCallback callback, Pointer context);
-	void flib_netconn_onTeamDelete(NetconnPtr conn, StrCallback callback, Pointer context);
-	void flib_netconn_onRoomJoin(NetconnPtr conn, StrCallback callback, Pointer context);
-	void flib_netconn_onRoomLeave(NetconnPtr conn, StrStrCallback callback, Pointer context);
-	void flib_netconn_onRunGame(NetconnPtr conn, VoidCallback callback, Pointer context);
-	void flib_netconn_onTeamAccepted(NetconnPtr conn, StrCallback callback, Pointer context);
-	void flib_netconn_onHogCountChanged(NetconnPtr conn, StrIntCallback callback, Pointer context);
-	void flib_netconn_onTeamColorChanged(NetconnPtr conn, StrIntCallback callback, Pointer context);
-	void flib_netconn_onEngineMessage(NetconnPtr conn, BytesCallback callback, Pointer context);
-	void flib_netconn_onCfgScheme(NetconnPtr conn, SchemeCallback callback, Pointer context);
-	void flib_netconn_onMapChanged(NetconnPtr conn, MapIntCallback callback, Pointer context);
-	void flib_netconn_onScriptChanged(NetconnPtr conn, StrCallback callback, Pointer context);
-	void flib_netconn_onWeaponsetChanged(NetconnPtr conn, WeaponsetCallback callback, Pointer context);
-	void flib_netconn_onAdminAccess(NetconnPtr conn, VoidCallback callback, Pointer context);
-	void flib_netconn_onServerVar(NetconnPtr conn, StrStrCallback callback, Pointer context);
-
-	// Gameconn
-	GameconnPtr flib_gameconn_create(String playerName, GameSetupPtr setup, boolean netgame);
-	GameconnPtr flib_gameconn_create_playdemo(Buffer demo, NativeLong size);
-	GameconnPtr flib_gameconn_create_loadgame(String playerName, Buffer save, NativeLong size);
-	GameconnPtr flib_gameconn_create_campaign(String playerName, String seed, String script);
-
-	void flib_gameconn_destroy(GameconnPtr conn);
-	int flib_gameconn_getport(GameconnPtr conn);
-	void flib_gameconn_tick(GameconnPtr conn);
-
-	int flib_gameconn_send_enginemsg(GameconnPtr conn, Buffer data, NativeLong len);
-	int flib_gameconn_send_textmsg(GameconnPtr conn, int msgtype, String msg);
-	int flib_gameconn_send_chatmsg(GameconnPtr conn, String playername, String msg);
-	
-	void flib_gameconn_onConnect(GameconnPtr conn, VoidCallback callback, Pointer context);
-	void flib_gameconn_onDisconnect(GameconnPtr conn, IntCallback callback, Pointer context);
-	void flib_gameconn_onErrorMessage(GameconnPtr conn, StrCallback callback, Pointer context);
-	void flib_gameconn_onChat(GameconnPtr conn, StrBoolCallback callback, Pointer context);
-	void flib_gameconn_onGameRecorded(GameconnPtr conn, BytesBoolCallback callback, Pointer context);
-	void flib_gameconn_onEngineMessage(GameconnPtr conn, BytesCallback callback, Pointer context);
-	
-	// MapConn
-	MapconnPtr flib_mapconn_create(MapRecipePtr mapdesc);
-	void flib_mapconn_destroy(MapconnPtr conn);
-	int flib_mapconn_getport(MapconnPtr conn);
-	void flib_mapconn_onSuccess(MapconnPtr conn, MapimageCallback callback, Pointer context);
-	void flib_mapconn_onFailure(MapconnPtr conn, StrCallback callback, Pointer context);
-	void flib_mapconn_tick(MapconnPtr conn);
-	
-	// GameSetup
-	void flib_gamesetup_destroy(GameSetupPtr gamesetup);
-	GameSetupPtr flib_gamesetup_copy(GameSetupPtr gamesetup);
-	
-	// MapRecipe
-	public static final int MAPGEN_REGULAR = 0;
-	public static final int MAPGEN_MAZE = 1;
-	public static final int MAPGEN_DRAWN = 2;
-	public static final int MAPGEN_NAMED = 3;
-
-	public static final int TEMPLATEFILTER_ALL = 0;
-	public static final int TEMPLATEFILTER_SMALL = 1;
-	public static final int TEMPLATEFILTER_MEDIUM = 2;
-	public static final int TEMPLATEFILTER_LARGE = 3;
-	public static final int TEMPLATEFILTER_CAVERN = 4;
-	public static final int TEMPLATEFILTER_WACKY = 5;
-
-	public static final int MAZE_SIZE_SMALL_TUNNELS = 0;
-	public static final int MAZE_SIZE_MEDIUM_TUNNELS = 1;
-	public static final int MAZE_SIZE_LARGE_TUNNELS = 2;
-	public static final int MAZE_SIZE_SMALL_ISLANDS = 3;
-	public static final int MAZE_SIZE_MEDIUM_ISLANDS = 4;
-	public static final int MAZE_SIZE_LARGE_ISLANDS = 5;
-	
-	MapRecipePtr flib_map_create_regular(String seed, String theme, int templateFilter);
-	MapRecipePtr flib_map_create_maze(String seed, String theme, int mazeSize);
-	MapRecipePtr flib_map_create_named(String seed, String name);
-	MapRecipePtr flib_map_create_drawn(String seed, String theme, Buffer drawData, NativeLong drawDataSize);
-	MapRecipePtr flib_map_copy(MapRecipePtr map);
-	MapRecipePtr flib_map_retain(MapRecipePtr map);
-	void flib_map_release(MapRecipePtr map);
-	
-	// Metascheme
-	MetaschemePtr flib_metascheme_from_ini(String filename);
-	MetaschemePtr flib_metascheme_retain(MetaschemePtr metainfo);
-	void flib_metascheme_release(MetaschemePtr metainfo);
-	
-	public static final int FLIB_LOGLEVEL_ALL = -100;
-	public static final int FLIB_LOGLEVEL_DEBUG = -1;
-	public static final int FLIB_LOGLEVEL_INFO = 0;
-	public static final int FLIB_LOGLEVEL_WARNING = 1;
-	public static final int FLIB_LOGLEVEL_ERROR = 2;
-	public static final int FLIB_LOGLEVEL_NONE = 100;
-	
-    void flib_log_setLevel(int level);
-    void flib_log_setCallback(LogCallback callback);
-}
\ No newline at end of file
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/LobbyActivity.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/LobbyActivity.java	Mon Aug 06 22:39:36 2012 +0200
@@ -1,7 +1,6 @@
 package org.hedgewars.hedgeroid.netplay;
 
 import org.hedgewars.hedgeroid.R;
-import org.hedgewars.hedgeroid.StartGameActivity;
 import org.hedgewars.hedgeroid.netplay.Netplay.State;
 import org.hedgewars.hedgeroid.netplay.NetplayStateFragment.NetplayStateListener;
 import org.hedgewars.hedgeroid.netplay.TextInputDialog.TextInputDialogListener;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/LobbyPlayerlist.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,13 @@
+package org.hedgewars.hedgeroid.netplay;
+
+import org.hedgewars.hedgeroid.Datastructures.Player;
+
+import android.util.Pair;
+
+public class LobbyPlayerlist extends ObservableTreeMap<String, Pair<Player, Long>> {
+	private long nextId = 1;
+	
+	public void addPlayerWithNewId(String name) {
+		put(name, Pair.create(new Player(name), nextId++));
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/LobbyPlayerlistAdapter.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,58 @@
+package org.hedgewars.hedgeroid.netplay;
+
+import java.util.Comparator;
+
+import org.hedgewars.hedgeroid.R;
+import org.hedgewars.hedgeroid.Datastructures.Player;
+
+import android.content.Context;
+import android.util.Pair;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class LobbyPlayerlistAdapter extends ObservableTreeMapAdapter<String, Pair<Player, Long>> {
+	private Context context;
+	
+	public LobbyPlayerlistAdapter(Context context) {
+		this.context = context;
+	}
+	
+	@Override
+	protected Comparator<Pair<Player, Long>> getEntryOrder() {
+		return AlphabeticalOrderComparator.INSTANCE;
+	}
+
+	public Player getItem(int position) {
+		return getEntries().get(position).first;
+	}
+
+	public long getItemId(int position) {
+		return getEntries().get(position).second;
+	}
+
+	public boolean hasStableIds() {
+		return true;
+	}
+	
+	public View getView(int position, View convertView, ViewGroup parent) {
+		View v = convertView;
+		if (v == null) {
+			LayoutInflater vi = LayoutInflater.from(context);
+			v = vi.inflate(R.layout.listview_player, null);
+		}
+
+		String player = getItem(position).name;
+		TextView username = (TextView) v.findViewById(android.R.id.text1);
+		username.setText(player);
+		return v;
+	}
+	
+	private static final class AlphabeticalOrderComparator implements Comparator<Pair<Player, Long>> {
+		public static final AlphabeticalOrderComparator INSTANCE = new AlphabeticalOrderComparator();
+		public int compare(Pair<Player, Long> lhs, Pair<Player, Long> rhs) {
+			return lhs.first.name.compareToIgnoreCase(rhs.first.name);
+		};
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/LobbyPlayerlistFragment.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,74 @@
+package org.hedgewars.hedgeroid.netplay;
+
+import org.hedgewars.hedgeroid.R;
+import org.hedgewars.hedgeroid.Datastructures.Player;
+
+import android.os.Bundle;
+import android.support.v4.app.ListFragment;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.LayoutInflater;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView.AdapterContextMenuInfo;
+
+public class LobbyPlayerlistFragment extends ListFragment {
+	private Netplay netplay;
+	private LobbyPlayerlistAdapter adapter;
+	
+	@Override
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		netplay = Netplay.getAppInstance(getActivity().getApplicationContext());
+		adapter = new LobbyPlayerlistAdapter(getActivity());
+		adapter.setSource(netplay.lobbyPlayerlist);
+		setListAdapter(adapter);
+	}
+
+	@Override
+	public void onDestroy() {
+		super.onDestroy();
+		adapter.invalidate();
+	}
+	
+	@Override
+	public void onActivityCreated(Bundle savedInstanceState) {
+		super.onActivityCreated(savedInstanceState);
+		registerForContextMenu(getListView());
+	}
+
+	@Override
+	public void onCreateContextMenu(ContextMenu menu, View v,
+			ContextMenuInfo menuInfo) {
+		super.onCreateContextMenu(menu, v, menuInfo);
+		AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo;
+		MenuInflater inflater = getActivity().getMenuInflater();
+		inflater.inflate(R.menu.lobby_playerlist_context, menu);
+		menu.setHeaderIcon(R.drawable.human);
+		menu.setHeaderTitle(adapter.getItem(info.position).name);
+	}
+	
+	@Override
+	public boolean onContextItemSelected(MenuItem item) {
+		AdapterContextMenuInfo info = (AdapterContextMenuInfo)item.getMenuInfo();
+		Player player = adapter.getItem(info.position);
+		switch(item.getItemId()) {
+		case R.id.player_info:
+			netplay.sendPlayerInfoQuery(player.name);
+			return true;
+		case R.id.player_follow:
+			netplay.sendFollowPlayer(player.name);
+			return true;
+		default:
+			return super.onContextItemSelected(item);
+		}
+	}
+	
+	@Override
+	public View onCreateView(LayoutInflater inflater, ViewGroup container,
+			Bundle savedInstanceState) {
+		return inflater.inflate(R.layout.fragment_playerlist, container, false);
+	}
+}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/MessageLog.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/MessageLog.java	Mon Aug 06 22:39:36 2012 +0200
@@ -7,6 +7,7 @@
 import java.util.List;
 
 import org.hedgewars.hedgeroid.R;
+import org.hedgewars.hedgeroid.frontlib.Frontlib;
 
 import android.content.Context;
 import android.graphics.Color;
@@ -105,17 +106,17 @@
 	
 	void appendMessage(int type, String msg) {
 		switch(type) {
-		case JnaFrontlib.NETCONN_MSG_TYPE_ERROR:
+		case Frontlib.NETCONN_MSG_TYPE_ERROR:
 			append(withColor("***"+msg, ERROR_COLOR));
 			break;
-		case JnaFrontlib.NETCONN_MSG_TYPE_WARNING:
+		case Frontlib.NETCONN_MSG_TYPE_WARNING:
 			append(withColor("***"+msg, WARN_COLOR));
 			break;
-		case JnaFrontlib.NETCONN_MSG_TYPE_PLAYERINFO:
+		case Frontlib.NETCONN_MSG_TYPE_PLAYERINFO:
 			// TODO Display in popup?
 			append(withColor(msg.replace("\n", " "), PLAYERINFO_COLOR));
 			break;
-		case JnaFrontlib.NETCONN_MSG_TYPE_SERVERMESSAGE:
+		case Frontlib.NETCONN_MSG_TYPE_SERVERMESSAGE:
 			appendRaw(span(TextUtils.concat("\n", Html.fromHtml(msg), "\n"), new RelativeSizeSpan(1.5f)));
 			break;
 		default:
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Netplay.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Netplay.java	Mon Aug 06 22:39:36 2012 +0200
@@ -5,19 +5,29 @@
 
 import org.hedgewars.hedgeroid.R;
 import org.hedgewars.hedgeroid.Utils;
-import org.hedgewars.hedgeroid.netplay.JnaFrontlib.BoolCallback;
-import org.hedgewars.hedgeroid.netplay.JnaFrontlib.IntStrCallback;
-import org.hedgewars.hedgeroid.netplay.JnaFrontlib.MetaschemePtr;
-import org.hedgewars.hedgeroid.netplay.JnaFrontlib.NetconnPtr;
-import org.hedgewars.hedgeroid.netplay.JnaFrontlib.RoomArrayPtr;
-import org.hedgewars.hedgeroid.netplay.JnaFrontlib.RoomCallback;
-import org.hedgewars.hedgeroid.netplay.JnaFrontlib.RoomListCallback;
-import org.hedgewars.hedgeroid.netplay.JnaFrontlib.RoomPtr;
-import org.hedgewars.hedgeroid.netplay.JnaFrontlib.StrCallback;
-import org.hedgewars.hedgeroid.netplay.JnaFrontlib.StrRoomCallback;
-import org.hedgewars.hedgeroid.netplay.JnaFrontlib.StrStrCallback;
-import org.hedgewars.hedgeroid.netplay.JnaFrontlib.VoidCallback;
+import org.hedgewars.hedgeroid.Datastructures.RoomlistRoom;
+import org.hedgewars.hedgeroid.Datastructures.TeamInGame;
+import org.hedgewars.hedgeroid.Datastructures.TeamIngameAttributes;
+import org.hedgewars.hedgeroid.frontlib.Flib;
+import org.hedgewars.hedgeroid.frontlib.Frontlib;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.BoolCallback;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.IntStrCallback;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.MetaschemePtr;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.NetconnPtr;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.RoomArrayPtr;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.RoomCallback;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.RoomListCallback;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.RoomPtr;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.StrBoolCallback;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.StrCallback;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.StrIntCallback;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.StrRoomCallback;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.StrStrCallback;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.TeamCallback;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.TeamPtr;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.VoidCallback;
 
+import android.annotation.SuppressLint;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
@@ -58,31 +68,32 @@
 	private final LocalBroadcastManager broadcastManager;
 	private final FromNetHandler fromNetHandler = new FromNetHandler();
 	
-	private State state;
+	private State state = State.NOT_CONNECTED;
 	private int foregroundUsers = 0;	// Reference counter of clients requesting foreground tick speed (fast ticks)
 	private boolean chief;				// Do we control the current room?
+	private String playerName;
 	
 	// null if there is no running connection (==state is NOT_CONNECTED)
 	private ThreadedNetConnection connection;
 	
-	public final Playerlist playerList = new Playerlist();
+	public final LobbyPlayerlist lobbyPlayerlist = new LobbyPlayerlist();
+	public final RoomPlayerlist roomPlayerlist = new RoomPlayerlist();
 	public final Roomlist roomList = new Roomlist();
 	public final MessageLog lobbyChatlog;
 	public final MessageLog roomChatlog;
+	public final Teamlist roomTeamlist = new Teamlist();
 	
 	public Netplay(Context appContext) {
 		this.appContext = appContext;
 		broadcastManager = LocalBroadcastManager.getInstance(appContext);
 		lobbyChatlog = new MessageLog(appContext);
 		roomChatlog = new MessageLog(appContext);
-		state = State.NOT_CONNECTED;
 	}
 	
 	private void clearState() {
-		playerList.clear();
+		lobbyPlayerlist.clear();
 		roomList.clear();
 		lobbyChatlog.clear();
-		roomChatlog.clear();
 	}
 	
 	public void connectToDefaultServer(String playerName) {
@@ -97,6 +108,7 @@
 	 * will change back to NOT_CONNECTED and an ACTION_DISCONNECTED broadcast is sent.
 	 */
 	public void connect(String name, String host, int port) {
+		playerName = name;
 		if(state != State.NOT_CONNECTED) {
 			throw new IllegalStateException("Attempt to start a new connection while the old one was still running.");
 		}
@@ -107,7 +119,10 @@
 		connection.setFastTickRate(foregroundUsers > 0);
 	}
 	
-	public void sendNick(String nick) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_NICK, nick); }
+	public void sendNick(String nick) {
+		playerName = nick;
+		sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_NICK, nick);
+	}
 	public void sendPassword(String password) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_PASSWORD, password); }
 	public void sendQuit(String message) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_QUIT, message); }
 	public void sendRoomlistRequest() { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_ROOMLIST_REQUEST); }
@@ -117,6 +132,7 @@
 	public void sendJoinRoom(String name) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_JOIN_ROOM, name); }
 	public void sendCreateRoom(String name) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_CREATE_ROOM, name); }
 	public void sendLeaveRoom(String message) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_LEAVE_ROOM, message); }
+	public void sendKick(String player) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_KICK, player); }
 	
 	public void disconnect() { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_DISCONNECT, "User Quit"); }
 	
@@ -155,6 +171,10 @@
 		return chief;
 	}
 	
+	public String getPlayerName() {
+		return playerName;
+	}
+	
 	/**
 	 * Indicate that you want network messages to be checked regularly (several times per second).
 	 * As long as nobody requests fast ticks, the network is only checked once every few seconds
@@ -210,6 +230,7 @@
 	/**
 	 * Processes messages from the networking system. Always runs on the main thread.
 	 */
+	@SuppressLint("HandlerLeak")
 	final class FromNetHandler extends Handler {
 		public static final int MSG_LOBBY_JOIN = 0;
 		public static final int MSG_LOBBY_LEAVE = 1;
@@ -226,6 +247,12 @@
 		public static final int MSG_PASSWORD_REQUEST = 12;
 		public static final int MSG_ENTER_ROOM_FROM_LOBBY = 13;
 		public static final int MSG_LEAVE_ROOM = 14;
+		public static final int MSG_READYSTATE = 15;
+		public static final int MSG_TEAM_ADDED = 16;
+		public static final int MSG_TEAM_DELETED = 17;
+		public static final int MSG_TEAM_ACCEPTED = 18;
+		public static final int MSG_TEAM_COLOR_CHANGED = 19;
+		public static final int MSG_HOG_COUNT_CHANGED = 20;
 		
 		public FromNetHandler() {
 			super(Looper.getMainLooper());
@@ -237,25 +264,25 @@
 			switch(msg.what) {
 			case MSG_LOBBY_JOIN: {
 				String name = (String)msg.obj;
-				playerList.addPlayerWithNewId(name);
+				lobbyPlayerlist.addPlayerWithNewId(name);
 				lobbyChatlog.appendPlayerJoin(name);
 				break;
 			}
 			case MSG_LOBBY_LEAVE: {
 				Pair<String, String> args = (Pair<String, String>)msg.obj;
-				playerList.removePlayer(args.first);
+				lobbyPlayerlist.remove(args.first);
 				lobbyChatlog.appendPlayerLeave(args.first, args.second);
 				break;
 			}
 			case MSG_ROOM_JOIN: {
 				String name = (String)msg.obj;
-				// TODO roomPlayerList.addPlayerWithNewId(name);
+				roomPlayerlist.addPlayerWithNewId(name);
 				roomChatlog.appendPlayerJoin(name);
 				break;
 			}
 			case MSG_ROOM_LEAVE: {
 				Pair<String, String> args = (Pair<String, String>)msg.obj;
-				// TODO roomPlayerList.removePlayer(args.first);
+				roomPlayerlist.remove(args.first);
 				roomChatlog.appendPlayerLeave(args.first, args.second);
 				break;
 			}
@@ -269,23 +296,24 @@
 				break;
 			}
 			case MSG_ROOM_ADD: {
-				roomList.addRoomWithNewId((Room)msg.obj);
+				roomList.addRoomWithNewId((RoomlistRoom)msg.obj);
 				break;
 			}
 			case MSG_ROOM_UPDATE: {
-				Pair<String, Room> args = (Pair<String, Room>)msg.obj;
+				Pair<String, RoomlistRoom> args = (Pair<String, RoomlistRoom>)msg.obj;
 				roomList.updateRoom(args.first, args.second);
 				break;
 			}
 			case MSG_ROOM_DELETE: {
-				roomList.removeRoom((String)msg.obj);
+				roomList.remove((String)msg.obj);
 				break;
 			}
 			case MSG_ROOMLIST: {
-				roomList.updateList((Room[])msg.obj);
+				roomList.updateList((RoomlistRoom[])msg.obj);
 				break;
 			}
 			case MSG_CONNECTED: {
+				playerName = (String)msg.obj;
 				changeState(State.LOBBY);
 				broadcastManager.sendBroadcast(new Intent(ACTION_CONNECTED));
 				break;
@@ -308,6 +336,8 @@
 			}
 			case MSG_ENTER_ROOM_FROM_LOBBY: {
 				roomChatlog.clear();
+				roomPlayerlist.clear();
+				roomTeamlist.clear();
 				changeState(State.ROOM);
 				chief = (Boolean)msg.obj;
 				Intent intent = new Intent(ACTION_ENTERED_ROOM_FROM_LOBBY);
@@ -322,6 +352,45 @@
 				broadcastManager.sendBroadcastSync(intent);
 				break;
 			}
+			case MSG_READYSTATE: {
+				Pair<String, Boolean> args = (Pair<String, Boolean>)msg.obj;
+				roomPlayerlist.setReady(args.first, args.second);
+				break;
+			}
+			case MSG_TEAM_ADDED: {
+				roomTeamlist.addTeamWithNewId((TeamInGame)msg.obj);
+				break;
+			}
+			case MSG_TEAM_DELETED: {
+				roomTeamlist.remove((String)msg.obj);
+				break;
+			}
+			case MSG_TEAM_ACCEPTED: {
+				// TODO depends: adding teams
+				break;
+			}
+			case MSG_TEAM_COLOR_CHANGED: {
+				Pair<TeamInGame, Long> oldEntry = roomTeamlist.get((String)msg.obj);
+				if(oldEntry != null) {
+					TeamInGame tig = oldEntry.first;
+					TeamIngameAttributes tiga = tig.ingameAttribs.withColorIndex(msg.arg1);
+					roomTeamlist.put(tig.team.name, Pair.create(tig.withAttribs(tiga), oldEntry.second));
+				} else {
+					Log.e("Netplay", "Color update for unknown team "+msg.obj);
+				}
+				break;
+			}
+			case MSG_HOG_COUNT_CHANGED: {
+				Pair<TeamInGame, Long> oldEntry = roomTeamlist.get((String)msg.obj);
+				if(oldEntry != null) {
+					TeamInGame tig = oldEntry.first;
+					TeamIngameAttributes tiga = tig.ingameAttribs.withHogCount(msg.arg1);
+					roomTeamlist.put(tig.team.name, Pair.create(tig.withAttribs(tiga), oldEntry.second));
+				} else {
+					Log.e("Netplay", "Hog count update for unknown team "+msg.obj);
+				}
+				break;
+			}
 			default: {
 				Log.e("FromNetHandler", "Unknown message type: "+msg.what);
 				break;
@@ -336,7 +405,7 @@
 	private static class ThreadedNetConnection {
 		private static final long TICK_INTERVAL_FAST = 100;
 		private static final long TICK_INTERVAL_SLOW = 5000;
-		private static final JnaFrontlib FLIB = Flib.INSTANCE;
+		private static final Frontlib FLIB = Flib.INSTANCE;
 		
 		public final ToNetHandler toNetHandler;
 		
@@ -399,6 +468,12 @@
 					FLIB.flib_netconn_onPasswordRequest(conn, passwordRequestCb, null);
 					FLIB.flib_netconn_onEnterRoom(conn, enterRoomCb, null);
 					FLIB.flib_netconn_onLeaveRoom(conn, leaveRoomCb, null);
+					FLIB.flib_netconn_onReadyState(conn, readyStateCb, null);
+					FLIB.flib_netconn_onTeamAdd(conn, teamAddedCb, null);
+					FLIB.flib_netconn_onTeamDelete(conn, teamDeletedCb, null);
+					FLIB.flib_netconn_onTeamAccepted(conn, teamAcceptedCb, null);
+					FLIB.flib_netconn_onTeamColorChanged(conn, teamColorChangedCb, null);
+					FLIB.flib_netconn_onHogCountChanged(conn, hogCountChangedCb, null);
 					
 					FLIB.flib_metascheme_release(meta);
 					tickHandler.start();
@@ -496,7 +571,7 @@
 		
 		private final BoolCallback enterRoomCb = new BoolCallback() {
 			public void callback(Pointer context, boolean isChief) {
-				sendFromNet(FromNetHandler.MSG_ENTER_ROOM_FROM_LOBBY, Boolean.TRUE);
+				sendFromNet(FromNetHandler.MSG_ENTER_ROOM_FROM_LOBBY, isChief);
 			}
 		};
 		
@@ -506,6 +581,42 @@
 			}
 		};
 		
+		private final StrBoolCallback readyStateCb = new StrBoolCallback() {
+			public void callback(Pointer context, String player, boolean ready) {
+				sendFromNet(FromNetHandler.MSG_READYSTATE, Pair.create(player, ready));
+			}
+		};
+		
+		private final TeamCallback teamAddedCb = new TeamCallback() {
+			public void callback(Pointer context, TeamPtr team) {
+				sendFromNet(FromNetHandler.MSG_TEAM_ADDED, team.deref());
+			}
+		};
+		
+		private final StrCallback teamDeletedCb = new StrCallback() {
+			public void callback(Pointer context, String teamName) {
+				sendFromNet(FromNetHandler.MSG_TEAM_DELETED, teamName);
+			}
+		};
+		
+		private final StrCallback teamAcceptedCb = new StrCallback() {
+			public void callback(Pointer context, String teamName) {
+				sendFromNet(FromNetHandler.MSG_TEAM_ACCEPTED, teamName);
+			}
+		};
+		
+		private final StrIntCallback teamColorChangedCb = new StrIntCallback() {
+			public void callback(Pointer context, String teamName, int colorIndex) {
+				sendFromNet(FromNetHandler.MSG_TEAM_COLOR_CHANGED, colorIndex, teamName);
+			}
+		};
+		
+		private final StrIntCallback hogCountChangedCb = new StrIntCallback() {
+			public void callback(Pointer context, String teamName, int hogCount) {
+				sendFromNet(FromNetHandler.MSG_HOG_COUNT_CHANGED, hogCount, teamName);
+			}
+		};
+		
 		private void shutdown(boolean error, String message) {
 			if(conn != null) {
 				FLIB.flib_netconn_destroy(conn);
@@ -518,7 +629,7 @@
 		
 		private final IntStrCallback disconnectCb = new IntStrCallback() {
 			public void callback(Pointer context, int reason, String message) {
-				Boolean error = reason != JnaFrontlib.NETCONN_DISCONNECT_NORMAL;
+				Boolean error = reason != Frontlib.NETCONN_DISCONNECT_NORMAL;
 				String messageForUser = createDisconnectUserMessage(appContext.getResources(), reason, message);
 				shutdown(error, messageForUser);
 			}
@@ -526,13 +637,13 @@
 		
 		private static String createDisconnectUserMessage(Resources res, int reason, String message) {
 			switch(reason) {
-			case JnaFrontlib.NETCONN_DISCONNECT_AUTH_FAILED:
+			case Frontlib.NETCONN_DISCONNECT_AUTH_FAILED:
 				return res.getString(R.string.error_auth_failed);
-			case JnaFrontlib.NETCONN_DISCONNECT_CONNLOST:
+			case Frontlib.NETCONN_DISCONNECT_CONNLOST:
 				return res.getString(R.string.error_connection_lost);
-			case JnaFrontlib.NETCONN_DISCONNECT_INTERNAL_ERROR:
+			case Frontlib.NETCONN_DISCONNECT_INTERNAL_ERROR:
 				return res.getString(R.string.error_unexpected, message);
-			case JnaFrontlib.NETCONN_DISCONNECT_SERVER_TOO_OLD:
+			case Frontlib.NETCONN_DISCONNECT_SERVER_TOO_OLD:
 				return res.getString(R.string.error_server_too_old);
 			default:
 				return message;
@@ -550,6 +661,7 @@
 		/**
 		 * Processes messages to the networking system. Runs on a non-main thread.
 		 */
+		@SuppressLint("HandlerLeak")
 		public final class ToNetHandler extends Handler {
 			public static final int MSG_SEND_NICK = 0;
 			public static final int MSG_SEND_PASSWORD = 1;
@@ -561,8 +673,9 @@
 			public static final int MSG_SEND_JOIN_ROOM = 7;
 			public static final int MSG_SEND_CREATE_ROOM = 8;
 			public static final int MSG_SEND_LEAVE_ROOM = 9;
+			public static final int MSG_SEND_KICK = 10;
 			
-			public static final int MSG_DISCONNECT = 10;
+			public static final int MSG_DISCONNECT = 11;
 			
 			public ToNetHandler(Looper looper) {
 				super(looper);
@@ -615,6 +728,10 @@
 					}
 					break;
 				}
+				case MSG_SEND_KICK: {
+					FLIB.flib_netconn_send_kick(conn, (String)msg.obj);
+					break;
+				}
 				case MSG_DISCONNECT: {
 					FLIB.flib_netconn_send_quit(conn, (String)msg.obj);
 					shutdown(false, "User quit");
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/NetplayStateFragment.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/NetplayStateFragment.java	Mon Aug 06 22:39:36 2012 +0200
@@ -1,6 +1,7 @@
 package org.hedgewars.hedgeroid.netplay;
 
 import org.hedgewars.hedgeroid.R;
+import org.hedgewars.hedgeroid.frontlib.Frontlib;
 import org.hedgewars.hedgeroid.netplay.Netplay.State;
 
 import android.app.Activity;
@@ -101,9 +102,9 @@
 		@Override
 		public void onReceive(Context context, Intent intent) {
 			int reason = intent.getIntExtra(Netplay.EXTRA_REASON, -1);
-			if(reason == JnaFrontlib.NETCONN_ROOMLEAVE_ABANDONED) {
+			if(reason == Frontlib.NETCONN_ROOMLEAVE_ABANDONED) {
 				Toast.makeText(appContext, R.string.toast_room_abandoned, Toast.LENGTH_LONG).show();
-			} else if(reason == JnaFrontlib.NETCONN_ROOMLEAVE_KICKED) {
+			} else if(reason == Frontlib.NETCONN_ROOMLEAVE_KICKED) {
 				Toast.makeText(appContext, R.string.toast_kicked, Toast.LENGTH_LONG).show();
 			}
 		}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/ObservableTreeMap.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,43 @@
+package org.hedgewars.hedgeroid.netplay;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.TreeMap;
+
+import android.database.DataSetObservable;
+
+public class ObservableTreeMap<K,V> extends DataSetObservable {
+	private final Map<K, V> map = new TreeMap<K, V>();
+	
+	public void replaceContent(Map<? extends K, ? extends V> newMap) {
+		map.clear();
+		map.putAll(newMap);
+		notifyChanged();
+	}
+	
+	public void put(K key, V value) {
+		map.put(key, value);
+		notifyChanged();
+	}
+	
+	public V get(K key) {
+		return map.get(key);
+	}
+	
+	public void remove(K key) {
+		if(map.remove(key) != null) {
+			notifyChanged();
+		}
+	}
+	
+	public void clear() {
+		if(!map.isEmpty()) {
+			map.clear();
+			notifyChanged();
+		}
+	}
+	
+	public Map<K, V> getMap() {
+		return Collections.unmodifiableMap(map);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/ObservableTreeMapAdapter.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,62 @@
+package org.hedgewars.hedgeroid.netplay;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import android.database.DataSetObserver;
+import android.widget.BaseAdapter;
+
+public abstract class ObservableTreeMapAdapter<K,V> extends BaseAdapter {
+	private boolean sourceChanged = true;
+	private List<V> entries = new ArrayList<V>();
+	private ObservableTreeMap<K, V> source;
+	
+	private DataSetObserver observer = new DataSetObserver() {
+		@Override
+		public void onChanged() {
+			sourceChanged = true;
+			notifyDataSetChanged();
+		}
+		
+		@Override
+		public void onInvalidated() {
+			invalidate();
+		}
+	};
+	
+	abstract protected Comparator<V> getEntryOrder();
+	
+	protected List<V> getEntries() {
+		if(sourceChanged) {
+			entries.clear();
+			entries.addAll(source.getMap().values());
+			Collections.sort(entries, getEntryOrder());
+			sourceChanged = false;
+		}
+		return entries;
+	}
+	
+	public int getCount() {
+		return getEntries().size();
+	}
+
+	public void setSource(ObservableTreeMap<K,V> source) {
+		if(this.source != null) {
+			this.source.unregisterObserver(observer);
+		}
+		this.source = source;
+		this.source.registerObserver(observer);
+		sourceChanged = true;
+		notifyDataSetChanged();
+	}
+	
+	public void invalidate() {
+		if(source != null) {
+			source.unregisterObserver(observer);
+		}
+		source = null;
+		notifyDataSetInvalidated();
+	}
+}
\ No newline at end of file
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Player.java	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-package org.hedgewars.hedgeroid.netplay;
-
-public class Player {
-	public final String name;
-	
-	public Player(String name) {
-		this.name = name;
-	}
-}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerList.java	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-package org.hedgewars.hedgeroid.netplay;
-
-import java.util.Collections;
-import java.util.Map;
-import java.util.TreeMap;
-
-import android.database.DataSetObservable;
-import android.util.Pair;
-
-public class Playerlist extends DataSetObservable {
-	private long nextId = 1;
-	private Map<String, Pair<Player, Long>> players = new TreeMap<String, Pair<Player, Long>>();
-	
-	public void addPlayerWithNewId(String name) {
-		players.put(name, Pair.create(new Player(name), nextId++));
-		notifyChanged();
-	}
-	
-	public void removePlayer(String name) {
-		if(players.remove(name) != null) {
-			notifyChanged();
-		}
-	}
-
-	public void clear() {
-		if(!players.isEmpty()) {
-			players.clear();
-			notifyChanged();
-		}
-	}
-
-	public Map<String, Pair<Player, Long>> getMap() {
-		return Collections.unmodifiableMap(players);
-	}
-}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerListAdapter.java	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-package org.hedgewars.hedgeroid.netplay;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-import org.hedgewars.hedgeroid.R;
-
-import android.content.Context;
-import android.database.DataSetObserver;
-import android.util.Pair;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.TextView;
-
-public class PlayerlistAdapter extends BaseAdapter {
-	private List<Pair<Player, Long>> players = new ArrayList<Pair<Player, Long>>();
-	private Context context;
-	private Playerlist playerlist;
-	
-	private DataSetObserver observer = new DataSetObserver() {
-		@Override
-		public void onChanged() {
-			reloadFromList(playerlist);
-		}
-		
-		@Override
-		public void onInvalidated() {
-			invalidate();
-		}
-	};
-	
-	public PlayerlistAdapter(Context context) {
-		this.context = context;
-	}
-	
-	public int getCount() {
-		return players.size();
-	}
-
-	public Player getItem(int position) {
-		return players.get(position).first;
-	}
-
-	public long getItemId(int position) {
-		return players.get(position).second;
-	}
-
-	public boolean hasStableIds() {
-		return true;
-	}
-	
-	public void setList(Playerlist playerlist) {
-		if(this.playerlist != null) {
-			this.playerlist.unregisterObserver(observer);
-		}
-		this.playerlist = playerlist;
-		this.playerlist.registerObserver(observer);
-		reloadFromList(playerlist);
-	}
-	
-	public void invalidate() {
-		if(playerlist != null) {
-			playerlist.unregisterObserver(observer);
-		}
-		playerlist = null;
-		notifyDataSetInvalidated();
-	}
-	
-	private void reloadFromList(Playerlist list) {
-		players = new ArrayList<Pair<Player, Long>>(list.getMap().values());
-		Collections.sort(players, AlphabeticalOrderComparator.INSTANCE);
-		notifyDataSetChanged();
-	}
-	
-	public View getView(int position, View convertView, ViewGroup parent) {
-		View v = convertView;
-		if (v == null) {
-			LayoutInflater vi = LayoutInflater.from(context);
-			v = vi.inflate(R.layout.listview_player, null);
-		}
-
-		String player = players.get(position).first.name;
-		TextView username = (TextView) v.findViewById(android.R.id.text1);
-		username.setText(player);
-		return v;
-	}
-	
-	private static final class AlphabeticalOrderComparator implements Comparator<Pair<Player, Long>> {
-		public static final AlphabeticalOrderComparator INSTANCE = new AlphabeticalOrderComparator();
-		public int compare(Pair<Player, Long> lhs, Pair<Player, Long> rhs) {
-			return lhs.first.name.compareToIgnoreCase(rhs.first.name);
-		};
-	}
-}
\ No newline at end of file
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerlistFragment.java	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-package org.hedgewars.hedgeroid.netplay;
-
-import org.hedgewars.hedgeroid.R;
-
-import android.os.Bundle;
-import android.support.v4.app.ListFragment;
-import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.LayoutInflater;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView.AdapterContextMenuInfo;
-
-public class PlayerlistFragment extends ListFragment {
-	private Netplay netconn;
-	private PlayerlistAdapter playerListAdapter;
-	
-	@Override
-	public void onCreate(Bundle savedInstanceState) {
-		super.onCreate(savedInstanceState);
-		netconn = Netplay.getAppInstance(getActivity().getApplicationContext());
-		playerListAdapter = new PlayerlistAdapter(getActivity());
-		playerListAdapter.setList(Netplay.getAppInstance(getActivity().getApplicationContext()).playerList);
-		setListAdapter(playerListAdapter);
-	}
-
-	@Override
-	public void onDestroy() {
-		super.onDestroy();
-		playerListAdapter.invalidate();
-	}
-	
-	@Override
-	public void onActivityCreated(Bundle savedInstanceState) {
-		super.onActivityCreated(savedInstanceState);
-		registerForContextMenu(getListView());
-	}
-
-	@Override
-	public void onCreateContextMenu(ContextMenu menu, View v,
-			ContextMenuInfo menuInfo) {
-		super.onCreateContextMenu(menu, v, menuInfo);
-		AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo;
-		MenuInflater inflater = getActivity().getMenuInflater();
-		inflater.inflate(R.menu.lobby_playerlist_context, menu);
-		menu.setHeaderIcon(R.drawable.human);
-		menu.setHeaderTitle(playerListAdapter.getItem(info.position).name);
-	}
-	
-	@Override
-	public boolean onContextItemSelected(MenuItem item) {
-		AdapterContextMenuInfo info = (AdapterContextMenuInfo)item.getMenuInfo();
-		Player player = playerListAdapter.getItem(info.position);
-		switch(item.getItemId()) {
-		case R.id.player_info:
-			netconn.sendPlayerInfoQuery(player.name);
-			return true;
-		case R.id.player_follow:
-			netconn.sendFollowPlayer(player.name);
-			return true;
-		default:
-			return super.onContextItemSelected(item);
-		}
-	}
-	
-	@Override
-	public View onCreateView(LayoutInflater inflater, ViewGroup container,
-			Bundle savedInstanceState) {
-		return inflater.inflate(R.layout.lobby_players_fragment, container, false);
-	}
-}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Room.java	Mon Aug 06 22:33:07 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-package org.hedgewars.hedgeroid.netplay;
-
-import org.hedgewars.hedgeroid.R;
-
-import android.content.res.Resources;
-
-public class Room {
-	public static final String MAP_REGULAR = "+rnd+";
-	public static final String MAP_MAZE = "+maze+";
-	public static final String MAP_DRAWN = "+drawn+";
-	
-	public final String name, map, scheme, weapons, owner;
-	public final int playerCount, teamCount;
-	public final boolean inProgress;
-	
-	public Room(String name, String map, String scheme, String weapons,
-			String owner, int playerCount, int teamCount, boolean inProgress) {
-		this.name = name;
-		this.map = map;
-		this.scheme = scheme;
-		this.weapons = weapons;
-		this.owner = owner;
-		this.playerCount = playerCount;
-		this.teamCount = teamCount;
-		this.inProgress = inProgress;
-	}
-
-	public static String formatMapName(Resources res, String map) {
-		if(map.charAt(0)=='+') {
-			if(map.equals(MAP_REGULAR)) {
-				return res.getString(R.string.map_regular);
-			} else if(map.equals(MAP_MAZE)) {
-				return res.getString(R.string.map_maze);
-			} else if(map.equals(MAP_DRAWN)) {
-				return res.getString(R.string.map_drawn);
-			}
-		}
-		return map;
-	}
-}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomActivity.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomActivity.java	Mon Aug 06 22:39:36 2012 +0200
@@ -1,18 +1,12 @@
 package org.hedgewars.hedgeroid.netplay;
 
 import org.hedgewars.hedgeroid.R;
-import org.hedgewars.hedgeroid.netplay.JnaFrontlib.NetconnPtr;
 import org.hedgewars.hedgeroid.netplay.Netplay.State;
 import org.hedgewars.hedgeroid.netplay.NetplayStateFragment.NetplayStateListener;
 
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.os.Bundle;
-import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentActivity;
 import android.support.v4.app.FragmentTransaction;
-import android.support.v4.content.LocalBroadcastManager;
-import android.widget.LinearLayout;
 import android.widget.TabHost;
 import android.widget.Toast;
 
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomList.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomList.java	Mon Aug 06 22:39:36 2012 +0200
@@ -1,64 +1,39 @@
 package org.hedgewars.hedgeroid.netplay;
 
-import java.util.Collections;
 import java.util.Map;
 import java.util.TreeMap;
 
-import android.database.DataSetObservable;
-import android.util.Log;
+import org.hedgewars.hedgeroid.Datastructures.RoomlistRoom;
+
 import android.util.Pair;
 
-public class Roomlist extends DataSetObservable {
+public class Roomlist extends ObservableTreeMap<String, Pair<RoomlistRoom, Long>> {
 	private long nextId = 1;
-	private Map<String, Pair<Room, Long>> rooms = new TreeMap<String, Pair<Room, Long>>();
 	
-	public void updateList(Room[] newRooms) {
-		Map<String, Pair<Room, Long>> newMap = new TreeMap<String, Pair<Room, Long>>();
-		for(Room room : newRooms) {
-			Pair<Room, Long> oldEntry = rooms.get(room.name);
+	public void updateList(RoomlistRoom[] newRooms) {
+		Map<String, Pair<RoomlistRoom, Long>> newMap = new TreeMap<String, Pair<RoomlistRoom, Long>>();
+		for(RoomlistRoom room : newRooms) {
+			Pair<RoomlistRoom, Long> oldEntry = get(room.name);
 			if(oldEntry == null) {
 				newMap.put(room.name, Pair.create(room, nextId++));
 			} else {
 				newMap.put(room.name, Pair.create(room, oldEntry.second));
 			}
 		}
-		rooms = newMap;
-		notifyChanged();
+		replaceContent(newMap);
 	}
 	
-	public void addRoomWithNewId(Room room) {
-		rooms.put(room.name, Pair.create(room, nextId++));
-		notifyChanged();
+	public void addRoomWithNewId(RoomlistRoom room) {
+		put(room.name, Pair.create(room, nextId++));
 	}
 	
-	public void updateRoom(String name, Room room) {
-		Pair<Room, Long> oldEntry = rooms.get(name);
+	public void updateRoom(String name, RoomlistRoom room) {
+		Pair<RoomlistRoom, Long> oldEntry = get(name);
 		if(oldEntry == null) {
-			Log.e("RoomList", "Received update for unknown room: "+name);
-			rooms.put(room.name, Pair.create(room, nextId++));
+			addRoomWithNewId(room);
 		} else {
-			if(!name.equals(room.name)) {
-				rooms.remove(name);
-			}
-			rooms.put(room.name, Pair.create(room, oldEntry.second));
-		}
-		notifyChanged();
-	}
-	
-	public void removeRoom(String name) {
-		if(rooms.remove(name) != null) {
-			notifyChanged();
+			remove(name);
+			put(room.name, Pair.create(room, oldEntry.second));
 		}
 	}
-	
-	public void clear() {
-		if(!rooms.isEmpty()) {
-			rooms.clear();
-			notifyChanged();
-		}
-	}
-	
-	public Map<String, Pair<Room, Long>> getMap() {
-		return Collections.unmodifiableMap(rooms);
-	}
 }
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomListAdapter.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomListAdapter.java	Mon Aug 06 22:39:36 2012 +0200
@@ -1,85 +1,45 @@
 package org.hedgewars.hedgeroid.netplay;
 
-import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Comparator;
-import java.util.List;
 
 import org.hedgewars.hedgeroid.R;
+import org.hedgewars.hedgeroid.Datastructures.RoomlistRoom;
 
 import android.content.Context;
 import android.content.res.Resources;
-import android.database.DataSetObserver;
 import android.util.Pair;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.BaseAdapter;
 import android.widget.TextView;
 
-public class RoomlistAdapter extends BaseAdapter {
-	private List<Pair<Room, Long>> rooms = new ArrayList<Pair<Room, Long>>();
+public class RoomlistAdapter extends ObservableTreeMapAdapter<String, Pair<RoomlistRoom, Long>> {
 	private Context context;
-	private Roomlist roomlist;
-	
-	private DataSetObserver observer = new DataSetObserver() {
-		@Override
-		public void onChanged() {
-			reloadFromList(roomlist);
-		}
-		
-		@Override
-		public void onInvalidated() {
-			invalidate();
-		}
-	};
 	
 	public RoomlistAdapter(Context context) {
 		this.context = context;
 	}
 	
-	public int getCount() {
-		return rooms.size();
+	@Override
+	protected Comparator<Pair<RoomlistRoom, Long>> getEntryOrder() {
+		return RoomAgeComparator.INSTANCE;
 	}
-
-	public Room getItem(int position) {
-		return rooms.get(position).first;
+	
+	public RoomlistRoom getItem(int position) {
+		return getEntries().get(position).first;
 	}
 
 	public long getItemId(int position) {
-		return rooms.get(position).second;
+		return getEntries().get(position).second;
 	}
 
 	public boolean hasStableIds() {
 		return true;
 	}
-
-	public void setList(Roomlist roomlist) {
-		if(this.roomlist != null) {
-			this.roomlist.unregisterObserver(observer);
-		}
-		this.roomlist = roomlist;
-		this.roomlist.registerObserver(observer);
-		reloadFromList(roomlist);
-	}
 	
-	public void invalidate() {
-		if(roomlist != null) {
-			roomlist.unregisterObserver(observer);
-		}
-		roomlist = null;
-		notifyDataSetInvalidated();
-	}
-	
-	private void reloadFromList(Roomlist list) {
-		rooms = new ArrayList<Pair<Room, Long>>(roomlist.getMap().values());
-		Collections.sort(rooms, RoomAgeComparator.INSTANCE);
-		notifyDataSetChanged();
-	}
-	
-	private static CharSequence formatExtra(Resources res, Room room) {
+	private static CharSequence formatExtra(Resources res, RoomlistRoom room) {
 		String ownermsg = res.getString(R.string.roomlist_owner, room.owner);
-		String mapmsg = res.getString(R.string.roomlist_map, Room.formatMapName(res, room.map));
+		String mapmsg = res.getString(R.string.roomlist_map, RoomlistRoom.formatMapName(res, room.map));
 		String scheme = room.scheme.equals(room.weapons) ? room.scheme : room.scheme + " / " + room.weapons;
 		String schememsg = res.getString(R.string.roomlist_scheme, scheme);
 		return ownermsg + ". " + mapmsg + ", " + schememsg;
@@ -92,7 +52,7 @@
 			v = vi.inflate(R.layout.listview_room, null);
 		}
 		
-		Room room = rooms.get(position).first;
+		RoomlistRoom room = getItem(position);
 		int iconRes = room.inProgress ? R.drawable.roomlist_ingame : R.drawable.roomlist_preparing;
 		
 		if(v.findViewById(android.R.id.text1) == null) {
@@ -114,7 +74,7 @@
 				teamCountView.setText(String.valueOf(room.teamCount));
 			}
 			ownerView.setText(room.owner);
-			mapView.setText(Room.formatMapName(context.getResources(), room.map));
+			mapView.setText(RoomlistRoom.formatMapName(context.getResources(), room.map));
 			schemeView.setText(room.scheme);
 			weaponView.setText(room.weapons);
 		} else {
@@ -130,9 +90,9 @@
 		return v;
 	}
 	
-	private static final class RoomAgeComparator implements Comparator<Pair<Room, Long>> {
+	private static final class RoomAgeComparator implements Comparator<Pair<RoomlistRoom, Long>> {
 		public static final RoomAgeComparator INSTANCE = new RoomAgeComparator();
-		public int compare(Pair<Room, Long> lhs, Pair<Room, Long> rhs) {
+		public int compare(Pair<RoomlistRoom, Long> lhs, Pair<RoomlistRoom, Long> rhs) {
 			return rhs.second.compareTo(lhs.second);
 		}
 	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomPlayerlist.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,36 @@
+package org.hedgewars.hedgeroid.netplay;
+
+import org.hedgewars.hedgeroid.Datastructures.Player;
+import org.hedgewars.hedgeroid.netplay.RoomPlayerlist.PlayerInRoom;
+
+import android.util.Log;
+
+public class RoomPlayerlist extends ObservableTreeMap<String, PlayerInRoom> {
+	private long nextId = 1;
+	
+	public void addPlayerWithNewId(String name) {
+		put(name, new PlayerInRoom(new Player(name), nextId++, false));
+	}
+	
+	public void setReady(String name, boolean ready) {
+		PlayerInRoom oldEntry = get(name);
+		if(oldEntry==null) {
+			Log.e("RoomPlayerlist", "Setting readystate for unknown player "+name);
+		} else {
+			put(name, new PlayerInRoom(oldEntry.player, oldEntry.id, ready));
+		}
+	}
+	
+	// Immutable
+	public static class PlayerInRoom {
+		public final Player player;
+		public final long id;
+		public final boolean ready;
+		
+		public PlayerInRoom(Player player, long id, boolean ready) {
+			this.player = player;
+			this.id = id;
+			this.ready = ready;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomPlayerlistAdapter.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,59 @@
+package org.hedgewars.hedgeroid.netplay;
+
+import java.util.Comparator;
+
+import org.hedgewars.hedgeroid.R;
+import org.hedgewars.hedgeroid.netplay.RoomPlayerlist.PlayerInRoom;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class RoomPlayerlistAdapter extends ObservableTreeMapAdapter<String, PlayerInRoom> {
+	private Context context;
+	
+	public RoomPlayerlistAdapter(Context context) {
+		this.context = context;
+	}
+	
+	@Override
+	protected Comparator<PlayerInRoom> getEntryOrder() {
+		return AlphabeticalOrderComparator.INSTANCE;
+	}
+
+	public PlayerInRoom getItem(int position) {
+		return getEntries().get(position);
+	}
+
+	public long getItemId(int position) {
+		return getEntries().get(position).id;
+	}
+
+	public boolean hasStableIds() {
+		return true;
+	}
+	
+	public View getView(int position, View convertView, ViewGroup parent) {
+		View v = convertView;
+		if (v == null) {
+			LayoutInflater vi = LayoutInflater.from(context);
+			v = vi.inflate(R.layout.listview_player, null);
+		}
+
+		PlayerInRoom player = getItem(position);
+		TextView username = (TextView) v.findViewById(android.R.id.text1);
+		username.setText(player.player.name);
+		int readyDrawable = player.ready ? R.drawable.lightbulb_on : R.drawable.lightbulb_off;
+		username.setCompoundDrawablesWithIntrinsicBounds(readyDrawable, 0, 0, 0);
+		return v;
+	}
+	
+	private static final class AlphabeticalOrderComparator implements Comparator<PlayerInRoom> {
+		public static final AlphabeticalOrderComparator INSTANCE = new AlphabeticalOrderComparator();
+		public int compare(PlayerInRoom lhs, PlayerInRoom rhs) {
+			return lhs.player.name.compareToIgnoreCase(rhs.player.name);
+		};
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomPlayerlistFragment.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,79 @@
+package org.hedgewars.hedgeroid.netplay;
+
+import org.hedgewars.hedgeroid.R;
+import org.hedgewars.hedgeroid.netplay.RoomPlayerlist.PlayerInRoom;
+
+import android.os.Bundle;
+import android.support.v4.app.ListFragment;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.LayoutInflater;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView.AdapterContextMenuInfo;
+
+public class RoomPlayerlistFragment extends ListFragment {
+	private Netplay netplay;
+	private RoomPlayerlistAdapter adapter;
+	
+	@Override
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		netplay = Netplay.getAppInstance(getActivity().getApplicationContext());
+		adapter = new RoomPlayerlistAdapter(getActivity());
+		adapter.setSource(netplay.roomPlayerlist);
+		setListAdapter(adapter);
+	}
+
+	@Override
+	public void onDestroy() {
+		super.onDestroy();
+		adapter.invalidate();
+	}
+	
+	@Override
+	public void onActivityCreated(Bundle savedInstanceState) {
+		super.onActivityCreated(savedInstanceState);
+		registerForContextMenu(getListView());
+	}
+
+	@Override
+	public void onCreateContextMenu(ContextMenu menu, View v,
+			ContextMenuInfo menuInfo) {
+		super.onCreateContextMenu(menu, v, menuInfo);
+		AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo;
+		String playerName = adapter.getItem(info.position).player.name;
+		
+		MenuInflater inflater = getActivity().getMenuInflater();
+		inflater.inflate(R.menu.room_playerlist_context, menu);
+		if(netplay.isChief() && !playerName.equals(netplay.getPlayerName())) {
+			inflater.inflate(R.menu.room_playerlist_chief_context, menu);
+		}
+		menu.setHeaderIcon(R.drawable.human);
+		menu.setHeaderTitle(playerName);
+	}
+	
+	@Override
+	public boolean onContextItemSelected(MenuItem item) {
+		AdapterContextMenuInfo info = (AdapterContextMenuInfo)item.getMenuInfo();
+		PlayerInRoom player = adapter.getItem(info.position);
+		switch(item.getItemId()) {
+		case R.id.player_info:
+			netplay.sendPlayerInfoQuery(player.player.name);
+			return true;
+		case R.id.player_kick:
+			netplay.sendKick(player.player.name);
+			return true;
+		default:
+			return super.onContextItemSelected(item);
+		}
+	}
+	
+	@Override
+	public View onCreateView(LayoutInflater inflater, ViewGroup container,
+			Bundle savedInstanceState) {
+		return inflater.inflate(R.layout.fragment_playerlist, container, false);
+	}
+}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomlistFragment.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomlistFragment.java	Mon Aug 06 22:39:36 2012 +0200
@@ -31,7 +31,7 @@
 		super.onCreate(savedInstanceState);
 		netplay = Netplay.getAppInstance(getActivity().getApplicationContext());
 		adapter = new RoomlistAdapter(getActivity());
-		adapter.setList(netplay.roomList);
+		adapter.setSource(netplay.roomList);
 		setListAdapter(adapter);
 	}
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Teamlist.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,13 @@
+package org.hedgewars.hedgeroid.netplay;
+
+import org.hedgewars.hedgeroid.Datastructures.TeamInGame;
+
+import android.util.Pair;
+
+public class Teamlist extends ObservableTreeMap<String, Pair<TeamInGame, Long>> {
+	private long nextId = 1;
+	
+	public void addTeamWithNewId(TeamInGame team) {
+		put(team.team.name, Pair.create(team, nextId++));
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/TeamlistAdapter.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,60 @@
+package org.hedgewars.hedgeroid.netplay;
+
+import java.util.Comparator;
+
+import org.hedgewars.hedgeroid.Datastructures.TeamInGame;
+
+import android.content.Context;
+import android.util.Pair;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class TeamlistAdapter extends ObservableTreeMapAdapter<String, Pair<TeamInGame, Long>> {
+	private Context context;
+	
+	public TeamlistAdapter(Context context) {
+		this.context = context;
+	}
+	
+	@Override
+	protected Comparator<Pair<TeamInGame, Long>> getEntryOrder() {
+		return AlphabeticalOrderComparator.INSTANCE;
+	}
+
+	public TeamInGame getItem(int position) {
+		return getEntries().get(position).first;
+	}
+
+	public long getItemId(int position) {
+		return getEntries().get(position).second;
+	}
+
+	public boolean hasStableIds() {
+		return true;
+	}
+	
+	public View getView(int position, View convertView, ViewGroup parent) {
+		View v = convertView;
+		if (v == null) {
+			LayoutInflater vi = LayoutInflater.from(context);
+			v = vi.inflate(android.R.layout.simple_list_item_2, null);
+		}
+
+		TeamInGame team = getItem(position);
+		TextView tv1 = (TextView) v.findViewById(android.R.id.text1);
+		TextView tv2 = (TextView) v.findViewById(android.R.id.text2);
+		
+		tv1.setText(team.team.name);
+		tv2.setText("Hogs: "+team.ingameAttribs.hogCount);
+		return v;
+	}
+	
+	private static final class AlphabeticalOrderComparator implements Comparator<Pair<TeamInGame, Long>> {
+		public static final AlphabeticalOrderComparator INSTANCE = new AlphabeticalOrderComparator();
+		public int compare(Pair<TeamInGame, Long> lhs, Pair<TeamInGame, Long> rhs) {
+			return lhs.first.team.name.compareToIgnoreCase(rhs.first.team.name);
+		};
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/TeamlistFragment.java	Mon Aug 06 22:39:36 2012 +0200
@@ -0,0 +1,35 @@
+package org.hedgewars.hedgeroid.netplay;
+
+import org.hedgewars.hedgeroid.R;
+
+import android.os.Bundle;
+import android.support.v4.app.ListFragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class TeamlistFragment extends ListFragment {
+	private Netplay netplay;
+	private TeamlistAdapter adapter;
+
+	@Override
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		netplay = Netplay.getAppInstance(getActivity().getApplicationContext());
+		adapter = new TeamlistAdapter(getActivity());
+		adapter.setSource(netplay.roomTeamlist);
+		setListAdapter(adapter);
+	}
+
+	@Override
+	public View onCreateView(LayoutInflater inflater, ViewGroup container,
+			Bundle savedInstanceState) {
+		return inflater.inflate(R.layout.fragment_teamlist, container, false);
+	}
+	
+	@Override
+	public void onDestroy() {
+		super.onDestroy();
+		adapter.invalidate();
+	}
+}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/TickHandler.java	Mon Aug 06 22:33:07 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/TickHandler.java	Mon Aug 06 22:39:36 2012 +0200
@@ -12,7 +12,7 @@
  * The interval can be changed at any time, which will cause
  * an immediate execution of the runnable again.
  */
-class TickHandler extends Handler {
+public class TickHandler extends Handler {
 	private final Runnable callback;
 	private int messageId;
 	private long interval;