# HG changeset patch # User Medo <smaxein@googlemail.com> # Date 1345486775 -7200 # Node ID 714310efad8f2f94738138579228cb2a0a796fd8 # Parent c92596feac0d5a5286df052c15ea8baad09a6467 Hedgeroid: Final sprint to the deadline - Changed local game setup to use the new fragments from the netroom - Pulled team editing into the main activity menu / action bar - Cleanups, renames, anything to make the code look better ;) diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/AndroidManifest.xml --- a/project_files/Android-build/SDL-android-project/AndroidManifest.xml Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/AndroidManifest.xml Mon Aug 20 20:19:35 2012 +0200 @@ -48,13 +48,12 @@ <service android:name=".Downloader.DownloadService" /> <activity - android:name="StartGameActivity" + android:name=".LocalRoomActivity" android:label="@string/app_name" - android:screenOrientation="landscape" - android:theme="@android:style/Theme.NoTitleBar.Fullscreen" > + android:screenOrientation="landscape" > </activity> <activity - android:name="TeamSelectionActivity" + android:name=".TeamListActivity" android:label="@string/app_name" android:screenOrientation="landscape" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" > @@ -73,7 +72,7 @@ android:windowSoftInputMode="adjustPan" > </activity> <activity - android:name=".RoomActivity" + android:name=".NetRoomActivity" android:label="@string/title_activity_room" android:screenOrientation="landscape" android:windowSoftInputMode="adjustPan" > diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/drawable-mdpi/backbutton.png Binary file project_files/Android-build/SDL-android-project/res/drawable-mdpi/backbutton.png has changed diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/drawable-mdpi/button_disabled.9.png Binary file project_files/Android-build/SDL-android-project/res/drawable-mdpi/button_disabled.9.png has changed diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/drawable-mdpi/button_focused.9.png Binary file project_files/Android-build/SDL-android-project/res/drawable-mdpi/button_focused.9.png has changed diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/drawable-mdpi/button_focused_disabled.9.png Binary file project_files/Android-build/SDL-android-project/res/drawable-mdpi/button_focused_disabled.9.png has changed diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/drawable-mdpi/button_normal.9.png Binary file project_files/Android-build/SDL-android-project/res/drawable-mdpi/button_normal.9.png has changed diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/drawable-mdpi/dropdown_disabled.9.png Binary file project_files/Android-build/SDL-android-project/res/drawable-mdpi/dropdown_disabled.9.png has changed diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/drawable-mdpi/dropdown_focused.9.png Binary file project_files/Android-build/SDL-android-project/res/drawable-mdpi/dropdown_focused.9.png has changed diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/drawable-mdpi/dropdown_focused_disabled.9.png Binary file project_files/Android-build/SDL-android-project/res/drawable-mdpi/dropdown_focused_disabled.9.png has changed diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/drawable-mdpi/dropdown_normal.9.png Binary file project_files/Android-build/SDL-android-project/res/drawable-mdpi/dropdown_normal.9.png has changed diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/drawable-mdpi/savebutton.png Binary file project_files/Android-build/SDL-android-project/res/drawable-mdpi/savebutton.png has changed diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout-large/activity_lobby.xml --- a/project_files/Android-build/SDL-android-project/res/layout-large/activity_lobby.xml Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/res/layout-large/activity_lobby.xml Mon Aug 20 20:19:35 2012 +0200 @@ -24,7 +24,7 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" class="org.hedgewars.hedgeroid.RoomlistFragment" - tools:layout="@layout/lobby_rooms_fragment" /> + tools:layout="@layout/fragment_roomlist" /> </FrameLayout> <RelativeLayout diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout-large/activity_localroom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/Android-build/SDL-android-project/res/layout-large/activity_localroom.xml Mon Aug 20 20:19:35 2012 +0200 @@ -0,0 +1,83 @@ +<?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="fill_parent" + android:layout_height="fill_parent" > + + <include layout="@layout/background" /> + + <RelativeLayout + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:padding="2dp" > + + <LinearLayout + android:id="@+id/upperFrame" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_alignParentLeft="true" + android:layout_alignParentRight="true" + android:layout_alignParentTop="true" + android:layout_marginBottom="4dp" + android:layout_above="@+id/startGame" + android:baselineAligned="false" + android:minHeight="200dp" > + + <FrameLayout + android:id="@+id/mapFrame" + android:layout_width="0dp" + android:layout_height="fill_parent" + android:layout_marginRight="4dp" + android:layout_weight="1" + android:background="@drawable/box" > + + <fragment + android:id="@+id/mapFragment" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + class="org.hedgewars.hedgeroid.MapFragment" + tools:layout="@layout/fragment_map" /> + </FrameLayout> + + <FrameLayout + android:id="@+id/settingsFrame" + android:layout_width="0dp" + android:layout_height="fill_parent" + android:layout_marginRight="4dp" + android:layout_weight="1" + android:background="@drawable/box" > + + <fragment + android:id="@+id/settingsFragment" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + class="org.hedgewars.hedgeroid.SettingsFragment" + tools:layout="@layout/fragment_settings" /> + </FrameLayout> + + <FrameLayout + android:id="@+id/teamsFrame" + android:layout_width="0dp" + android:layout_height="fill_parent" + android:layout_weight="1" + android:background="@drawable/box" > + + <fragment + android:id="@+id/teamsFragment" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + class="org.hedgewars.hedgeroid.TeamlistFragment" + tools:layout="@layout/fragment_teamlist" /> + </FrameLayout> + </LinearLayout> + + <Button + android:id="@id/startGame" + android:layout_width="200dp" + android:layout_height="67dp" + android:layout_alignParentBottom="true" + android:layout_centerHorizontal="true" + android:background="@drawable/startgamebutton" /> + </RelativeLayout> + +</FrameLayout> \ No newline at end of file diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout-large/activity_netroom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/Android-build/SDL-android-project/res/layout-large/activity_netroom.xml Mon Aug 20 20:19:35 2012 +0200 @@ -0,0 +1,119 @@ +<?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="fill_parent" + android:layout_height="fill_parent" > + + <include layout="@layout/background" /> + + <RelativeLayout + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:padding="2dp" > + + <LinearLayout + android:id="@+id/upperFrame" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_alignParentLeft="true" + android:layout_alignParentRight="true" + android:layout_alignParentTop="true" + android:layout_marginBottom="4dp" + android:baselineAligned="false" + android:minHeight="200dp" > + + <FrameLayout + android:id="@+id/mapFrame" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginRight="4dp" + android:layout_weight="1" + android:background="@drawable/box" > + + <fragment + android:id="@+id/mapFragment" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + class="org.hedgewars.hedgeroid.MapFragment" + tools:layout="@layout/fragment_map" /> + </FrameLayout> + + <FrameLayout + android:id="@+id/settingsFrame" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginRight="4dp" + android:layout_weight="1" + android:background="@drawable/box" > + + <fragment + android:id="@+id/settingsFragment" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + class="org.hedgewars.hedgeroid.SettingsFragment" + tools:layout="@layout/fragment_settings" /> + </FrameLayout> + + <FrameLayout + android:id="@+id/teamsFrame" + android:layout_width="0dp" + android:layout_height="fill_parent" + android:layout_weight="1" + android:background="@drawable/box" > + + <fragment + android:id="@+id/teamsFragment" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + class="org.hedgewars.hedgeroid.TeamlistFragment" + tools:layout="@layout/fragment_teamlist" /> + </FrameLayout> + </LinearLayout> + + <FrameLayout + android:id="@+id/playerFrame" + android:layout_width="200dp" + android:layout_height="fill_parent" + android:layout_above="@+id/startGame" + android:layout_alignParentRight="true" + android:layout_below="@id/upperFrame" + android:background="@drawable/box" > + + <fragment + android:id="@+id/playerListFragment" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + class="org.hedgewars.hedgeroid.RoomPlayerlistFragment" + tools:layout="@layout/fragment_playerlist" /> + </FrameLayout> + + <FrameLayout + android:layout_width="0dp" + android:layout_height="fill_parent" + android:layout_alignParentBottom="true" + android:layout_alignParentLeft="true" + android:layout_below="@id/upperFrame" + android:layout_marginRight="4dp" + android:layout_toLeftOf="@id/playerFrame" + android:background="@drawable/box" > + + <fragment + android:id="@+id/chatFragment" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + class="org.hedgewars.hedgeroid.ChatFragment" + tools:layout="@layout/fragment_chat" /> + </FrameLayout> + + <Button + android:id="@id/startGame" + android:layout_width="200dp" + android:layout_height="67dp" + android:layout_marginTop="4dp" + android:layout_alignParentBottom="true" + android:layout_alignParentRight="true" + android:background="@drawable/startgamebutton" /> + + </RelativeLayout> + +</FrameLayout> \ No newline at end of file diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout-large/fragment_roomlist.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/Android-build/SDL-android-project/res/layout-large/fragment_roomlist.xml Mon Aug 20 20:19:35 2012 +0200 @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout 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" > + + <FrameLayout + android:id="@+id/listHeader" + android:layout_width="fill_parent" + android:layout_height="wrap_content" > + <include layout="@layout/listview_room_header" /> + </FrameLayout> + + <ListView + android:id="@id/android:list" + android:layout_width="fill_parent" + android:layout_height="0dp" + android:layout_alignParentBottom="true" + android:layout_below="@+id/listHeader" + android:cacheColorHint="@android:color/transparent" + android:drawSelectorOnTop="false" + tools:listitem="@layout/listview_room" /> + + <TextView + android:id="@id/android:empty" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + android:layout_centerVertical="true" + android:text="@string/no_rooms_in_list" /> + +</RelativeLayout> \ No newline at end of file diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout-large/lobby_rooms_fragment.xml --- a/project_files/Android-build/SDL-android-project/res/layout-large/lobby_rooms_fragment.xml Mon Aug 20 20:16:37 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<RelativeLayout 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" > - - <FrameLayout - android:id="@+id/listHeader" - android:layout_width="fill_parent" - android:layout_height="wrap_content" > - <include layout="@layout/listview_room_header" /> - </FrameLayout> - - <ListView - android:id="@id/android:list" - android:layout_width="fill_parent" - android:layout_height="0dp" - android:layout_alignParentBottom="true" - android:layout_below="@+id/listHeader" - android:cacheColorHint="@android:color/transparent" - android:drawSelectorOnTop="false" - tools:listitem="@layout/listview_room" /> - - <TextView - android:id="@id/android:empty" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_centerHorizontal="true" - android:layout_centerVertical="true" - android:text="@string/no_rooms_in_list" /> - -</RelativeLayout> \ No newline at end of file diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/activity_lobby.xml --- a/project_files/Android-build/SDL-android-project/res/layout/activity_lobby.xml Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/res/layout/activity_lobby.xml Mon Aug 20 20:19:35 2012 +0200 @@ -34,7 +34,7 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" class="org.hedgewars.hedgeroid.RoomlistFragment" - tools:layout="@layout/lobby_rooms_fragment" /> + tools:layout="@layout/fragment_roomlist" /> <fragment android:id="@+id/chatFragment" diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/activity_localroom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/Android-build/SDL-android-project/res/layout/activity_localroom.xml Mon Aug 20 20:19:35 2012 +0200 @@ -0,0 +1,71 @@ +<?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="fill_parent" + android:layout_height="fill_parent" > + + <include layout="@layout/background" /> + + <TabHost + android:id="@android:id/tabhost" + android:layout_width="match_parent" + android:layout_height="match_parent" > + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="horizontal" > + + <TabWidget + android:id="@android:id/tabs" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_weight="0" /> + + <FrameLayout + android:id="@android:id/tabcontent" + android:layout_width="0dip" + android:layout_height="match_parent" + android:layout_weight="1" > + + <fragment + android:id="@+id/mapFragment" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + class="org.hedgewars.hedgeroid.MapFragment" + tools:layout="@layout/fragment_map" /> + + <fragment + android:id="@+id/settingsFragment" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + class="org.hedgewars.hedgeroid.SettingsFragment" + tools:layout="@layout/fragment_settings" /> + + + <LinearLayout + android:id="@+id/teamlistContainer" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" > + <fragment + android:id="@+id/teamlistFragment" + android:layout_width="fill_parent" + android:layout_height="0dp" + android:layout_weight="1" + class="org.hedgewars.hedgeroid.TeamlistFragment" + tools:layout="@layout/fragment_teamlist" /> + + <Button + android:id="@+id/startGame" + android:layout_width="120dp" + android:layout_height="40dp" + android:layout_gravity="right" + android:layout_marginTop="4dp" + android:background="@drawable/startgamebutton" /> + </LinearLayout> + </FrameLayout> + </LinearLayout> + </TabHost> + +</FrameLayout> \ No newline at end of file diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/activity_main.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/Android-build/SDL-android-project/res/layout/activity_main.xml Mon Aug 20 20:19:35 2012 +0200 @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="utf-8"?> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" > + + <include layout="@layout/background" /> + + <RelativeLayout + android:layout_width="fill_parent" + android:layout_height="fill_parent" > + + <View + android:id="@+id/placeholder" + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_centerInParent="true" /> + + <FrameLayout + android:id="@+id/frameLayout1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:layout_alignParentLeft="true" + android:layout_alignParentTop="true" + android:layout_toLeftOf="@id/placeholder" > + + <Button + android:id="@+id/startGame" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:drawableTop="@drawable/button_local_play" + android:text="@string/main_button_localplay" /> + </FrameLayout> + + <FrameLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:layout_alignParentRight="true" + android:layout_alignParentTop="true" + android:layout_toRightOf="@id/placeholder" > + + <Button + android:id="@+id/joinLobby" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:drawableTop="@drawable/button_network_play" + android:text="@string/main_button_netplay" /> + </FrameLayout> + </RelativeLayout> + +</FrameLayout> \ No newline at end of file diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/activity_netroom.xml --- a/project_files/Android-build/SDL-android-project/res/layout/activity_netroom.xml Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/res/layout/activity_netroom.xml Mon Aug 20 20:19:35 2012 +0200 @@ -6,29 +6,27 @@ <include layout="@layout/background" /> - <RelativeLayout - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:padding="5dp" > + <TabHost + android:id="@android:id/tabhost" + android:layout_width="match_parent" + android:layout_height="match_parent" > <LinearLayout - android:id="@+id/upperFrame" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_alignParentLeft="true" - android:layout_alignParentRight="true" - android:layout_alignParentTop="true" - android:layout_marginBottom="10dp" - android:baselineAligned="false" - android:minHeight="200dp" > - + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="horizontal" > + + <TabWidget + android:id="@android:id/tabs" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_weight="0" /> + <FrameLayout - android:id="@+id/mapFrame" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_marginRight="10dp" - android:layout_weight="1" - android:background="@drawable/box" > + android:id="@android:id/tabcontent" + android:layout_width="0dip" + android:layout_height="match_parent" + android:layout_weight="1" > <fragment android:id="@+id/mapFragment" @@ -36,15 +34,6 @@ android:layout_height="fill_parent" class="org.hedgewars.hedgeroid.MapFragment" tools:layout="@layout/fragment_map" /> - </FrameLayout> - - <FrameLayout - android:id="@+id/settingsFrame" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_marginRight="10dp" - android:layout_weight="1" - android:background="@drawable/box" > <fragment android:id="@+id/settingsFragment" @@ -52,58 +41,45 @@ android:layout_height="fill_parent" class="org.hedgewars.hedgeroid.SettingsFragment" tools:layout="@layout/fragment_settings" /> - </FrameLayout> - - <FrameLayout - android:id="@+id/teamsFrame" - android:layout_width="0dp" - android:layout_height="fill_parent" - android:layout_weight="1" - android:background="@drawable/box" > <fragment - android:id="@+id/teamsFragment" + android:id="@+id/teamlistFragment" android:layout_width="fill_parent" android:layout_height="fill_parent" class="org.hedgewars.hedgeroid.TeamlistFragment" tools:layout="@layout/fragment_teamlist" /> + + <fragment + android:id="@+id/chatFragment" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + class="org.hedgewars.hedgeroid.ChatFragment" + tools:layout="@layout/fragment_chat" /> + + <LinearLayout + android:id="@+id/playerListContainer" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" > + + <fragment + android:id="@+id/playerListFragment" + android:layout_width="fill_parent" + android:layout_height="0dp" + android:layout_weight="1" + class="org.hedgewars.hedgeroid.RoomPlayerlistFragment" + tools:layout="@layout/fragment_playerlist" /> + + <Button + android:id="@+id/startGame" + android:layout_width="120dp" + android:layout_height="40dp" + android:layout_gravity="right" + android:layout_marginTop="4dp" + android:background="@drawable/startgamebutton" /> + </LinearLayout> </FrameLayout> </LinearLayout> - - <FrameLayout - android:id="@+id/playerFrame" - android:layout_width="200dp" - android:layout_height="fill_parent" - android:layout_alignParentBottom="true" - android:layout_alignParentRight="true" - android:layout_below="@id/upperFrame" - android:background="@drawable/box" > - - <fragment - android:id="@+id/playerListFragment" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - class="org.hedgewars.hedgeroid.RoomPlayerlistFragment" - tools:layout="@layout/fragment_playerlist" /> - </FrameLayout> - - <FrameLayout - android:layout_width="0dp" - android:layout_height="fill_parent" - android:layout_alignParentBottom="true" - android:layout_alignParentLeft="true" - android:layout_below="@id/upperFrame" - android:layout_marginRight="10dp" - android:layout_toLeftOf="@id/playerFrame" - android:background="@drawable/box" > - - <fragment - android:id="@+id/chatFragment" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - class="org.hedgewars.hedgeroid.ChatFragment" - tools:layout="@layout/fragment_chat" /> - </FrameLayout> - </RelativeLayout> + </TabHost> </FrameLayout> \ No newline at end of file diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/activity_teamlist.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/Android-build/SDL-android-project/res/layout/activity_teamlist.xml Mon Aug 20 20:19:35 2012 +0200 @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent"> + + <include layout="@layout/background"/> + + <TextView + android:id="@android:id/empty" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center" + android:text="@string/teamlist_empty" /> + + <ListView + android:id="@android:id/list" + android:layout_height="fill_parent" + android:layout_width="wrap_content" + android:layout_margin="3dp" + android:background="@drawable/box" /> + + <ImageButton + android:id="@+id/btnAdd" + android:layout_width="wrap_content" + android:layout_height="50dip" + android:layout_alignParentBottom="true" + android:layout_alignParentRight="true" + android:adjustViewBounds="true" + android:scaleType="centerInside" + android:background="@android:color/transparent" + android:src="@drawable/settings" + android:contentDescription="@string/teamlist_add_content_description"/> + +</RelativeLayout> diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/backbutton.xml --- a/project_files/Android-build/SDL-android-project/res/layout/backbutton.xml Mon Aug 20 20:16:37 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<merge xmlns:android="http://schemas.android.com/apk/res/android"> - <ImageButton - android:id="@+id/btnBack" - android:layout_width="120dip" - android:layout_height="40dip" - android:layout_alignParentBottom="true" - android:layout_alignParentLeft="true" - android:adjustViewBounds="true" - android:scaleType="centerInside" - android:background="@android:color/transparent" - android:src="@drawable/backbutton"/> -</merge> \ No newline at end of file diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/config.xml --- a/project_files/Android-build/SDL-android-project/res/layout/config.xml Mon Aug 20 20:16:37 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent"> - - <ListView - android:id="@+id/listView" - android:layout_width="wrap_content" - android:layout_height="fill_parent"/> - -</RelativeLayout> - diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/fragment_map.xml --- a/project_files/Android-build/SDL-android-project/res/layout/fragment_map.xml Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/res/layout/fragment_map.xml Mon Aug 20 20:19:35 2012 +0200 @@ -15,7 +15,6 @@ android:layout_height="128dip" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" - android:layout_margin="5dip" android:background="@drawable/box" android:scaleType="fitCenter" android:src="@drawable/roomlist_preparing" /> @@ -27,7 +26,7 @@ android:layout_below="@id/mapPreview" android:stretchColumns="1" > - <TableRow> + <TableRow android:layout_marginTop="5dip" > <TextView android:layout_width="wrap_content" @@ -38,10 +37,14 @@ android:id="@+id/spinMapType" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_marginLeft = "5dip" android:background="@drawable/dropdown" /> </TableRow> - <TableRow android:id="@+id/rowMapName"> + <TableRow + android:id="@+id/rowMapName" + android:layout_marginTop="5dip" > + <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -52,34 +55,57 @@ android:id="@+id/spinMapName" android:layout_width="fill_parent" android:layout_height="wrap_content" + android:layout_marginLeft = "5dip" android:background="@drawable/dropdown" /> </TableRow> - <TableRow android:id="@+id/rowTemplateFilter"> - <TextView + + <TableRow + android:id="@+id/rowTemplateFilter" + android:layout_marginTop="5dip" + android:visibility="gone" > + + <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:text="@string/map_template" /> - + <Spinner android:id="@+id/spinTemplateFilter" android:layout_width="fill_parent" android:layout_height="wrap_content" + android:layout_marginLeft = "5dip" android:background="@drawable/dropdown" /> - </TableRow> - <TableRow android:id="@+id/rowMazeSize"> - <TextView + </TableRow> + + <TableRow + android:id="@+id/rowMazeSize" + android:layout_marginTop="5dip" + android:visibility="gone" > + + <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:text="@string/map_maze_size" /> - + <Spinner android:id="@+id/spinMazeSize" android:layout_width="fill_parent" android:layout_height="wrap_content" + android:layout_marginLeft = "5dip" android:background="@drawable/dropdown" /> - </TableRow> + </TableRow> + + <Button + android:id="@+id/btnEditDrawnMap" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_marginTop="5dip" + android:background="@drawable/button" + android:enabled="false" + android:text="@string/map_button_editdrawnmap" + android:visibility="gone" /> </TableLayout> </RelativeLayout> \ No newline at end of file diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/fragment_roomlist.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/Android-build/SDL-android-project/res/layout/fragment_roomlist.xml Mon Aug 20 20:19:35 2012 +0200 @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout 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" + android:paddingLeft="8dp" + android:paddingRight="8dp" > + + <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_room" /> + + <TextView + android:id="@id/android:empty" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:text="@string/no_rooms_in_list" /> + +</LinearLayout> \ No newline at end of file diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/fragment_settings.xml --- a/project_files/Android-build/SDL-android-project/res/layout/fragment_settings.xml Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/res/layout/fragment_settings.xml Mon Aug 20 20:19:35 2012 +0200 @@ -27,10 +27,11 @@ android:id="@+id/spinGameplay" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_marginLeft="5dip" android:background="@drawable/dropdown" /> </TableRow> - <TableRow> + <TableRow android:layout_marginTop="5dip" > <TextView android:id="@+id/txtGamescheme" @@ -42,10 +43,11 @@ android:id="@+id/spinGamescheme" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_marginLeft="5dip" android:background="@drawable/dropdown" /> </TableRow> - <TableRow> + <TableRow android:layout_marginTop="5dip" > <TextView android:id="@+id/txtweapons" @@ -57,6 +59,7 @@ android:id="@+id/spinweapons" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_marginLeft="5dip" android:background="@drawable/dropdown" /> </TableRow> </TableLayout> @@ -76,6 +79,7 @@ android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_below="@id/gameOptions" + android:layout_marginTop="5dip" android:layout_toRightOf="@+id/imgTheme" android:background="@drawable/dropdown" /> diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/fragment_teamlist.xml --- a/project_files/Android-build/SDL-android-project/res/layout/fragment_teamlist.xml Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/res/layout/fragment_teamlist.xml Mon Aug 20 20:19:35 2012 +0200 @@ -3,21 +3,32 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:orientation="vertical" > + android:orientation="vertical" + android:paddingBottom="3dp" + android:paddingLeft="5dp" + android:paddingRight="3dp" + android:paddingTop="3dp" > - <ListView + <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="0dp" - android:layout_weight="1" - android:cacheColorHint="@android:color/transparent" - /> + android:layout_weight="1" + android:cacheColorHint="@android:color/transparent" /> - <Button + <TextView + android:id="@id/android:empty" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:gravity="center" + android:text="@string/no_teams_in_list" /> + + <Button android:id="@+id/addTeamButton" android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="@string/teamlist_addteam" - android:background="@drawable/button" /> + android:background="@drawable/button" + android:text="@string/teamlist_addteam" /> </LinearLayout> \ No newline at end of file diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/lobby_rooms_fragment.xml --- a/project_files/Android-build/SDL-android-project/res/layout/lobby_rooms_fragment.xml Mon Aug 20 20:16:37 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout 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" - android:paddingLeft="8dp" - android:paddingRight="8dp" > - - <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_room" /> - - <TextView - android:id="@id/android:empty" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:text="@string/no_rooms_in_list" /> - -</LinearLayout> \ No newline at end of file diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/main.xml --- a/project_files/Android-build/SDL-android-project/res/layout/main.xml Mon Aug 20 20:16:37 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent" > - - <include layout="@layout/background" /> - - <RelativeLayout - android:layout_width="fill_parent" - android:layout_height="fill_parent" > - - <View - android:id="@+id/placeholder" - android:layout_width="0dp" - android:layout_height="0dp" - android:layout_centerInParent="true" /> - - <FrameLayout - android:id="@+id/frameLayout1" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentBottom="true" - android:layout_alignParentLeft="true" - android:layout_alignParentTop="true" - android:layout_toLeftOf="@id/placeholder" > - - <Button - android:id="@+id/startGame" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:drawableTop="@drawable/button_local_play" - android:text="@string/main_button_localplay" /> - </FrameLayout> - - <FrameLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentBottom="true" - android:layout_alignParentRight="true" - android:layout_alignParentTop="true" - android:layout_toRightOf="@id/placeholder" > - - <Button - android:id="@+id/joinLobby" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:drawableTop="@drawable/button_network_play" - android:text="@string/main_button_netplay" /> - </FrameLayout> - </RelativeLayout> - -</FrameLayout> \ No newline at end of file diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/roomlist_player_team_count.xml --- a/project_files/Android-build/SDL-android-project/res/layout/roomlist_player_team_count.xml Mon Aug 20 20:16:37 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<merge xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools"> -</merge> \ No newline at end of file diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/roomlist_player_team_count_header.xml --- a/project_files/Android-build/SDL-android-project/res/layout/roomlist_player_team_count_header.xml Mon Aug 20 20:16:37 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<merge xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools"> -</merge> \ No newline at end of file diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/savebutton.xml --- a/project_files/Android-build/SDL-android-project/res/layout/savebutton.xml Mon Aug 20 20:16:37 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<merge xmlns:android="http://schemas.android.com/apk/res/android"> - <ImageButton - android:id="@+id/btnSave" - android:layout_width="120dip" - android:layout_height="40dip" - android:layout_alignParentBottom="true" - android:layout_alignParentRight="true" - android:adjustViewBounds="true" - android:scaleType="centerInside" - android:background="@android:color/transparent" - android:src="@drawable/savebutton"/> -</merge> \ No newline at end of file diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/starting_game.xml --- a/project_files/Android-build/SDL-android-project/res/layout/starting_game.xml Mon Aug 20 20:16:37 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent"> - <include - layout="@layout/background"/> - - <ImageView - android:id="@+id/mapPreview" - android:layout_width="256dip" - android:layout_height="128dip" - android:layout_margin="5dip" - android:scaleType="fitXY" - android:background="@drawable/box" - android:src="@drawable/backbutton"/> - - <Spinner - android:id="@+id/spinMaps" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_below="@id/mapPreview" - android:layout_alignRight="@id/mapPreview" - android:layout_toRightOf="@+id/txtMap" - android:background="@drawable/dropdown"/> - <TextView - android:id="@id/txtMap" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/start_map" - android:layout_alignTop="@id/spinMaps" - android:layout_alignBottom="@id/spinMaps" - android:layout_alignLeft="@id/mapPreview" - android:gravity="center"/> - - <TableLayout - android:id="@+id/gameOptions" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_centerHorizontal="true" - android:layout_toRightOf="@id/mapPreview" - android:layout_alignParentRight="true" - android:padding="3dip" - android:layout_margin="5dip" - android:background="@drawable/box" - android:stretchColumns="0,2" - android:shrinkColumns="1"> - - <TableRow> - <TextView - android:id="@+id/txtGameplay" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/start_gameplay"/> - <Spinner - android:id="@+id/spinGameplay" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:background="@drawable/dropdown" - /> - </TableRow> - <TableRow> - <TextView - android:id="@+id/txtGamescheme" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/start_gamescheme"/> - <Spinner - android:id="@+id/spinGamescheme" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:background="@drawable/dropdown"/> - <ImageButton - android:id="@+id/btnGamescheme" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:background="@drawable/edit" - android:adjustViewBounds="true" - android:scaleType="centerInside" - android:layout_gravity="center" - android:padding="3dip"/> - </TableRow> - <TableRow> - <TextView - android:id="@+id/txtweapons" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_below="@id/txtGamescheme" - android:layout_marginTop="5dip" - android:text="@string/start_weapons"/> - - <Spinner - android:id="@+id/spinweapons" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:background="@drawable/dropdown"/> - - <ImageButton - android:id="@+id/btnweapons" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:background="@drawable/edit" - android:adjustViewBounds="true" - android:scaleType="centerInside" - android:layout_gravity="center" - android:padding="3dip"/> - </TableRow> - </TableLayout> - - <ImageView - android:id="@+id/imgTheme" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_alignTop="@+id/spinTheme" - android:layout_alignBottom="@id/spinTheme" - android:layout_alignLeft="@id/gameOptions" - android:adjustViewBounds="true"/> - - <Spinner - android:id="@id/spinTheme" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_toRightOf="@+id/imgTheme" - android:layout_alignParentRight="true" - android:layout_below="@id/gameOptions" - android:background="@drawable/dropdown"/> - - <include layout="@layout/backbutton"/> - - <LinearLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentBottom="true" - android:layout_centerHorizontal="true" - android:orientation="horizontal"> - <ImageButton - android:id="@+id/btnTeams" - android:layout_width="120dip" - android:layout_height="40dip" - android:adjustViewBounds="true" - android:scaleType="centerInside" - android:background="@android:color/transparent" - android:src="@drawable/teams"/> - <ImageView - android:id="@+id/imgTeamsCount" - android:layout_width="40dip" - android:layout_height="40dip" - android:adjustViewBounds="true" - android:scaleType="centerInside" - android:background="@android:color/transparent" - android:src="@drawable/teams_number"/> - - </LinearLayout> - - <ImageButton - android:id="@+id/btnStart" - android:layout_width="120dip" - android:layout_height="40dip" - android:layout_alignParentBottom="true" - android:layout_alignParentRight="true" - android:adjustViewBounds="true" - android:scaleType="centerInside" - android:background="@android:color/transparent" - android:src="@drawable/startgamebutton"/> - -</RelativeLayout> - diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/tab_indicator.xml --- a/project_files/Android-build/SDL-android-project/res/layout/tab_indicator.xml Mon Aug 20 20:16:37 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="0dp" - android:layout_weight="1" - android:orientation="vertical" - android:background="@drawable/box"> - - <ImageView android:id="@+id/icon" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_centerHorizontal="true" - /> - - <TextView android:id="@+id/title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:scrollHorizontally="false" - android:padding="4dp" - android:layout_alignParentBottom="true" - android:layout_centerHorizontal="true" - style="?android:attr/tabWidgetStyle" - /> -</RelativeLayout> diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/tab_indicator_vertical.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/Android-build/SDL-android-project/res/layout/tab_indicator_vertical.xml Mon Aug 20 20:19:35 2012 +0200 @@ -0,0 +1,23 @@ +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:orientation="vertical" + android:background="@drawable/box"> + + <ImageView android:id="@+id/icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + /> + + <TextView android:id="@+id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:scrollHorizontally="false" + android:padding="4dp" + android:layout_alignParentBottom="true" + android:layout_centerHorizontal="true" + style="?android:attr/tabWidgetStyle" + /> +</RelativeLayout> diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/team_selection_dialog.xml --- a/project_files/Android-build/SDL-android-project/res/layout/team_selection_dialog.xml Mon Aug 20 20:16:37 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" - android:layout_width="wrap_content" - android:layout_height="wrap_content"> - <TextView - android:id="@+id/team_selection_dialog_select" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/select"/> - <TextView - android:id="@+id/team_selection_dialog_edit" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/edit"/> - <TextView - android:id="@+id/team_selection_dialog_delete" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/delete"/> -</LinearLayout> diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/layout/team_selector.xml --- a/project_files/Android-build/SDL-android-project/res/layout/team_selector.xml Mon Aug 20 20:16:37 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<RelativeLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent"> - - <include layout="@layout/background"/> - - <ImageButton - android:id="@+id/btnAdd" - android:layout_width="wrap_content" - android:layout_height="50dip" - android:layout_alignParentBottom="true" - android:layout_alignParentRight="true" - android:adjustViewBounds="true" - android:scaleType="centerInside" - android:background="@android:color/transparent" - android:src="@drawable/settings"/> - <TextView - android:id="@+id/txtInfo" - android:layout_height="wrap_content" - android:layout_width="fill_parent" - android:layout_alignParentBottom="true" - android:layout_toRightOf="@id/btnBack" - android:layout_toLeftOf="@id/btnAdd" - android:layout_alignTop="@id/btnBack" - android:layout_margin="3dp" - android:gravity="center" - android:background="@drawable/box"/> - - - - <LinearLayout - android:orientation="horizontal" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:layout_above="@id/txtInfo" - android:layout_margin="3dp"> - - <ListView - android:id="@+id/selectedTeams" - android:layout_height="fill_parent" - android:layout_width="wrap_content" - android:layout_margin="3dp" - android:background="@drawable/box" - android:layout_weight="1"/> - - <ListView - android:id="@+id/availableTeams" - android:layout_height="fill_parent" - android:layout_width="wrap_content" - android:layout_margin="3dp" - android:background="@drawable/box" - android:layout_weight="1"/> - </LinearLayout> -</RelativeLayout> diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/menu/main_options.xml --- a/project_files/Android-build/SDL-android-project/res/menu/main_options.xml Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/res/menu/main_options.xml Mon Aug 20 20:19:35 2012 +0200 @@ -10,6 +10,10 @@ android:icon="@android:drawable/ic_menu_preferences" android:showAsAction="ifRoom|withText" /> <item + android:id="@+id/edit_teams" + android:title="@string/edit_teams_menu" + android:showAsAction="ifRoom|withText" /> + <item android:id="@+id/edit_weaponsets" android:title="@string/edit_weaponsets_menu" android:showAsAction="ifRoom|withText" /> diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/res/values/strings.xml --- a/project_files/Android-build/SDL-android-project/res/values/strings.xml Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/res/values/strings.xml Mon Aug 20 20:19:35 2012 +0200 @@ -36,14 +36,17 @@ <!-- start game --> <string name="start_gameplay">Style</string> - <string name="start_gamescheme">Game scheme</string> + <string name="start_gamescheme">Scheme</string> <string name="start_weapons">Weapons</string> <string name="start_map">Map</string> <string name="start_filter">Filter</string> <!-- Teams --> - <string name="not_enough_teams">Not enough teams</string> - <string name="teams_info_template">Selected teams = %d</string> + <string name="not_enough_teams">You need at least two teams.</string> + <string name="not_enough_clans">You need at least two different team colors (clans).</string> + <string name="teamlist_empty">No teams</string> + <string name="teamlist_add_content_description">New team</string> + <!-- Settings --> <string name="name">Name</string> <string name="name_default">Unnamed</string> @@ -76,6 +79,7 @@ <string name="map_template">Type</string> <string name="map_maze_size">Type</string> <string name="map_mission_prefix">Mission: </string> + <string name="map_button_editdrawnmap">Edit drawn map</string> <string-array name="map_types"> <item>Generated map</item> <item>Generated maze</item> @@ -106,6 +110,8 @@ <string name="teamlist_addteam">Add team</string> <string name="teamlist_color_button_description">Team color</string> <string name="teamlist_hogcount_button_description">Hog count</string> + <string name="no_teams_in_list">No teams</string> + <string name="edit_teams_menu">Edit Teams</string> <!-- Roomlist --> <string name="roomlist_header_roomname">Room Name</string> @@ -177,4 +183,11 @@ <string name="edit_weaponsets_menu">Edit Weaponsets</string> <string name="schemelist_add_button_text">New Scheme</string> + + <!-- Room activity tabs --> + <string name="room_tab_map">Map</string> + <string name="room_tab_settings">Game</string> + <string name="room_tab_teams">Teams</string> + <string name="room_tab_chat">Chat</string> + <string name="room_tab_players">Users</string> </resources> diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/BasicRoomState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/BasicRoomState.java Mon Aug 20 20:19:35 2012 +0200 @@ -0,0 +1,161 @@ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.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; either version 2 + * of the License, or (at your option) any later version. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.hedgewars.hedgeroid; + +import static org.hedgewars.hedgeroid.util.ObjectUtils.equal; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.hedgewars.hedgeroid.RoomStateManager; +import org.hedgewars.hedgeroid.Datastructures.MapRecipe; +import org.hedgewars.hedgeroid.Datastructures.Scheme; +import org.hedgewars.hedgeroid.Datastructures.TeamInGame; +import org.hedgewars.hedgeroid.Datastructures.Weaponset; + +/** + * Common base implementation for a roomstate that will call listeners on every + * change. The derived classes have to coordinate how state is changed to + * complete the implementation of the RoomStateManager interface. + * + * See {@link RoomStateManager} for a description of what this is for. + */ +public abstract class BasicRoomState implements RoomStateManager { + private final List<RoomStateManager.Listener> observers = new LinkedList<RoomStateManager.Listener>(); + + private boolean chief; + private String gameStyle; + private Scheme scheme; + private MapRecipe map; + private Weaponset weaponset; + private Map<String, TeamInGame> teams = Collections.emptyMap(); + + public final MapRecipe getMapRecipe() { + return map; + } + + public final boolean getChiefStatus() { + return chief; + } + + public final Scheme getScheme() { + return scheme; + } + + public final String getGameStyle() { + return gameStyle; + } + + public final Weaponset getWeaponset() { + return weaponset; + } + + public final Map<String, TeamInGame> getTeams() { + return teams; + } + + public final void setWeaponset(Weaponset weaponset) { + if(!equal(weaponset, this.weaponset)) { + this.weaponset = weaponset; + for(RoomStateManager.Listener observer : observers) { + observer.onWeaponsetChanged(weaponset); + } + } + } + + public final void setMapRecipe(MapRecipe map) { + if(!equal(map, this.map)) { + this.map = map; + for(RoomStateManager.Listener observer : observers) { + observer.onMapChanged(map); + } + } + } + + public final void setGameStyle(String gameStyle) { + if(!equal(gameStyle, this.gameStyle)) { + this.gameStyle = gameStyle; + for(RoomStateManager.Listener observer : observers) { + observer.onGameStyleChanged(gameStyle); + } + } + } + + public final void setScheme(Scheme scheme) { + if(!equal(scheme, this.scheme)) { + this.scheme = scheme; + for(RoomStateManager.Listener observer : observers) { + observer.onSchemeChanged(scheme); + } + } + } + + public final void setChief(boolean chief) { + if(chief != this.chief) { + this.chief = chief; + for(RoomStateManager.Listener observer : observers) { + observer.onChiefStatusChanged(chief); + } + } + } + + public final void putTeam(TeamInGame team) { + TeamInGame oldEntry = teams.get(team.team.name); + if(!equal(team, oldEntry)) { + Map<String, TeamInGame> changedMap = new TreeMap<String, TeamInGame>(teams); + changedMap.put(team.team.name, team); + teams = Collections.unmodifiableMap(changedMap); + for(RoomStateManager.Listener observer : observers) { + observer.onTeamsChanged(teams); + } + } + } + + public final void removeTeam(String teamname) { + if(teams.containsKey(teamname)) { + Map<String, TeamInGame> changedMap = new TreeMap<String, TeamInGame>(teams); + changedMap.remove(teamname); + teams = Collections.unmodifiableMap(changedMap); + for(RoomStateManager.Listener observer : observers) { + observer.onTeamsChanged(teams); + } + } + } + + public final void setTeams(Map<String, TeamInGame> newTeams) { + if(!newTeams.equals(teams)) { + teams = Collections.unmodifiableMap(new TreeMap<String, TeamInGame>(newTeams)); + for(RoomStateManager.Listener observer : observers) { + observer.onTeamsChanged(teams); + } + } + } + + public final void addListener(Listener observer) { + observers.add(observer); + } + + public final void removeListener(Listener observer) { + observers.remove(observer); + } +} diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ChatFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ChatFragment.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ChatFragment.java Mon Aug 20 20:19:35 2012 +0200 @@ -1,3 +1,22 @@ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.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; either version 2 + * of the License, or (at your option) any later version. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + package org.hedgewars.hedgeroid; import org.hedgewars.hedgeroid.R; @@ -15,11 +34,13 @@ import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; +/** + * This fragment displays a chatlog and text input field for chatting in either + * the lobby or a room. + */ public class ChatFragment extends Fragment { - public static final String ARGUMENT_INROOM = "inRoom"; - private ChatlogAdapter adapter; - private Netplay netconn; + private Netplay netplay; private MessageLog messageLog; private boolean inRoom; @@ -30,22 +51,22 @@ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - netconn = Netplay.getAppInstance(getActivity().getApplicationContext()); + netplay = Netplay.getAppInstance(getActivity().getApplicationContext()); adapter = new ChatlogAdapter(getActivity()); } @Override public void onStart() { super.onStart(); - messageLog = inRoom ? netconn.roomChatlog : netconn.lobbyChatlog; + messageLog = inRoom ? netplay.roomChatlog : netplay.lobbyChatlog; adapter.setLog(messageLog.getLog()); - messageLog.registerObserver(adapter); + messageLog.addListener(adapter); } @Override public void onStop() { super.onStop(); - messageLog.unregisterObserver(adapter); + messageLog.removeListener(adapter); } @Override @@ -70,7 +91,7 @@ String text = v.getText().toString(); if(text.length()>0) { v.setText(""); - netconn.sendChat(text); + netplay.sendChat(text); } return true; } diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ChatlogAdapter.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ChatlogAdapter.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ChatlogAdapter.java Mon Aug 20 20:19:35 2012 +0200 @@ -1,10 +1,29 @@ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.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; either version 2 + * of the License, or (at your option) any later version. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + package org.hedgewars.hedgeroid; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import org.hedgewars.hedgeroid.netplay.MessageLog.Observer; +import org.hedgewars.hedgeroid.netplay.MessageLog; import android.content.Context; import android.text.method.LinkMovementMethod; @@ -30,7 +49,14 @@ } } -public class ChatlogAdapter extends BaseAdapter implements Observer { +/** + * For performance reasons, the chatlog is implemented as ListView instead of a + * single TextView (although I later learned that TextView might also have + * facilities for efficient appending with limited backlog... oh well, this + * works). Every chat line is a line in the ListView, and this adapter prepares + * the textviews from a messagelog in an efficient way. + */ +public class ChatlogAdapter extends BaseAdapter implements MessageLog.Listener { long idOffset = 0; private List<CharSequence> log = new ArrayList<CharSequence>(); private Context context; diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ConnectingDialog.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ConnectingDialog.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ConnectingDialog.java Mon Aug 20 20:19:35 2012 +0200 @@ -1,3 +1,22 @@ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.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; either version 2 + * of the License, or (at your option) any later version. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + package org.hedgewars.hedgeroid; import org.hedgewars.hedgeroid.netplay.Netplay; @@ -12,13 +31,21 @@ import android.content.IntentFilter; import android.os.Bundle; import android.support.v4.content.LocalBroadcastManager; +import android.widget.Toast; +/** + * Indeterminate progress dialog that is shown in the MainActivity while trying + * to connect to the server. If the connection fails (disconnect before we reach + * lobby state), an error toast with the disconnect message is shown. + * + */ public class ConnectingDialog extends ConnectionDependendDialogFragment { @Override public void onStart() { super.onStart(); LocalBroadcastManager.getInstance(getActivity().getApplicationContext()).registerReceiver(connectedReceiver, new IntentFilter(Netplay.ACTION_CONNECTED)); - + LocalBroadcastManager.getInstance(getActivity().getApplicationContext()).registerReceiver(disconnectedReceiver, new IntentFilter(Netplay.ACTION_DISCONNECTED)); + if(Netplay.getAppInstance(getActivity().getApplicationContext()).getState() != State.CONNECTING) { dismiss(); } @@ -28,6 +55,7 @@ public void onStop() { super.onStop(); LocalBroadcastManager.getInstance(getActivity().getApplicationContext()).unregisterReceiver(connectedReceiver); + LocalBroadcastManager.getInstance(getActivity().getApplicationContext()).unregisterReceiver(disconnectedReceiver); } @Override @@ -52,6 +80,13 @@ } }; + private BroadcastReceiver disconnectedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Toast.makeText(getActivity(), intent.getExtras().getString(Netplay.EXTRA_MESSAGE), Toast.LENGTH_LONG).show(); + } + }; + public void onCancel(DialogInterface dialog) { super.onCancel(dialog); Netplay.getAppInstance(getActivity().getApplicationContext()).disconnect(); diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ConnectionDependendDialogFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ConnectionDependendDialogFragment.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ConnectionDependendDialogFragment.java Mon Aug 20 20:19:35 2012 +0200 @@ -1,3 +1,22 @@ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.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; either version 2 + * of the License, or (at your option) any later version. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + package org.hedgewars.hedgeroid; import org.hedgewars.hedgeroid.netplay.Netplay; @@ -11,6 +30,11 @@ import android.support.v4.app.DialogFragment; import android.support.v4.content.LocalBroadcastManager; +/** + * Helper class for DialogFragments that are supposed to be dismissed when the + * network connection is lost. This is used for some dialog fragments that + * appear during connecting (e.g. username input) + */ public class ConnectionDependendDialogFragment extends DialogFragment { @Override public void onStart() { diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/EngineProtocol/PascalExports.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/EngineProtocol/PascalExports.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/EngineProtocol/PascalExports.java Mon Aug 20 20:19:35 2012 +0200 @@ -19,6 +19,7 @@ package org.hedgewars.hedgeroid.EngineProtocol; public class PascalExports { + public static Object engineMutex = new Object(); static{ System.loadLibrary("SDL"); @@ -32,8 +33,12 @@ } public static native int HWgetMaxNumberOfTeams(); - public static native int HWterminate(boolean b); - public static native int HWGenLandPreview(int port); + private static native void HWGenLandPreview(int port); + + public static void synchronizedGenLandPreview(int port) { + synchronized(engineMutex) { + HWGenLandPreview(port); + } + } - public static Object engineMutex = new Object(); } diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/GameConnection.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/GameConnection.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/GameConnection.java Mon Aug 20 20:19:35 2012 +0200 @@ -1,5 +1,26 @@ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.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; either version 2 + * of the License, or (at your option) any later version. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + package org.hedgewars.hedgeroid; +import java.net.ConnectException; + import org.hedgewars.hedgeroid.Datastructures.GameConfig; import org.hedgewars.hedgeroid.frontlib.Flib; import org.hedgewars.hedgeroid.frontlib.Frontlib; @@ -23,106 +44,95 @@ import com.sun.jna.Memory; import com.sun.jna.Pointer; +/** + * This class handles both talking to the engine (IPC) for running a game, and + * coordinating with the netconn if it is a netgame, using the frontlib for the + * actual IPC networking communication. + * + * After creating the GameConnection object, it will communicate with the engine + * on its own thread. It shuts itself down as soon as the connection to the engine + * is lost. + */ public final class GameConnection { private static final Handler mainHandler = new Handler(Looper.getMainLooper()); + public final int port; private final HandlerThread thread; private final Handler handler; - private final TickHandler tickHandler; + private TickHandler tickHandler; private final Netplay netplay; // ==null if not a netgame private GameconnPtr conn; - - /** - * The actual connection has to be set up on a separate thread because networking - * is not allowed on the UI thread, so the port can't be queried immediately after - * creating the GameConnection object. Instead, one of these interface methods is - * called once we know which port we are listening on (or once we fail to set this up). - * Methods will be called on the UI thread. - */ - public static interface Listener { - /** - * We are listening for the engine at $port, go start the engine. - */ - void gameConnectionReady(int port); - - /** - * The connection has stopped, either because the game has ended or was interrupted, - * or maybe we failed to create the connection at all (in that case gameConnectionReady wasn't called). - */ - void gameConnectionDisconnected(int reason); + + private GameConnection(GameconnPtr conn, Netplay netplay) { + this.conn = conn; + this.port = Flib.INSTANCE.flib_gameconn_getport(conn); + this.netplay = netplay; + this.thread = new HandlerThread("IPCThread"); + thread.start(); + this.handler = new Handler(thread.getLooper()); } - private GameConnection(Netplay netplay) { - this.netplay = netplay; - thread = new HandlerThread("IPCThread"); - thread.start(); - handler = new Handler(thread.getLooper()); - tickHandler = new TickHandler(thread.getLooper(), 50, new Runnable() { - public void run() { - if(conn != null) { - Flib.INSTANCE.flib_gameconn_tick(conn); + private void setupConnection() { + tickHandler = new TickHandler(thread.getLooper(), 50, tickCb); + tickHandler.start(); + + if(netplay != null) { + mainHandler.post(new Runnable() { + public void run() { + netplay.registerGameMessageListener(gameMessageListener); } - } - }); - tickHandler.start(); + }); + Flib.INSTANCE.flib_gameconn_onChat(conn, chatCb, null); + Flib.INSTANCE.flib_gameconn_onEngineMessage(conn, engineMessageCb, null); + } + Flib.INSTANCE.flib_gameconn_onConnect(conn, connectCb, null); + Flib.INSTANCE.flib_gameconn_onDisconnect(conn, disconnectCb, null); + Flib.INSTANCE.flib_gameconn_onErrorMessage(conn, errorMessageCb, null); } - public static GameConnection forNetgame(final GameConfig config, Netplay netplay, final Listener listener) { - final GameConnection result = new GameConnection(netplay); + /** + * Start a new IPC server to communicate with the engine. + * Performs networking operations, don't run on the UI thread. + * @throws ConnectException if we can't set up the IPC server + */ + public static GameConnection forNetgame(final GameConfig config, Netplay netplay) throws ConnectException { final String playerName = netplay.getPlayerName(); - result.handler.post(new Runnable() { - public void run() { - GameconnPtr conn = Flib.INSTANCE.flib_gameconn_create(playerName, GameSetupPtr.createJavaOwned(config), true); - result.setupConnection(conn, true, listener); - } - }); + GameconnPtr conn = Flib.INSTANCE.flib_gameconn_create(playerName, GameSetupPtr.createJavaOwned(config), true); + if(conn == null) { + throw new ConnectException(); + } + GameConnection result = new GameConnection(conn, netplay); + result.setupConnection(); return result; } - public static GameConnection forLocalGame(final GameConfig config, final Listener listener) { - final GameConnection result = new GameConnection(null); - result.handler.post(new Runnable() { - public void run() { - GameconnPtr conn = Flib.INSTANCE.flib_gameconn_create("Player", GameSetupPtr.createJavaOwned(config), false); - result.setupConnection(conn, false, listener); - } - }); + /** + * Start a new IPC server to communicate with the engine. + * Performs networking operations, don't run on the UI thread. + * @throws ConnectException if we can't set up the IPC server + */ + public static GameConnection forLocalGame(final GameConfig config) throws ConnectException { + GameconnPtr conn = Flib.INSTANCE.flib_gameconn_create("Player", GameSetupPtr.createJavaOwned(config), false); + if(conn == null) { + throw new ConnectException(); + } + GameConnection result = new GameConnection(conn, null); + result.setupConnection(); return result; } - // runs on the IPCThread - private void setupConnection(GameconnPtr conn, final boolean netgame, final Listener listener) { - if(conn == null) { - mainHandler.post(new Runnable() { - public void run() { listener.gameConnectionDisconnected(Frontlib.GAME_END_ERROR); } - }); - shutdown(); - } else { - this.conn = conn; - final int port = Flib.INSTANCE.flib_gameconn_getport(conn); - mainHandler.post(new Runnable() { - public void run() { - listener.gameConnectionReady(port); - if(netgame) { - netplay.registerGameMessageListener(gameMessageListener); - } - } - }); - Flib.INSTANCE.flib_gameconn_onConnect(conn, connectCb, null); - Flib.INSTANCE.flib_gameconn_onDisconnect(conn, disconnectCb, null); - Flib.INSTANCE.flib_gameconn_onErrorMessage(conn, errorMessageCb, null); - if(netgame) { - Flib.INSTANCE.flib_gameconn_onChat(conn, chatCb, null); - Flib.INSTANCE.flib_gameconn_onEngineMessage(conn, engineMessageCb, null); - } + private final Runnable tickCb = new Runnable() { + public void run() { + Flib.INSTANCE.flib_gameconn_tick(conn); } - } + }; // runs on the IPCThread private void shutdown() { tickHandler.stop(); thread.quit(); Flib.INSTANCE.flib_gameconn_destroy(conn); + conn = null; if(netplay != null) { mainHandler.post(new Runnable() { public void run() { @@ -179,7 +189,7 @@ public void onNetDisconnected() { handler.post(new Runnable() { public void run() { - shutdown(); + Flib.INSTANCE.flib_gameconn_send_quit(conn); } }); } diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LobbyActivity.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LobbyActivity.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LobbyActivity.java Mon Aug 20 20:19:35 2012 +0200 @@ -1,27 +1,46 @@ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.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; either version 2 + * of the License, or (at your option) any later version. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + package org.hedgewars.hedgeroid; -import org.hedgewars.hedgeroid.R; import org.hedgewars.hedgeroid.NetplayStateFragment.NetplayStateListener; import org.hedgewars.hedgeroid.netplay.Netplay; import org.hedgewars.hedgeroid.netplay.Netplay.State; import org.hedgewars.hedgeroid.util.TextInputDialog; import org.hedgewars.hedgeroid.util.TextInputDialog.TextInputDialogListener; +import org.hedgewars.hedgeroid.util.UiUtils; -import android.content.Context; import android.content.Intent; -import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentTransaction; -import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; -import android.view.View; -import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TabHost; -import android.widget.TextView; +/** + * Activity for the server lobby of a hedgewars server. Allows you to chat, join + * and create rooms and interact with a list of players. + * + * Most of the functionality is handled by various fragments. + */ public class LobbyActivity extends FragmentActivity implements TextInputDialogListener, NetplayStateListener { private static final int DIALOG_CREATE_ROOM = 0; @@ -42,14 +61,15 @@ netplay = Netplay.getAppInstance(getApplicationContext()); + // Set up a tabbed UI for medium and small screens tabHost = (TabHost)findViewById(android.R.id.tabhost); if(tabHost != null) { tabHost.setup(); tabHost.getTabWidget().setOrientation(LinearLayout.VERTICAL); - tabHost.addTab(tabHost.newTabSpec("rooms").setIndicator(createIndicatorView(tabHost, R.string.lobby_tab_rooms, getResources().getDrawable(R.drawable.roomlist_ingame))).setContent(R.id.roomListFragment)); - tabHost.addTab(tabHost.newTabSpec("chat").setIndicator(createIndicatorView(tabHost, R.string.lobby_tab_chat, getResources().getDrawable(R.drawable.edit))).setContent(R.id.chatFragment)); - tabHost.addTab(tabHost.newTabSpec("players").setIndicator(createIndicatorView(tabHost, R.string.lobby_tab_players, getResources().getDrawable(R.drawable.human))).setContent(R.id.playerListFragment)); + tabHost.addTab(tabHost.newTabSpec("rooms").setIndicator(UiUtils.createTabIndicator(tabHost, R.string.lobby_tab_rooms, R.drawable.roomlist_ingame)).setContent(R.id.roomListFragment)); + tabHost.addTab(tabHost.newTabSpec("chat").setIndicator(UiUtils.createTabIndicator(tabHost, R.string.lobby_tab_chat, R.drawable.edit)).setContent(R.id.chatFragment)); + tabHost.addTab(tabHost.newTabSpec("players").setIndicator(UiUtils.createTabIndicator(tabHost, R.string.lobby_tab_players, R.drawable.human)).setContent(R.id.playerListFragment)); if (icicle != null) { tabHost.setCurrentTabByTag(icicle.getString("currentTab")); @@ -57,24 +77,6 @@ } } - private View createIndicatorView(TabHost tabHost, int label, Drawable icon) { - LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); - - View tabIndicator = inflater.inflate(R.layout.tab_indicator, - tabHost.getTabWidget(), // tab widget is the parent - false); // no inflate params - - final TextView tv = (TextView) tabIndicator.findViewById(R.id.title); - tv.setText(label); - - if(icon != null) { - final ImageView iconView = (ImageView) tabIndicator.findViewById(R.id.icon); - iconView.setImageDrawable(icon); - } - - return tabIndicator; - } - @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); @@ -99,7 +101,6 @@ @Override public void onBackPressed() { - super.onBackPressed(); netplay.disconnect(); } @@ -127,8 +128,7 @@ finish(); break; case ROOM: - case INGAME: - startActivity(new Intent(getApplicationContext(), RoomActivity.class)); + startActivity(new Intent(getApplicationContext(), NetRoomActivity.class)); break; case LOBBY: // Do nothing diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LobbyPlayerlistAdapter.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LobbyPlayerlistAdapter.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LobbyPlayerlistAdapter.java Mon Aug 20 20:19:35 2012 +0200 @@ -1,3 +1,22 @@ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.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; either version 2 + * of the License, or (at your option) any later version. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + package org.hedgewars.hedgeroid; import java.util.Comparator; @@ -11,6 +30,9 @@ import android.view.ViewGroup; import android.widget.TextView; +/** + * Simple adapter for displaying the list of players in the lobby. + */ public class LobbyPlayerlistAdapter extends ObservableTreeMapAdapter<String, Player> { @Override protected Comparator<Player> getEntryOrder() { diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LobbyPlayerlistFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LobbyPlayerlistFragment.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LobbyPlayerlistFragment.java Mon Aug 20 20:19:35 2012 +0200 @@ -1,3 +1,22 @@ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.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; either version 2 + * of the License, or (at your option) any later version. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + package org.hedgewars.hedgeroid; import org.hedgewars.hedgeroid.R; @@ -15,6 +34,10 @@ import android.view.ViewGroup; import android.widget.AdapterView.AdapterContextMenuInfo; +/** + * Shows the list of players in the lobby and allows some interactions with them + * over the context menu. + */ public class LobbyPlayerlistFragment extends ListFragment { private Netplay netplay; private LobbyPlayerlistAdapter adapter; diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LocalRoomActivity.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LocalRoomActivity.java Mon Aug 20 20:19:35 2012 +0200 @@ -0,0 +1,121 @@ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.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; either version 2 + * of the License, or (at your option) any later version. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.hedgewars.hedgeroid; + +import java.util.ArrayList; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import org.hedgewars.hedgeroid.Datastructures.GameConfig; +import org.hedgewars.hedgeroid.Datastructures.Team; +import org.hedgewars.hedgeroid.Datastructures.TeamInGame; +import org.hedgewars.hedgeroid.netplay.Netplay; +import org.hedgewars.hedgeroid.util.UiUtils; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TabHost; +import android.widget.Toast; + +/** + * This activity is used to set up a local game. + */ +public class LocalRoomActivity extends FragmentActivity implements RoomStateManager.Provider, TeamAddDialog.Listener { + private TabHost tabHost; + private RoomStateManager stateManager; + private Button startButton; + + @Override + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + // TODO find a better central location / way to set up the default scheme and weaponset + Netplay netplay = Netplay.getAppInstance(getApplicationContext()); + stateManager = new LocalRoomStateManager(netplay.defaultScheme, netplay.defaultWeaponset); + + setContentView(R.layout.activity_localroom); + startButton = (Button)findViewById(R.id.startGame); + + startButton.setOnClickListener(startButtonClickListener); + + // Set up a tabbed UI for medium and small screens + tabHost = (TabHost)findViewById(android.R.id.tabhost); + if(tabHost != null) { + tabHost.setup(); + tabHost.getTabWidget().setOrientation(LinearLayout.VERTICAL); + + tabHost.addTab(tabHost.newTabSpec("map").setIndicator(UiUtils.createTabIndicator(tabHost, R.string.room_tab_map, 0)).setContent(R.id.mapFragment)); + tabHost.addTab(tabHost.newTabSpec("settings").setIndicator(UiUtils.createTabIndicator(tabHost, R.string.room_tab_settings, 0)).setContent(R.id.settingsFragment)); + tabHost.addTab(tabHost.newTabSpec("teams").setIndicator(UiUtils.createTabIndicator(tabHost, R.string.room_tab_teams, 0)).setContent(R.id.teamlistContainer)); + + if (icicle != null) { + tabHost.setCurrentTabByTag(icicle.getString("currentTab")); + } + } + } + + @Override + protected void onSaveInstanceState(Bundle icicle) { + super.onSaveInstanceState(icicle); + if(tabHost != null) { + icicle.putString("currentTab", tabHost.getCurrentTabTag()); + } + } + + public void onTeamAddDialogSubmitted(Team newTeam) { + stateManager.requestAddTeam(newTeam, TeamInGame.getUnusedOrRandomColorIndex(stateManager.getTeams().values())); + } + + public RoomStateManager getRoomStateManager() { + return stateManager; + } + + private final OnClickListener startButtonClickListener = new OnClickListener() { + public void onClick(View v) { + Map<String, TeamInGame> teams = stateManager.getTeams(); + Set<Integer> clanColors = new TreeSet<Integer>(); + for(TeamInGame t : teams.values()) { + clanColors.add(t.ingameAttribs.colorIndex); + } + if(clanColors.size()<2) { + if(tabHost != null) { + tabHost.setCurrentTabByTag("teams"); + } + int errortext = teams.size()<2 ? R.string.not_enough_teams : R.string.not_enough_clans; + Toast.makeText(getApplicationContext(), errortext, Toast.LENGTH_SHORT).show(); + return; + } + + SDLActivity.startNetgame = false; + SDLActivity.startConfig = new GameConfig( + stateManager.getGameStyle(), + stateManager.getScheme(), + stateManager.getMapRecipe(), + new ArrayList<TeamInGame>(stateManager.getTeams().values()), + stateManager.getWeaponset()); + startActivity(new Intent(LocalRoomActivity.this, SDLActivity.class)); + } + }; +} diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LocalRoomStateManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LocalRoomStateManager.java Mon Aug 20 20:19:35 2012 +0200 @@ -0,0 +1,95 @@ +package org.hedgewars.hedgeroid; + +import org.hedgewars.hedgeroid.Datastructures.GameConfig; +import org.hedgewars.hedgeroid.Datastructures.MapRecipe; +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.Datastructures.Weaponset; + +import android.util.Log; + +/** + * This RoomStateManager is responsible for keeping/changing the roomstate in local play. + * That is very straightforward, just react to every request by immediately changing the + * state. + */ +public class LocalRoomStateManager extends BasicRoomState { + private static final String TAG = LocalRoomStateManager.class.getSimpleName(); + + public LocalRoomStateManager(Scheme defaultScheme, Weaponset defaultWeaponset) { + setChief(true); + setGameStyle(GameConfig.DEFAULT_STYLE); + setMapRecipe(MapRecipe.makeRandomMap(0, MapRecipe.makeRandomSeed(), GameConfig.DEFAULT_THEME)); + setScheme(defaultScheme); + setWeaponset(defaultWeaponset); + } + + public void changeMapRecipe(MapRecipe map) { + setMapRecipe(map); + } + + public void changeMapTheme(String theme) { + setMapRecipe(getMapRecipe().withTheme(theme)); + } + + public void changeMapNameAndGenerator(String mapName) { + int newGenerator = MapRecipe.generatorForMapname(mapName); + setMapRecipe(getMapRecipe().withName(mapName).withMapgen(newGenerator)); + } + + public void changeMapTemplate(int template) { + setMapRecipe(getMapRecipe().withTemplateFilter(template)); + } + + public void changeMazeSize(int mazeSize) { + setMapRecipe(getMapRecipe().withMazeSize(mazeSize)); + } + + public void changeMapSeed(String seed) { + setMapRecipe(getMapRecipe().withSeed(seed)); + } + + public void changeMapDrawdata(byte[] drawdata) { + setMapRecipe(getMapRecipe().withDrawData(drawdata)); + } + + public void changeScheme(Scheme scheme) { + setScheme(scheme); + } + + public void changeGameStyle(String style) { + setGameStyle(style); + } + + public void changeWeaponset(Weaponset weaponset) { + setWeaponset(weaponset); + } + + public void requestAddTeam(Team team, int colorIndex) { + putTeam(new TeamInGame(team, new TeamIngameAttributes("Player", colorIndex, TeamIngameAttributes.DEFAULT_HOG_COUNT, false))); + } + + public void requestRemoveTeam(String teamname) { + removeTeam(teamname); + } + + public void changeTeamColorIndex(String teamname, int colorIndex) { + TeamInGame oldTeam = getTeams().get(teamname); + if(oldTeam != null) { + putTeam(oldTeam.withAttribs(oldTeam.ingameAttribs.withColorIndex(colorIndex))); + } else { + Log.e(TAG, "Requested color change for unknown team "+ teamname); + } + } + + public void changeTeamHogCount(String teamname, int hogcount) { + TeamInGame oldTeam = getTeams().get(teamname); + if(oldTeam != null) { + putTeam(oldTeam.withAttribs(oldTeam.ingameAttribs.withHogCount(hogcount))); + } else { + Log.e(TAG, "Requested hog count change for unknown team "+ teamname); + } + } +} diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MainActivity.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MainActivity.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MainActivity.java Mon Aug 20 20:19:35 2012 +0200 @@ -24,7 +24,6 @@ import org.hedgewars.hedgeroid.Downloader.DownloadAssets; import org.hedgewars.hedgeroid.Downloader.DownloadListActivity; -import org.hedgewars.hedgeroid.frontlib.Flib; import org.hedgewars.hedgeroid.netplay.Netplay; import org.hedgewars.hedgeroid.netplay.Netplay.State; import org.hedgewars.hedgeroid.util.FileUtils; @@ -56,7 +55,7 @@ public void onCreate(Bundle sis){ super.onCreate(sis); - setContentView(R.layout.main); + setContentView(R.layout.activity_main); broadcastManager = LocalBroadcastManager.getInstance(getApplicationContext()); Button startLocalGame = (Button)findViewById(R.id.startGame); @@ -120,13 +119,16 @@ public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()) { case R.id.download: - startActivityForResult(new Intent(getApplicationContext(), DownloadListActivity.class), 0); + startActivityForResult(new Intent(this, DownloadListActivity.class), 0); return true; case R.id.preferences: Toast.makeText(this, R.string.not_implemented_yet, Toast.LENGTH_SHORT).show(); return true; case R.id.edit_weaponsets: - startActivity(new Intent(getApplicationContext(), WeaponsetListActivity.class)); + startActivity(new Intent(this, WeaponsetListActivity.class)); + return true; + case R.id.edit_teams: + startActivity(new Intent(this, TeamListActivity.class)); return true; default: return super.onOptionsItemSelected(item); @@ -164,7 +166,7 @@ private final OnClickListener startGameListener = new OnClickListener(){ public void onClick(View v){ - startActivity(new Intent(getApplicationContext(), StartGameActivity.class)); + startActivity(new Intent(getApplicationContext(), LocalRoomActivity.class)); } }; diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MapFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MapFragment.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MapFragment.java Mon Aug 20 20:19:35 2012 +0200 @@ -10,8 +10,6 @@ import org.hedgewars.hedgeroid.Datastructures.FrontendDataUtils; import org.hedgewars.hedgeroid.Datastructures.MapFile; import org.hedgewars.hedgeroid.Datastructures.MapRecipe; -import org.hedgewars.hedgeroid.Datastructures.Scheme; -import org.hedgewars.hedgeroid.Datastructures.Weaponset; import org.hedgewars.hedgeroid.frontlib.Frontlib; import android.content.Context; @@ -33,7 +31,7 @@ import android.widget.TableRow; import android.widget.Toast; -public class MapFragment extends Fragment implements RoomStateManager.Observer { +public class MapFragment extends Fragment { private Spinner mapTypeSpinner, mapNameSpinner, templateSpinner, mazeSizeSpinner; private TableRow nameRow, templateRow, mazeSizeRow; private ImageView mapPreview; @@ -91,7 +89,7 @@ templateSpinner = prepareSpinner(v, R.id.spinTemplateFilter, Arrays.asList(getResources().getStringArray(R.array.map_templates)), mapTemplateSelectedListener); mazeSizeSpinner = prepareSpinner(v, R.id.spinMazeSize, Arrays.asList(getResources().getStringArray(R.array.map_maze_sizes)), mazeSizeSelectedListener); - stateManager.registerObserver(this); + stateManager.addListener(roomStateChangeListener); currentMap = stateManager.getMapRecipe(); if(currentMap != null) { updateDisplay(currentMap); @@ -124,7 +122,7 @@ public void onDestroy() { super.onDestroy(); mapPreviewHandler.stop(); - stateManager.unregisterObserver(this); + stateManager.removeListener(roomStateChangeListener); } private void setChiefState(boolean chiefState) { @@ -207,27 +205,27 @@ } }; - public void onChiefStatusChanged(boolean isChief) { - setChiefState(isChief); - } - - public void onMapChanged(MapRecipe recipe) { - if(currentMap==null - || currentMap.mapgen != recipe.mapgen - || currentMap.mazeSize != recipe.mazeSize - || !currentMap.name.equals(recipe.name) - || !currentMap.seed.equals(recipe.seed) - || currentMap.templateFilter != recipe.templateFilter - || !Arrays.equals(currentMap.getDrawData(), recipe.getDrawData())) { - mapPreviewHandler.activity(); - } - updateDisplay(recipe); - currentMap = recipe; - } - - public void onGameStyleChanged(String gameStyle) { } - public void onSchemeChanged(Scheme scheme) { } - public void onWeaponsetChanged(Weaponset weaponset) { } + private final RoomStateManager.Listener roomStateChangeListener = new RoomStateManager.ListenerAdapter() { + @Override + public void onChiefStatusChanged(boolean isChief) { + setChiefState(isChief); + }; + + @Override + public void onMapChanged(MapRecipe recipe) { + if(currentMap==null + || currentMap.mapgen != recipe.mapgen + || currentMap.mazeSize != recipe.mazeSize + || !currentMap.name.equals(recipe.name) + || !currentMap.seed.equals(recipe.seed) + || currentMap.templateFilter != recipe.templateFilter + || !Arrays.equals(currentMap.getDrawData(), recipe.getDrawData())) { + mapPreviewHandler.activity(); + } + updateDisplay(recipe); + currentMap = recipe; + }; + }; private MapPreviewGenerator.Listener mapPreviewListener = new MapPreviewGenerator.Listener() { public void onMapPreviewResult(Drawable preview) { diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MapPreviewGenerator.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MapPreviewGenerator.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MapPreviewGenerator.java Mon Aug 20 20:19:35 2012 +0200 @@ -89,7 +89,11 @@ } catch (InterruptedException e) { // ignore } - } while(!resultAvailable && System.nanoTime()-startTime < 15000000000l); // 15 seconds timeout + if(System.nanoTime()-startTime > 15000000000l) { + Log.w(TAG, "Error generating map preview: timeout"); + resultAvailable = true; + } + } while(!resultAvailable); // 15 seconds timeout } finally { Flib.INSTANCE.flib_mapconn_destroy(conn); postToListener(result); @@ -117,9 +121,7 @@ new Thread(new Runnable() { public void run() { Log.d(TAG, "Starting engine "+port); - synchronized(PascalExports.engineMutex) { - PascalExports.HWGenLandPreview(port); - } + PascalExports.synchronizedGenLandPreview(port); Log.d(TAG, "Engine finished"); } }).start(); @@ -139,7 +141,6 @@ */ private final MapimageCallback successCb = new MapimageCallback() { public void callback(Pointer context, Pointer buffer, int hedgehogCount) { - Log.d(TAG, "Running success handler"); byte[] mapdata = buffer.getByteArray(0, Frontlib.MAPIMAGE_BYTES); int leftmostPixel = Frontlib.MAPIMAGE_WIDTH; @@ -192,7 +193,7 @@ private final StrCallback failureCb = new StrCallback() { public void callback(Pointer context, String reason) { - Log.e(TAG, "Error generating map preview: "+reason); + Log.w(TAG, "Error generating map preview: "+reason); result = null; resultAvailable = true; } diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/NetRoomActivity.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/NetRoomActivity.java Mon Aug 20 20:19:35 2012 +0200 @@ -0,0 +1,129 @@ +package org.hedgewars.hedgeroid; + +import org.hedgewars.hedgeroid.R; +import org.hedgewars.hedgeroid.Datastructures.GameConfig; +import org.hedgewars.hedgeroid.Datastructures.Team; +import org.hedgewars.hedgeroid.Datastructures.TeamInGame; +import org.hedgewars.hedgeroid.NetplayStateFragment.NetplayStateListener; +import org.hedgewars.hedgeroid.netplay.Netplay; +import org.hedgewars.hedgeroid.netplay.RunGameListener; +import org.hedgewars.hedgeroid.netplay.Netplay.State; +import org.hedgewars.hedgeroid.util.UiUtils; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentTransaction; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TabHost; + +public class NetRoomActivity extends FragmentActivity implements NetplayStateListener, TeamAddDialog.Listener, RoomStateManager.Provider, RunGameListener { + private TabHost tabHost; + private Netplay netplay; + private RoomStateManager stateManager; + private Button startButton; + + @Override + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + netplay = Netplay.getAppInstance(getApplicationContext()); + netplay.registerRunGameListener(this); + stateManager = netplay.getRoomStateManager(); + stateManager.addListener(roomStateChangeListener); + + setContentView(R.layout.activity_netroom); + startButton = (Button)findViewById(R.id.startGame); + + ChatFragment chatFragment = (ChatFragment)getSupportFragmentManager().findFragmentById(R.id.chatFragment); + chatFragment.setInRoom(true); + + FragmentTransaction trans = getSupportFragmentManager().beginTransaction(); + trans.add(new NetplayStateFragment(), "netplayFragment"); + trans.commit(); + + startButton.setVisibility(netplay.isChief() ? View.VISIBLE : View.GONE); + startButton.setOnClickListener(startButtonClickListener); + + // Set up a tabbed UI for medium and small screens + tabHost = (TabHost)findViewById(android.R.id.tabhost); + if(tabHost != null) { + tabHost.setup(); + tabHost.getTabWidget().setOrientation(LinearLayout.VERTICAL); + + tabHost.addTab(tabHost.newTabSpec("map").setIndicator(UiUtils.createTabIndicator(tabHost, R.string.room_tab_map, 0)).setContent(R.id.mapFragment)); + tabHost.addTab(tabHost.newTabSpec("settings").setIndicator(UiUtils.createTabIndicator(tabHost, R.string.room_tab_settings, 0)).setContent(R.id.settingsFragment)); + tabHost.addTab(tabHost.newTabSpec("teams").setIndicator(UiUtils.createTabIndicator(tabHost, R.string.room_tab_teams, 0)).setContent(R.id.teamlistFragment)); + tabHost.addTab(tabHost.newTabSpec("chat").setIndicator(UiUtils.createTabIndicator(tabHost, R.string.room_tab_chat, 0)).setContent(R.id.chatFragment)); + tabHost.addTab(tabHost.newTabSpec("players").setIndicator(UiUtils.createTabIndicator(tabHost, R.string.room_tab_players, 0)).setContent(R.id.playerListContainer)); + + if (icicle != null) { + tabHost.setCurrentTabByTag(icicle.getString("currentTab")); + } + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + stateManager.removeListener(roomStateChangeListener); + netplay.unregisterRunGameListener(this); + } + + @Override + public void onBackPressed() { + netplay.sendLeaveRoom(null); + } + + @Override + protected void onSaveInstanceState(Bundle icicle) { + super.onSaveInstanceState(icicle); + if(tabHost != null) { + icicle.putString("currentTab", tabHost.getCurrentTabTag()); + } + } + + public void onNetplayStateChanged(State newState) { + switch(newState) { + case NOT_CONNECTED: + case CONNECTING: + case LOBBY: + finish(); + break; + case ROOM: + // Do nothing + break; + default: + throw new IllegalStateException("Unknown connection state: "+newState); + } + } + + public void onTeamAddDialogSubmitted(Team newTeam) { + stateManager.requestAddTeam(newTeam, TeamInGame.getUnusedOrRandomColorIndex(stateManager.getTeams().values())); + } + + public RoomStateManager getRoomStateManager() { + return stateManager; + } + + private final OnClickListener startButtonClickListener = new OnClickListener() { + public void onClick(View v) { + netplay.sendStartGame(); + } + }; + + private final RoomStateManager.Listener roomStateChangeListener = new RoomStateManager.ListenerAdapter() { + @Override + public void onChiefStatusChanged(boolean isChief) { + startButton.setVisibility(isChief ? View.VISIBLE : View.GONE); + } + }; + + public void runGame(GameConfig config) { + SDLActivity.startConfig = config; + SDLActivity.startNetgame = true; + startActivity(new Intent(this, SDLActivity.class)); + } +} diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomActivity.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomActivity.java Mon Aug 20 20:16:37 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -package org.hedgewars.hedgeroid; - -import org.hedgewars.hedgeroid.R; -import org.hedgewars.hedgeroid.Datastructures.Team; -import org.hedgewars.hedgeroid.Datastructures.TeamInGame; -import org.hedgewars.hedgeroid.NetplayStateFragment.NetplayStateListener; -import org.hedgewars.hedgeroid.netplay.Netplay; -import org.hedgewars.hedgeroid.netplay.Netplay.State; - -import android.os.Bundle; -import android.support.v4.app.FragmentActivity; -import android.support.v4.app.FragmentTransaction; -import android.widget.TabHost; -import android.widget.Toast; - -public class RoomActivity extends FragmentActivity implements NetplayStateListener, TeamAddDialog.Listener, RoomStateManager.Provider { - private TabHost tabHost; - private Netplay netplay; - - @Override - protected void onCreate(Bundle icicle) { - super.onCreate(icicle); - netplay = Netplay.getAppInstance(getApplicationContext()); - - setContentView(R.layout.activity_netroom); - ChatFragment chatFragment = (ChatFragment)getSupportFragmentManager().findFragmentById(R.id.chatFragment); - chatFragment.setInRoom(true); - - FragmentTransaction trans = getSupportFragmentManager().beginTransaction(); - trans.add(new NetplayStateFragment(), "netplayFragment"); - trans.commit(); - - /*tabHost = (TabHost)findViewById(android.R.id.tabhost); - if(tabHost != null) { - tabHost.setup(); - tabHost.getTabWidget().setOrientation(LinearLayout.VERTICAL); - - //tabHost.addTab(tabHost.newTabSpec("chat").setIndicator(createIndicatorView(tabHost, R.string.lobby_tab_chat, getResources().getDrawable(R.drawable.edit))).setContent(R.id.chatFragment)); - //tabHost.addTab(tabHost.newTabSpec("players").setIndicator(createIndicatorView(tabHost, R.string.lobby_tab_players, getResources().getDrawable(R.drawable.human))).setContent(R.id.playerListFragment)); - - if (icicle != null) { - tabHost.setCurrentTabByTag(icicle.getString("currentTab")); - } - }*/ - } - - @Override - public void onBackPressed() { - netplay.sendLeaveRoom(null); - } - - @Override - protected void onSaveInstanceState(Bundle icicle) { - super.onSaveInstanceState(icicle); - if(tabHost != null) { - icicle.putString("currentTab", tabHost.getCurrentTabTag()); - } - } - - public void onNetplayStateChanged(State newState) { - switch(newState) { - case NOT_CONNECTED: - case CONNECTING: - case LOBBY: - finish(); - break; - case ROOM: - // Do nothing - break; - case INGAME: - //startActivity(new Intent(getApplicationContext(), RoomActivity.class)); - Toast.makeText(getApplicationContext(), R.string.not_implemented_yet, Toast.LENGTH_SHORT).show(); - break; - default: - throw new IllegalStateException("Unknown connection state: "+newState); - } - } - - public void onTeamAddDialogSubmitted(Team newTeam) { - netplay.sendAddTeam(newTeam, TeamInGame.getUnusedOrRandomColorIndex(netplay.roomTeamlist.getMap().values())); - } - - public RoomStateManager getRoomStateManager() { - return netplay.getRoomStateManager(); - } -} diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomPlayerlistFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomPlayerlistFragment.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomPlayerlistFragment.java Mon Aug 20 20:19:35 2012 +0200 @@ -1,13 +1,10 @@ package org.hedgewars.hedgeroid; import org.hedgewars.hedgeroid.R; -import org.hedgewars.hedgeroid.Datastructures.GameConfig; import org.hedgewars.hedgeroid.Datastructures.Player; import org.hedgewars.hedgeroid.Datastructures.PlayerInRoom; import org.hedgewars.hedgeroid.netplay.Netplay; -import org.hedgewars.hedgeroid.netplay.RunGameListener; -import android.content.Intent; import android.os.Bundle; import android.support.v4.app.ListFragment; import android.view.ContextMenu; @@ -21,7 +18,7 @@ import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.AdapterView.OnItemClickListener; -public class RoomPlayerlistFragment extends ListFragment implements OnItemClickListener, RunGameListener { +public class RoomPlayerlistFragment extends ListFragment implements OnItemClickListener { private Netplay netplay; private RoomPlayerlistAdapter adapter; @@ -29,7 +26,6 @@ public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); netplay = Netplay.getAppInstance(getActivity().getApplicationContext()); - netplay.registerRunGameListener(this); adapter = new RoomPlayerlistAdapter(); adapter.setSource(netplay.roomPlayerlist); setListAdapter(adapter); @@ -39,7 +35,6 @@ public void onDestroy() { super.onDestroy(); adapter.invalidate(); - netplay.unregisterRunGameListener(this); } @Override @@ -93,11 +88,4 @@ netplay.sendToggleReady(); } } - - // TODO this is really the wrong place for this... - public void runGame(GameConfig config) { - SDLActivity.startConfig = config; - SDLActivity.startNetgame = true; - startActivity(new Intent(getActivity().getApplicationContext(), SDLActivity.class)); - } } diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomStateManager.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomStateManager.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomStateManager.java Mon Aug 20 20:19:35 2012 +0200 @@ -1,24 +1,29 @@ package org.hedgewars.hedgeroid; +import java.util.Map; + import org.hedgewars.hedgeroid.Datastructures.MapRecipe; import org.hedgewars.hedgeroid.Datastructures.Scheme; +import org.hedgewars.hedgeroid.Datastructures.Team; +import org.hedgewars.hedgeroid.Datastructures.TeamInGame; import org.hedgewars.hedgeroid.Datastructures.Weaponset; /** - * This interface is supposed to abstract the handling of room state for several fragments - * that can display and manipulate it. The purpose of this is to allow using these fragments - * both for setting up networked and local games, despite the fact that for local games - * the settings can be changed immediately in memory, while they have to be sent out to the - * server for networked games. + * This interface is supposed to abstract the handling of room state for several + * fragments that can display and manipulate it. The purpose of this is to allow + * using these fragments both for setting up networked and local games, despite + * the fact that for local games the settings can be changed immediately in + * memory, while they have to be sent out to the server for networked games. * - * If/when the state changes as result of calling one of the "changeX" functions, that will - * also trigger the corresponding change listener method. There is no guarantee that calling - * a changeX method will actually change the setting (e.g. if you're not room chief). + * If/when the state changes as result of calling one of the "changeX" or + * "requestX" functions, that will also trigger the corresponding change + * listener method. There is no guarantee that calling a changeX method will + * actually change the setting (e.g. if you're not room chief). * * For local games, getChiefStatus is always true. * - * Implementations of this interface are probably not thread safe and should only be used on - * the UI thread. + * Implementations of this interface are probably not thread safe and should + * only be used on the UI thread. */ public interface RoomStateManager { // Query current state @@ -27,6 +32,7 @@ Scheme getScheme(); String getGameStyle(); Weaponset getWeaponset(); + Map<String, TeamInGame> getTeams(); // Manipulate state void changeMapRecipe(MapRecipe map); @@ -52,16 +58,31 @@ void changeGameStyle(String style); void changeWeaponset(Weaponset weaponset); - // Observe state - void registerObserver(Observer observer); - void unregisterObserver(Observer observer); + void requestAddTeam(Team team, int colorIndex); + void requestRemoveTeam(String teamname); + void changeTeamColorIndex(String teamname, int colorIndex); + void changeTeamHogCount(String teamname, int hogcount); - public interface Observer { + // Observe changes + void addListener(Listener observer); + void removeListener(Listener observer); + + public interface Listener { void onMapChanged(MapRecipe recipe); void onChiefStatusChanged(boolean isChief); void onSchemeChanged(Scheme scheme); void onGameStyleChanged(String gameStyle); void onWeaponsetChanged(Weaponset weaponset); + void onTeamsChanged(Map<String, TeamInGame> teams); + } + + public static class ListenerAdapter implements Listener { + public void onMapChanged(MapRecipe recipe) {} + public void onChiefStatusChanged(boolean isChief) {} + public void onSchemeChanged(Scheme scheme) {} + public void onGameStyleChanged(String gameStyle) {} + public void onWeaponsetChanged(Weaponset weaponset) {} + public void onTeamsChanged(Map<String, TeamInGame> teams) {} } public interface Provider { diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomlistFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomlistFragment.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomlistFragment.java Mon Aug 20 20:19:35 2012 +0200 @@ -39,7 +39,7 @@ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.lobby_rooms_fragment, container, false); + return inflater.inflate(R.layout.fragment_roomlist, container, false); } @Override diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SDLActivity.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SDLActivity.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SDLActivity.java Mon Aug 20 20:19:35 2012 +0200 @@ -1,7 +1,10 @@ package org.hedgewars.hedgeroid; - +/* + * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com> + */ +import java.io.IOException; import java.io.UnsupportedEncodingException; -import java.util.concurrent.atomic.AtomicBoolean; +import java.net.ConnectException; import javax.microedition.khronos.egl.EGL10; import javax.microedition.khronos.egl.EGLConfig; @@ -11,15 +14,8 @@ import org.hedgewars.hedgeroid.Datastructures.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.frontlib.Frontlib.IntCallback; import org.hedgewars.hedgeroid.netplay.Netplay; import org.hedgewars.hedgeroid.util.FileUtils; -import org.hedgewars.hedgeroid.util.TickHandler; - -import com.sun.jna.Pointer; import android.app.Activity; import android.content.Context; @@ -33,9 +29,6 @@ import android.media.AudioManager; import android.media.AudioTrack; import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Message; import android.util.Base64; import android.util.DisplayMetrics; import android.util.Log; @@ -61,9 +54,7 @@ // 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; // Guarded by SDLActivity.class + private static Thread mSDLThread; // Audio private static Thread mAudioThread; @@ -79,15 +70,11 @@ // Load the .so static { System.loadLibrary("SDL"); - //System.loadLibrary("SDL_image"); - //System.loadLibrary("SDL_mixer"); - //System.loadLibrary("SDL_ttf"); System.loadLibrary("main"); } // Setup protected void onCreate(Bundle savedInstanceState) { - //Log.v("SDL", "onCreate()"); super.onCreate(savedInstanceState); // So we can call stuff from static callbacks @@ -95,6 +82,7 @@ // Set up the surface mSurface = new SDLSurface(getApplication(), startConfig, startNetgame); + startConfig = null; setContentView(mSurface); } @@ -123,40 +111,18 @@ Log.v("SDL", "onDestroy()"); // Send a quit message to the application SDLActivity.nativeQuit(); - // Now wait for the SDL thread to quit - synchronized(SDLActivity.class) { - if (mSDLThread != null) { - try { - mSDLThread.join(); - } catch(Exception e) { - Log.w("SDL", "Problem stopping thread: " + e); - } - mSDLThread = null; + if (mSDLThread != null) { + try { + mSDLThread.join(); + } catch(Exception e) { + Log.w("SDL", "Problem stopping thread: " + e); } + mSDLThread = null; } + mSingleton = null; } - - // Messages from the SDLMain thread - static int COMMAND_CHANGE_TITLE = 1; - - // Handler for the messages - Handler commandHandler = new Handler() { - public void handleMessage(Message msg) { - if (msg.arg1 == COMMAND_CHANGE_TITLE) { - setTitle((String)msg.obj); - } - } - }; - - // Send a message from the SDLMain thread - void sendCommand(int command, Object data) { - Message msg = commandHandler.obtainMessage(); - msg.arg1 = command; - msg.obj = data; - commandHandler.sendMessage(msg); - } - + public static void synchronizedNativeInit(String...args) { synchronized(PascalExports.engineMutex) { nativeInit(args); @@ -188,9 +154,13 @@ flipEGL(); } - public static void setActivityTitle(String title) { + public static void setActivityTitle(final String title) { // Called from SDLMain() thread and can't directly affect the view - mSingleton.sendCommand(COMMAND_CHANGE_TITLE, title); + mSingleton.runOnUiThread(new Runnable() { + public void run() { + mSingleton.setTitle(title); + } + }); } public static Context getContext() { @@ -198,39 +168,18 @@ } public static void startApp(final int width, final int height, GameConfig config, boolean netgame) { - synchronized(SDLActivity.class) { - // Start up the C app thread TODO this is silly code - if (mSDLThread == null) { - final AtomicBoolean gameconnStartDone = new AtomicBoolean(false); - GameConnection.Listener listener = new GameConnection.Listener() { - public void gameConnectionReady(int port) { - mSDLThread = new Thread(new SDLMain(width, height, port, "Medo")); - mSDLThread.start(); - gameconnStartDone.set(true); - } - - public void gameConnectionDisconnected(int reason) { - Log.e("startApp", "disconnected: "+reason); - gameconnStartDone.set(true); - } - }; - if(netgame) { - Netplay netplay = Netplay.getAppInstance(mSingleton.getApplicationContext()); - GameConnection.forNetgame(config, netplay, listener); - } else { - GameConnection.forLocalGame(config, listener); - } - } else { - SDLActivity.nativeResume(); - } + // Start up the C app thread + if (mSDLThread == null) { + mSDLThread = new Thread(new SDLMain(width, height, config, netgame)); + mSDLThread.start(); + } else { + SDLActivity.nativeResume(); } } // EGL functions public static boolean initEGL(int majorVersion, int minorVersion) { if (SDLActivity.mEGLDisplay == null) { - //Log.v("SDL", "Starting up OpenGL ES " + majorVersion + "." + minorVersion); - try { EGL10 egl = (EGL10)EGLContext.getEGL(); @@ -248,7 +197,6 @@ renderableType = EGL_OPENGL_ES_BIT; } int[] configSpec = { - //EGL10.EGL_DEPTH_SIZE, 16, EGL10.EGL_RENDERABLE_TYPE, renderableType, EGL10.EGL_NONE }; @@ -260,15 +208,6 @@ } EGLConfig config = configs[0]; - /*int EGL_CONTEXT_CLIENT_VERSION=0x3098; - int contextAttrs[] = new int[] { EGL_CONTEXT_CLIENT_VERSION, majorVersion, EGL10.EGL_NONE }; - EGLContext ctx = egl.eglCreateContext(dpy, config, EGL10.EGL_NO_CONTEXT, contextAttrs); - - if (ctx == EGL10.EGL_NO_CONTEXT) { - Log.e("SDL", "Couldn't create context"); - return false; - } - SDLActivity.mEGLContext = ctx;*/ SDLActivity.mEGLDisplay = dpy; SDLActivity.mEGLConfig = config; SDLActivity.mGLMajor = majorVersion; @@ -454,34 +393,74 @@ Simple nativeInit() runnable */ class SDLMain implements Runnable { - + public static final String TAG = "SDLMain"; + + public static final int RQ_LOWRES = 0x00000001; // use half land array + public static final int RQ_BLURRY_LAND = 0x00000002; // downscaled terrain + public static final int RQ_NO_BACKGROUND = 0x00000004; // don't draw background + public static final int RQ_SIMPLE_ROPE = 0x00000008; // avoid drawing rope + public static final int RQ_2D_WATER = 0x00000010; // disabe 3D water effect + public static final int RQ_SIMPLE_EXPLOSIONS = 0x00000020; // no fancy explosion effects + public static final int RQ_NO_FLAKES = 0x00000040; // no flakes + public static final int RQ_NO_MENU_ANIM = 0x00000080; // ammomenu appears with no animation + public static final int RQ_NO_DROPLETS = 0x00000100; // no droplets + public static final int RQ_NO_CLAMPING = 0x00000200; // don't clamp textures + public static final int RQ_NO_TOOLTIPS = 0x00000400; // tooltips are not drawn + public static final int RQ_NO_VSYNC = 0x00000800; // don't sync on vblank + private final int surfaceWidth, surfaceHeight; - private final int port; private final String playerName; - HandlerThread thread = new HandlerThread("IPC thread"); + private final GameConfig config; + private final boolean netgame; - public SDLMain(int width, int height, int port, String playerName) { + public SDLMain(int width, int height, GameConfig config, boolean netgame) { surfaceWidth = width; surfaceHeight = height; - this.port = port; - this.playerName = playerName; + if(netgame) { + playerName = Netplay.getAppInstance(SDLActivity.getContext().getApplicationContext()).getPlayerName(); + } else { + playerName = "Player"; + } + this.config = config; + this.netgame = netgame; } public void run() { //Set up the IPC socket server to communicate with the engine - String path = FileUtils.getDataPath(SDLActivity.mSingleton);//This represents the data directory - path = path.substring(0, path.length()-1);//remove the trailing '/' - - Log.d("SDLMain", "Starting engine"); - // Runs SDL_main() with added parameters + GameConnection gameConn; + String path; try { - SDLActivity.synchronizedNativeInit(new String[] { String.valueOf(port), - String.valueOf(surfaceWidth), String.valueOf(surfaceHeight), - Integer.toString(0x40+0x10+0x100+0x2), "en.txt", Base64.encodeToString(playerName.getBytes("UTF-8"), 0), "1", "1", "1", path, "" }); - } catch (UnsupportedEncodingException e) { - throw new AssertionError(e); // never happens + if(netgame) { + Netplay netplay = Netplay.getAppInstance(SDLActivity.mSingleton.getApplicationContext()); + gameConn = GameConnection.forNetgame(config, netplay); + } else { + gameConn = GameConnection.forLocalGame(config); + } + + path = FileUtils.getDataPathFile(SDLActivity.mSingleton).getAbsolutePath(); + Log.d(TAG, "Starting engine"); + // Runs SDL_main() with added parameters + try { + String pPort = String.valueOf(gameConn.port); + String pWidth = String.valueOf(surfaceWidth); + String pHeight = String.valueOf(surfaceHeight); + String pQuality = Integer.toString(RQ_NO_FLAKES|RQ_NO_DROPLETS|RQ_SIMPLE_EXPLOSIONS); + String pPlayerName = Base64.encodeToString(playerName.getBytes("UTF-8"), 0); + SDLActivity.synchronizedNativeInit(new String[] { pPort, pWidth, pHeight, pQuality, "en.txt", pPlayerName, "1", "1", "1", path, "" }); + } catch (UnsupportedEncodingException e) { + throw new AssertionError(e); // never happens + } + Log.d(TAG, "Engine stopped"); + } catch(ConnectException e) { + Log.e(TAG, "Error starting IPC connection"); + } catch (IOException e) { + Log.e(TAG, "Missing SDCard"); } - Log.d("SDLMain", "Engine stopped"); + SDLActivity.mSingleton.runOnUiThread(new Runnable() { public void run() { + if(SDLActivity.mSingleton != null) { + SDLActivity.mSingleton.finish(); + } + }}); } } @@ -597,8 +576,9 @@ public boolean onKey(View v, int keyCode, KeyEvent event) { switch(keyCode){ case KeyEvent.KEYCODE_BACK: - PascalExports.HWterminate(true); - return true; + Log.d("SDL", "KEYCODE_BACK"); + SDLActivity.nativeQuit(); + return true; case KeyEvent.KEYCODE_VOLUME_DOWN: case KeyEvent.KEYCODE_VOLUME_UP: case KeyEvent.KEYCODE_VOLUME_MUTE: diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SettingsFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SettingsFragment.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SettingsFragment.java Mon Aug 20 20:19:35 2012 +0200 @@ -5,12 +5,14 @@ import java.io.IOException; import java.util.Collections; import java.util.List; +import java.util.Map; import org.hedgewars.hedgeroid.R; import org.hedgewars.hedgeroid.Datastructures.FrontendDataUtils; import org.hedgewars.hedgeroid.Datastructures.MapRecipe; import org.hedgewars.hedgeroid.Datastructures.Scheme; import org.hedgewars.hedgeroid.Datastructures.Schemes; +import org.hedgewars.hedgeroid.Datastructures.TeamInGame; import org.hedgewars.hedgeroid.Datastructures.Weaponset; import org.hedgewars.hedgeroid.Datastructures.Weaponsets; import org.hedgewars.hedgeroid.util.FileUtils; @@ -29,9 +31,7 @@ import android.widget.Spinner; import android.widget.Toast; -public class SettingsFragment extends Fragment implements RoomStateManager.Observer { - private static final String TAG = SettingsFragment.class.getSimpleName(); - +public class SettingsFragment extends Fragment { private Spinner styleSpinner, schemeSpinner, weaponsetSpinner, themeSpinner; private ImageView themeIcon; @@ -69,7 +69,7 @@ weaponsetSpinner = prepareSpinner(v, R.id.spinweapons, Weaponsets.toNameList(weaponsets), weaponsetSelectedListener); themeSpinner = prepareSpinner(v, R.id.spinTheme, themes, themeSelectedListener); - stateManager.registerObserver(this); + stateManager.addListener(roomStateChangeListener); if(stateManager.getGameStyle() != null) { styleSpinner.setSelection(styles.indexOf(stateManager.getGameStyle()), false); @@ -111,7 +111,7 @@ @Override public void onDestroy() { super.onDestroy(); - stateManager.unregisterObserver(this); + stateManager.removeListener(roomStateChangeListener); } private static int getSchemePosition(List<Scheme> schemes, String scheme) { @@ -182,23 +182,27 @@ public void onNothingSelected(AdapterView<?> arg0) {}; }; - public void onChiefStatusChanged(boolean isChief) { - setChiefState(isChief); - } - - public void onGameStyleChanged(String gameStyle) { - styleSpinner.setSelection(styles.indexOf(gameStyle)); - } - - public void onMapChanged(MapRecipe recipe) { - themeSpinner.setSelection(themes.indexOf(recipe.theme)); - } - - public void onSchemeChanged(Scheme scheme) { - schemeSpinner.setSelection(getSchemePosition(schemes, scheme.name)); - } - - public void onWeaponsetChanged(Weaponset weaponset) { - weaponsetSpinner.setSelection(getWeaponsetPosition(weaponsets, weaponset.name)); - } + private final RoomStateManager.Listener roomStateChangeListener = new RoomStateManager.Listener() { + public void onWeaponsetChanged(Weaponset weaponset) { + weaponsetSpinner.setSelection(getWeaponsetPosition(weaponsets, weaponset.name)); + } + + public void onTeamsChanged(Map<String, TeamInGame> teams) {} + + public void onSchemeChanged(Scheme scheme) { + schemeSpinner.setSelection(getSchemePosition(schemes, scheme.name)); + } + + public void onMapChanged(MapRecipe recipe) { + themeSpinner.setSelection(themes.indexOf(recipe.theme)); + } + + public void onGameStyleChanged(String gameStyle) { + styleSpinner.setSelection(styles.indexOf(gameStyle)); + } + + public void onChiefStatusChanged(boolean isChief) { + setChiefState(isChief); + } + }; } diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/StartGameActivity.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/StartGameActivity.java Mon Aug 20 20:16:37 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,217 +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; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.UUID; - -import org.hedgewars.hedgeroid.Datastructures.FrontendDataUtils; -import org.hedgewars.hedgeroid.Datastructures.GameConfig; -import org.hedgewars.hedgeroid.Datastructures.MapFile; -import org.hedgewars.hedgeroid.Datastructures.MapRecipe; -import org.hedgewars.hedgeroid.Datastructures.Scheme; -import org.hedgewars.hedgeroid.Datastructures.Schemes; -import org.hedgewars.hedgeroid.Datastructures.TeamInGame; -import org.hedgewars.hedgeroid.Datastructures.Weaponset; -import org.hedgewars.hedgeroid.Datastructures.Weaponsets; -import org.hedgewars.hedgeroid.util.FileUtils; - -import android.app.Activity; -import android.content.Intent; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemSelectedListener; -import android.widget.ArrayAdapter; -import android.widget.ImageButton; -import android.widget.ImageView; -import android.widget.Spinner; -import android.widget.Toast; - -public class StartGameActivity extends Activity { - public static final int ACTIVITY_TEAM_SELECTOR = 0; - - private ImageButton start, back, team; - private Spinner mapSpinner, styleSpinner, schemeSpinner, weaponsetSpinner, themeSpinner; - private ImageView themeIcon, mapPreview, teamCount; - - private List<MapFile> mapFiles; - private List<String> styles; - private List<Scheme> schemes; - private List<Weaponset> weaponsets; - private List<String> themes; - - private List<TeamInGame> teams = new ArrayList<TeamInGame>(); - - public void onCreate(Bundle savedInstanceState){ - super.onCreate(savedInstanceState); - - setContentView(R.layout.starting_game); - - back = (ImageButton) findViewById(R.id.btnBack); - team = (ImageButton) findViewById(R.id.btnTeams); - start = (ImageButton) findViewById(R.id.btnStart); - - themeIcon = (ImageView) findViewById(R.id.imgTheme); - mapPreview = (ImageView) findViewById(R.id.mapPreview); - teamCount = (ImageView) findViewById(R.id.imgTeamsCount); - - start.setOnClickListener(startClicker); - back.setOnClickListener(backClicker); - team.setOnClickListener(teamClicker); - - try { - mapFiles = FrontendDataUtils.getMaps(this); - styles = FrontendDataUtils.getGameStyles(this); - schemes = Schemes.loadAllSchemes(this); - weaponsets = Weaponsets.loadAllWeaponsets(this); - themes = FrontendDataUtils.getThemes(this); - } catch (IOException e) { - Toast.makeText(getApplicationContext(), R.string.error_missing_sdcard_or_files, Toast.LENGTH_LONG).show(); - finish(); - } - - Collections.sort(mapFiles, MapFile.MISSIONS_FIRST_NAME_ORDER); - Collections.sort(styles, String.CASE_INSENSITIVE_ORDER); - Collections.sort(schemes, Scheme.NAME_ORDER); - Collections.sort(weaponsets, Weaponset.NAME_ORDER); - Collections.sort(themes, String.CASE_INSENSITIVE_ORDER); - - List<String> mapNames = MapFile.toDisplayNameList(mapFiles, getResources()); - List<String> schemeNames = Schemes.toNameList(schemes); - List<String> weaponsetNames = Weaponsets.toNameList(weaponsets); - View rootView = findViewById(android.R.id.content); - mapSpinner = prepareSpinner(rootView, R.id.spinMaps, mapNames, mapsClicker); - styleSpinner = prepareSpinner(rootView, R.id.spinGameplay, styles, null); - schemeSpinner = prepareSpinner(rootView, R.id.spinGamescheme, schemeNames, null); - weaponsetSpinner = prepareSpinner(rootView, R.id.spinweapons, weaponsetNames, null); - themeSpinner = prepareSpinner(rootView, R.id.spinTheme, themes, themesClicker); - - // set map to first nonmission - for(int i = 0; i < mapFiles.size(); i++){ - if(!mapFiles.get(i).isMission){ - mapSpinner.setSelection(i, false); - break; - } - } - styleSpinner.setSelection(styles.indexOf(GameConfig.DEFAULT_STYLE), false); - schemeSpinner.setSelection(schemeNames.indexOf(GameConfig.DEFAULT_SCHEME), false); - weaponsetSpinner.setSelection(weaponsetNames.indexOf(GameConfig.DEFAULT_WEAPONSET), false); - themeSpinner.setSelection(themes.indexOf(GameConfig.DEFAULT_THEME), false); - } - - private static Spinner prepareSpinner(View v, int id, List<String> items, OnItemSelectedListener itemSelectedListener) { - Spinner spinner = (Spinner)v.findViewById(id); - ArrayAdapter<String> adapter = new ArrayAdapter<String>(v.getContext(), R.layout.listview_item, items); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - spinner.setAdapter(adapter); - spinner.setOnItemSelectedListener(itemSelectedListener); - return spinner; - } - - private void startTeamsActivity(){ - Intent i = new Intent(StartGameActivity.this, TeamSelectionActivity.class); - TeamSelectionActivity.activityParams = new ArrayList<TeamInGame>(teams); - startActivityForResult(i, ACTIVITY_TEAM_SELECTOR); - } - - public void onActivityResult(int requestCode, int resultCode, Intent data){ - switch(requestCode){ - case ACTIVITY_TEAM_SELECTOR: - if(resultCode == Activity.RESULT_OK){ - teams = new ArrayList<TeamInGame>(TeamSelectionActivity.activityReturn); - TeamSelectionActivity.activityReturn = Collections.emptyList(); - teamCount.getDrawable().setLevel(teams.size()); - } - break; - } - } - - - private OnItemSelectedListener themesClicker = new OnItemSelectedListener(){ - - public void onItemSelected(AdapterView<?> arg0, View view, int position, long rowId) { - String themeName = themes.get(position); - Drawable themeIconDrawable = Drawable.createFromPath(FileUtils.getDataPath(StartGameActivity.this) + "Themes/" + themeName + "/icon@2X.png"); - themeIcon.setImageDrawable(themeIconDrawable); - } - - public void onNothingSelected(AdapterView<?> arg0) { - } - - }; - - private OnItemSelectedListener mapsClicker = new OnItemSelectedListener(){ - - public void onItemSelected(AdapterView<?> arg0, View view, int position,long rowId) { - MapFile map = mapFiles.get(position); - try { - File previewFile = map.getPreviewFile(getApplicationContext()); - mapPreview.setImageDrawable(Drawable.createFromPath(previewFile.getAbsolutePath())); - } catch (FileNotFoundException e) { - mapPreview.setImageDrawable(null); - } - } - - public void onNothingSelected(AdapterView<?> arg0) { - } - - }; - - private OnClickListener startClicker = new OnClickListener(){ - public void onClick(View v) { - if(teams.size() < 2) { - Toast.makeText(getApplicationContext(), R.string.not_enough_teams, Toast.LENGTH_LONG).show(); - startTeamsActivity(); - } else { - String style = styles.get(styleSpinner.getSelectedItemPosition()); - Scheme scheme = schemes.get(schemeSpinner.getSelectedItemPosition()); - String mapName = mapFiles.get(mapSpinner.getSelectedItemPosition()).name; - String theme = themes.get(themeSpinner.getSelectedItemPosition()); - MapRecipe map = MapRecipe.makeMap(mapName, UUID.randomUUID().toString(), theme); - Weaponset weaponset = weaponsets.get(weaponsetSpinner.getSelectedItemPosition()); - SDLActivity.startConfig = new GameConfig(style, scheme, map, teams, weaponset); - SDLActivity.startNetgame = false; - Intent i = new Intent(StartGameActivity.this, SDLActivity.class); - startActivity(i); - } - } - }; - - private OnClickListener backClicker = new OnClickListener(){ - public void onClick(View v) { - finish(); - } - }; - - private OnClickListener teamClicker = new OnClickListener(){ - public void onClick(View v) { - startTeamsActivity(); - } - }; - -} diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamListActivity.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamListActivity.java Mon Aug 20 20:19:35 2012 +0200 @@ -0,0 +1,128 @@ +/* + * 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; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.hedgewars.hedgeroid.Datastructures.FrontendDataUtils; +import org.hedgewars.hedgeroid.Datastructures.Team; + +import android.app.ListActivity; +import android.content.Intent; +import android.os.Bundle; +import android.view.ContextMenu; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.AdapterView; +import android.widget.AdapterView.AdapterContextMenuInfo; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ImageButton; +import android.widget.SimpleAdapter; + +public class TeamListActivity extends ListActivity implements OnItemClickListener { + private List<Team> teams; + private ImageButton addButton; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_teamlist); + addButton = (ImageButton)findViewById(R.id.btnAdd); + addButton.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + editTeam(null); + } + }); + } + + @Override + public void onResume() { + super.onResume(); + updateList(); + getListView().setOnItemClickListener(this); + registerForContextMenu(getListView()); + } + + public void onItemClick(AdapterView<?> adapterView, View v, int position, long arg3) { + editTeam(teams.get(position).name); + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuinfo){ + menu.add(ContextMenu.NONE, 0, ContextMenu.NONE, R.string.edit); + menu.add(ContextMenu.NONE, 1, ContextMenu.NONE, R.string.delete); + } + + @Override + public boolean onContextItemSelected(MenuItem item){ + AdapterView.AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) item.getMenuInfo(); + int position = menuInfo.position; + Team team = teams.get(position); + switch(item.getItemId()){ + case 0: + editTeam(team.name); + return true; + case 1: + Team.getTeamfileByName(getApplicationContext(), team.name).delete(); + updateList(); + return true; + } + return false; + } + + private void updateList() { + teams = FrontendDataUtils.getTeams(getApplicationContext()); + Collections.sort(teams, Team.NAME_ORDER); + SimpleAdapter adapter = new SimpleAdapter(this, teamsToMaps(teams), R.layout.team_selection_entry_simple, new String[]{"txt", "img"}, new int[]{R.id.txtName, R.id.imgDifficulty}); + setListAdapter(adapter); + } + + private void editTeam(String teamName) { + Intent i = new Intent(this, TeamCreatorActivity.class); + i.putExtra(TeamCreatorActivity.PARAMETER_EXISTING_TEAMNAME, teamName); + startActivity(i); + } + + 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 List<Map<String, ?>> teamsToMaps(List<Team> teams) { + List<Map<String, ?>> result = new ArrayList<Map<String,?>>(); + for(Team t : teams) { + HashMap<String, Object> map = new HashMap<String, Object>(); + map.put("team", t); + map.put("txt", t.name); + int botlevel = t.hogs.get(0).level; + if(botlevel<0 || botlevel>=botlevelDrawables.length) { + map.put("img", R.drawable.bot1); + } else { + map.put("img", botlevelDrawables[botlevel]); + } + result.add(map); + } + return result; + } +} diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamSelectionActivity.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamSelectionActivity.java Mon Aug 20 20:16:37 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,287 +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; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -import org.hedgewars.hedgeroid.Datastructures.FrontendDataUtils; -import org.hedgewars.hedgeroid.Datastructures.Team; -import org.hedgewars.hedgeroid.Datastructures.TeamInGame; -import org.hedgewars.hedgeroid.Datastructures.TeamIngameAttributes; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.view.ContextMenu; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.AdapterView; -import android.widget.AdapterView.AdapterContextMenuInfo; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ImageButton; -import android.widget.ImageView; -import android.widget.ListView; -import android.widget.SimpleAdapter; -import android.widget.SimpleAdapter.ViewBinder; -import android.widget.TextView; - -public class TeamSelectionActivity extends Activity implements Runnable{ - private static final int ACTIVITY_TEAMCREATION = 0; - - public static volatile List<TeamInGame> activityParams; - public static volatile List<TeamInGame> activityReturn; - - private ImageButton addTeam; - private ListView availableTeams, selectedTeams; - private List<HashMap<String, Object>> availableTeamsList, selectedTeamsList; - private TextView txtInfo; - - public void onCreate(Bundle savedInstanceState){ - super.onCreate(savedInstanceState); - - setContentView(R.layout.team_selector); - - addTeam = (ImageButton) findViewById(R.id.btnAdd); - txtInfo = (TextView) findViewById(R.id.txtInfo); - selectedTeams = (ListView) findViewById(R.id.selectedTeams); - availableTeams = (ListView) findViewById(R.id.availableTeams); - addTeam.setOnClickListener(addTeamClicker); - - availableTeamsList = new ArrayList<HashMap<String, Object>>(); - SimpleAdapter adapter = new SimpleAdapter(this, availableTeamsList, R.layout.team_selection_entry_simple, new String[]{"txt", "img"}, new int[]{R.id.txtName, R.id.imgDifficulty}); - availableTeams.setAdapter(adapter); - availableTeams.setOnItemClickListener(availableClicker); - registerForContextMenu(availableTeams); - - selectedTeamsList = new ArrayList<HashMap<String, Object>>(); - adapter = new SimpleAdapter(this, selectedTeamsList, R.layout.team_selection_entry, new String[]{"txt", "img", "color", "count"}, new int[]{R.id.txtName, R.id.imgDifficulty, R.id.teamColor, R.id.teamCount}); - adapter.setViewBinder(viewBinder); - selectedTeams.setAdapter(adapter); - selectedTeams.setOnItemClickListener(selectedClicker); - - txtInfo.setText(String.format(getResources().getString(R.string.teams_info_template), selectedTeams.getChildCount())); - - new Thread(this).start();//load the teams from xml async - } - - public void run(){ - List<Team> teams = FrontendDataUtils.getTeams(this); - List<TeamInGame> existingTeams = activityParams; - final List<TeamInGame> newSelectedList = new ArrayList<TeamInGame>(); - final List<Team> newAvailableList = new ArrayList<Team>(); - - for(Team team : teams){ - boolean added = false; - for(TeamInGame existingTeam : existingTeams){ - if(team.name.equals(existingTeam.team.name)){ // add to available or add to selected - newSelectedList.add(new TeamInGame(team, existingTeam.ingameAttribs)); - added = true; - break; - } - } - if(!added) newAvailableList.add(team); - } - - this.runOnUiThread(new Runnable(){ - public void run() { - availableTeamsList.clear(); - selectedTeamsList.clear(); - for(TeamInGame t : newSelectedList) { - selectedTeamsList.add(toMap(t)); - } - for(Team t : newAvailableList) { - availableTeamsList.add(toMap(t)); - } - ((SimpleAdapter)selectedTeams.getAdapter()).notifyDataSetChanged(); - ((SimpleAdapter)availableTeams.getAdapter()).notifyDataSetChanged(); - } - }); - } - - private ViewBinder viewBinder = new ViewBinder(){ - public boolean setViewValue(View view, Object data, String textRepresentation) { - switch(view.getId()){ - case R.id.teamColor: - setTeamColor(view, (Integer)data); - return true; - case R.id.teamCount: - ((ImageView)view).getDrawable().setLevel((Integer)data); - return true; - default: - return false; - } - } - }; - - public void onActivityResult(int requestCode, int resultCode, Intent data){ - if(requestCode == ACTIVITY_TEAMCREATION){ - if(resultCode == Activity.RESULT_OK){ - updateListViews(); - } - }else{ - super.onActivityResult(requestCode, resultCode, data); - } - } - - /* - * Updates the list view when TeamCreationActivity is shutdown and the user returns to this point - */ - private void updateListViews(){ - List<Team> teams = FrontendDataUtils.getTeams(this); - availableTeamsList.clear(); - for(Team team : teams) { - availableTeamsList.add(toMap(team)); - } - - ArrayList<HashMap<String, Object>> toBeRemoved = new ArrayList<HashMap<String, Object>>(); - ArrayList<HashMap<String, Object>> toBeRemovedFromSelected = new ArrayList<HashMap<String, Object>>(); - for(HashMap<String, Object> hashmap : selectedTeamsList){ - String name = (String)hashmap.get("txt"); - boolean exists = false; - for(HashMap<String, Object> hash : availableTeamsList){ - if(name.equals((String)hash.get("txt"))){ - toBeRemoved.add(hash); - exists = true; - break; - } - } - if(!exists) { - toBeRemovedFromSelected.add(hashmap); - } - } - for(HashMap<String, Object> hash: toBeRemoved) availableTeamsList.remove(hash); - for(HashMap<String, Object> hash: toBeRemovedFromSelected) selectedTeamsList.remove(hash); - ((SimpleAdapter)selectedTeams.getAdapter()).notifyDataSetChanged(); - ((SimpleAdapter)availableTeams.getAdapter()).notifyDataSetChanged(); - } - - private void setTeamColor(View iv, int colorIndex){ - iv.setBackgroundColor(0xFF000000 + TeamIngameAttributes.TEAM_COLORS[colorIndex]); - } - - public void onBackPressed(){ - returnTeams(); - super.onBackPressed(); - } - - private OnClickListener addTeamClicker = new OnClickListener(){ - public void onClick(View v) { - startActivityForResult(new Intent(TeamSelectionActivity.this, TeamCreatorActivity.class), ACTIVITY_TEAMCREATION); - } - }; - - private OnItemClickListener availableClicker = new OnItemClickListener(){ - public void onItemClick(AdapterView<?> arg0, View arg1, int position,long arg3) { - selectAvailableTeamsItem(position); - } - }; - private OnItemClickListener selectedClicker = new OnItemClickListener(){ - public void onItemClick(AdapterView<?> arg0, View arg1, int position,long arg3) { - availableTeamsList.add((HashMap<String, Object>) selectedTeamsList.get(position)); - selectedTeamsList.remove(position); - ((SimpleAdapter)availableTeams.getAdapter()).notifyDataSetChanged(); - ((SimpleAdapter)selectedTeams.getAdapter()).notifyDataSetChanged(); - - txtInfo.setText(String.format(getResources().getString(R.string.teams_info_template), selectedTeamsList.size())); - } - - }; - - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuinfo){ - menu.add(ContextMenu.NONE, 0, ContextMenu.NONE, R.string.select); - menu.add(ContextMenu.NONE, 2, ContextMenu.NONE, R.string.edit); - menu.add(ContextMenu.NONE, 1, ContextMenu.NONE, R.string.delete); - - } - public boolean onContextItemSelected(MenuItem item){ - AdapterView.AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) item.getMenuInfo(); - int position = menuInfo.position; - Team team = (Team)availableTeamsList.get(position).get("team"); - switch(item.getItemId()){ - case 0://select - selectAvailableTeamsItem(position); - return true; - case 1://delete - Team.getTeamfileByName(getApplicationContext(), team.name).delete(); - availableTeamsList.remove(position); - ((SimpleAdapter)availableTeams.getAdapter()).notifyDataSetChanged(); - return true; - case 2://edit - Intent i = new Intent(TeamSelectionActivity.this, TeamCreatorActivity.class); - i.putExtra(TeamCreatorActivity.PARAMETER_EXISTING_TEAMNAME, team.name); - startActivityForResult(i, ACTIVITY_TEAMCREATION); - return true; - } - return false; - } - - private void selectAvailableTeamsItem(int position){ - HashMap<String, Object> hash = (HashMap<String, Object>) availableTeamsList.get(position); - int[] illegalcolors = new int[selectedTeamsList.size()]; - for(int i = 0; i < selectedTeamsList.size(); i++){ - illegalcolors[i] = (Integer)selectedTeamsList.get(i).get("color"); - } - hash.put("color", TeamIngameAttributes.randomColorIndex(illegalcolors)); - hash.put("count", TeamIngameAttributes.DEFAULT_HOG_COUNT); - - selectedTeamsList.add(hash); - availableTeamsList.remove(position); - ((SimpleAdapter)availableTeams.getAdapter()).notifyDataSetChanged(); - ((SimpleAdapter)selectedTeams.getAdapter()).notifyDataSetChanged(); - - txtInfo.setText(String.format(getResources().getString(R.string.teams_info_template), selectedTeamsList.size())); - } - - private void returnTeams() { - List<TeamInGame> result = new ArrayList<TeamInGame>(); - for(HashMap<String, Object> item : selectedTeamsList) { - result.add(new TeamInGame((Team)item.get("team"), new TeamIngameAttributes("Player", (Integer)item.get("color"), (Integer)item.get("count"), false))); - } - activityReturn = result; - setResult(Activity.RESULT_OK); - } - - 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> toMap(Team t) { - HashMap<String, Object> map = new HashMap<String, Object>(); - map.put("team", t); - map.put("txt", t.name); - int botlevel = t.hogs.get(0).level; - if(botlevel<0 || botlevel>=botlevelDrawables.length) { - map.put("img", R.drawable.bot1); - } else { - map.put("img", botlevelDrawables[botlevel]); - } - return map; - } - - private static HashMap<String, Object> toMap(TeamInGame t) { - HashMap<String, Object> map = toMap(t.team); - map.put("color", t.ingameAttribs.colorIndex); - map.put("count", t.ingameAttribs.hogCount); - return map; - } -} diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamlistAdapter.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamlistAdapter.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamlistAdapter.java Mon Aug 20 20:19:35 2012 +0200 @@ -1,11 +1,13 @@ package org.hedgewars.hedgeroid; -import java.util.Comparator; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; import org.hedgewars.hedgeroid.R; import org.hedgewars.hedgeroid.Datastructures.TeamInGame; import org.hedgewars.hedgeroid.Datastructures.TeamIngameAttributes; -import org.hedgewars.hedgeroid.util.ObservableTreeMapAdapter; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; @@ -13,18 +15,15 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; +import android.widget.BaseAdapter; import android.widget.ImageButton; import android.widget.TextView; -public class TeamlistAdapter extends ObservableTreeMapAdapter<String, TeamInGame> { +public class TeamlistAdapter extends BaseAdapter { private boolean colorHogcountEnabled = false; private Listener listener; + private List<TeamInGame> teams = new ArrayList<TeamInGame>(); - @Override - protected Comparator<TeamInGame> getEntryOrder() { - return TeamInGame.NAME_ORDER; - } - public void setColorHogcountEnabled(boolean colorHogcountEnabled) { this.colorHogcountEnabled = colorHogcountEnabled; notifyDataSetChanged(); @@ -34,6 +33,30 @@ this.listener = listener; } + public int getCount() { + return teams.size(); + } + + public TeamInGame getItem(int position) { + return teams.get(position); + } + + public long getItemId(int position) { + return position; + } + + @Override + public boolean hasStableIds() { + return false; + } + + public void updateTeamlist(Collection<TeamInGame> newTeams) { + teams.clear(); + teams.addAll(newTeams); + Collections.sort(teams, TeamInGame.NAME_ORDER); + notifyDataSetChanged(); + } + public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; if (v == null) { diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamlistFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamlistFragment.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamlistFragment.java Mon Aug 20 20:19:35 2012 +0200 @@ -3,17 +3,12 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Map; -import org.hedgewars.hedgeroid.R; -import org.hedgewars.hedgeroid.Datastructures.MapRecipe; -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.Datastructures.Weaponset; -import org.hedgewars.hedgeroid.netplay.Netplay; -import android.database.DataSetObserver; import android.os.Bundle; import android.support.v4.app.ListFragment; import android.view.LayoutInflater; @@ -22,15 +17,9 @@ import android.view.ViewGroup; import android.widget.Button; -/** - * TODO use an interface for querying and manipulating the team list, to allow re-using this fragment - * in local play - */ -public class TeamlistFragment extends ListFragment implements TeamlistAdapter.Listener, RoomStateManager.Observer { - private Netplay netplay; +public class TeamlistFragment extends ListFragment implements TeamlistAdapter.Listener { private TeamlistAdapter adapter; private Button addTeamButton; - private DataSetObserver teamlistObserver; private RoomStateManager stateManager; @Override @@ -41,13 +30,12 @@ } catch(ClassCastException e) { throw new RuntimeException("Hosting activity must implement RoomStateManager.Provider.", e); } - netplay = Netplay.getAppInstance(getActivity().getApplicationContext()); adapter = new TeamlistAdapter(); - adapter.setSource(netplay.roomTeamlist); + adapter.updateTeamlist(stateManager.getTeams().values()); adapter.setColorHogcountEnabled(stateManager.getChiefStatus()); adapter.setListener(this); setListAdapter(adapter); - stateManager.registerObserver(this); + stateManager.addListener(roomStateChangeListener); } @Override @@ -61,14 +49,7 @@ } }); - teamlistObserver = new DataSetObserver() { - @Override - public void onChanged() { - addTeamButton.setEnabled(netplay.roomTeamlist.getMap().size() < Team.maxNumberOfTeams); - } - }; - netplay.roomTeamlist.registerObserver(teamlistObserver); - teamlistObserver.onChanged(); + addTeamButton.setEnabled(stateManager.getTeams().size() < Team.maxNumberOfTeams); return v; } @@ -76,27 +57,20 @@ @Override public void onDestroy() { super.onDestroy(); - adapter.invalidate(); adapter.setListener(null); - netplay.roomTeamlist.unregisterObserver(teamlistObserver); - stateManager.unregisterObserver(this); + stateManager.removeListener(roomStateChangeListener); } - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - } - private Collection<String> getCurrentTeamNames() { List<String> names = new ArrayList<String>(); - for(TeamInGame team : netplay.roomTeamlist.getMap().values()) { + for(TeamInGame team : stateManager.getTeams().values()) { names.add(team.team.name); } return names; } public void onColorClicked(TeamInGame team) { - netplay.changeTeamColorIndex(team.team.name, (team.ingameAttribs.colorIndex+1)%TeamIngameAttributes.TEAM_COLORS.length); + stateManager.changeTeamColorIndex(team.team.name, (team.ingameAttribs.colorIndex+1)%TeamIngameAttributes.TEAM_COLORS.length); } public void onHogcountClicked(TeamInGame team) { @@ -104,19 +78,23 @@ if(newHogCount>Team.HEDGEHOGS_PER_TEAM) { newHogCount = 1; } - netplay.changeTeamHogCount(team.team.name, newHogCount); + stateManager.changeTeamHogCount(team.team.name, newHogCount); } public void onTeamClicked(TeamInGame team) { - netplay.sendRemoveTeam(team.team.name); + stateManager.requestRemoveTeam(team.team.name); } - public void onChiefStatusChanged(boolean isChief) { - adapter.setColorHogcountEnabled(isChief); - } - - public void onGameStyleChanged(String gameStyle) { } - public void onMapChanged(MapRecipe recipe) { } - public void onSchemeChanged(Scheme scheme) { } - public void onWeaponsetChanged(Weaponset weaponset) { } + private final RoomStateManager.Listener roomStateChangeListener = new RoomStateManager.ListenerAdapter() { + @Override + public void onChiefStatusChanged(boolean isChief) { + adapter.setColorHogcountEnabled(isChief); + }; + + @Override + public void onTeamsChanged(Map<String, TeamInGame> teams) { + adapter.updateTeamlist(teams.values()); + addTeamButton.setEnabled(teams.size() < Team.maxNumberOfTeams); + }; + }; } diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/Flib.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/Flib.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/Flib.java Mon Aug 20 20:19:35 2012 +0200 @@ -29,7 +29,7 @@ } }; static { - INSTANCE.flib_log_setLevel(Frontlib.FLIB_LOGLEVEL_ALL); + INSTANCE.flib_log_setLevel(Frontlib.FLIB_LOGLEVEL_INFO); INSTANCE.flib_log_setCallback(logCb); } } \ No newline at end of file diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/Frontlib.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/Frontlib.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/Frontlib.java Mon Aug 20 20:19:35 2012 +0200 @@ -1,6 +1,5 @@ package org.hedgewars.hedgeroid.frontlib; import java.io.UnsupportedEncodingException; -import java.nio.Buffer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -1067,7 +1066,7 @@ 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_onSchemeChanged(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); @@ -1081,8 +1080,8 @@ static final int GAME_END_ERROR = 3; GameconnPtr flib_gameconn_create(String playerName, GameSetupPtr setup, boolean netgame); - GameconnPtr flib_gameconn_create_playdemo(Buffer demo, NativeSizeT size); - GameconnPtr flib_gameconn_create_loadgame(String playerName, Buffer save, NativeSizeT size); + GameconnPtr flib_gameconn_create_playdemo(Pointer demo, NativeSizeT size); + GameconnPtr flib_gameconn_create_loadgame(String playerName, Pointer save, NativeSizeT size); GameconnPtr flib_gameconn_create_campaign(String playerName, String seed, String script); void flib_gameconn_destroy(GameconnPtr conn); @@ -1093,6 +1092,7 @@ int flib_gameconn_send_textmsg(GameconnPtr conn, int msgtype, String msg); int flib_gameconn_send_chatmsg(GameconnPtr conn, String playername, String msg); int flib_gameconn_send_quit(GameconnPtr conn); + int flib_gameconn_send_cmd(GameconnPtr conn, String cmdString); void flib_gameconn_onConnect(GameconnPtr conn, VoidCallback callback, Pointer context); void flib_gameconn_onDisconnect(GameconnPtr conn, IntCallback callback, Pointer context); diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/MessageLog.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/MessageLog.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/MessageLog.java Mon Aug 20 20:19:35 2012 +0200 @@ -35,7 +35,7 @@ private static final int ERROR_COLOR = Color.RED; private final Context context; - private List<Observer> observers = new LinkedList<Observer>(); + private List<Listener> observers = new LinkedList<Listener>(); private List<CharSequence> log = new LinkedList<CharSequence>(); public MessageLog(Context context) { @@ -70,12 +70,12 @@ private void appendRaw(CharSequence msg) { if(log.size() > BACKLOG_LINES) { log.remove(0); - for(Observer o : observers) { + for(Listener o : observers) { o.lineRemoved(); } } log.add(msg); - for(Observer o : observers) { + for(Listener o : observers) { o.lineAdded(msg); } } @@ -113,7 +113,6 @@ append(withColor("***"+msg, WARN_COLOR)); break; case Frontlib.NETCONN_MSG_TYPE_PLAYERINFO: - // TODO Display in popup? append(withColor(msg.replace("\n", " "), PLAYERINFO_COLOR)); break; case Frontlib.NETCONN_MSG_TYPE_SERVERMESSAGE: @@ -125,21 +124,21 @@ } void clear() { - for(Observer o : observers) { + for(Listener o : observers) { o.clear(); } log.clear(); } - public void registerObserver(Observer o) { + public void addListener(Listener o) { observers.add(o); } - public void unregisterObserver(Observer o) { + public void removeListener(Listener o) { observers.remove(o); } - public static interface Observer { + public static interface Listener { void lineAdded(CharSequence text); void lineRemoved(); void clear(); diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/NetRoomState.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/NetRoomState.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/NetRoomState.java Mon Aug 20 20:19:35 2012 +0200 @@ -1,202 +1,130 @@ package org.hedgewars.hedgeroid.netplay; -import static org.hedgewars.hedgeroid.netplay.ThreadedNetConnection.ToNetMsgType.MSG_SEND_GAMESTYLE; -import static org.hedgewars.hedgeroid.netplay.ThreadedNetConnection.ToNetMsgType.MSG_SEND_MAP; -import static org.hedgewars.hedgeroid.netplay.ThreadedNetConnection.ToNetMsgType.MSG_SEND_MAP_DRAWDATA; -import static org.hedgewars.hedgeroid.netplay.ThreadedNetConnection.ToNetMsgType.MSG_SEND_MAP_GENERATOR; -import static org.hedgewars.hedgeroid.netplay.ThreadedNetConnection.ToNetMsgType.MSG_SEND_MAP_NAME; -import static org.hedgewars.hedgeroid.netplay.ThreadedNetConnection.ToNetMsgType.MSG_SEND_MAP_SEED; -import static org.hedgewars.hedgeroid.netplay.ThreadedNetConnection.ToNetMsgType.MSG_SEND_MAP_TEMPLATE; -import static org.hedgewars.hedgeroid.netplay.ThreadedNetConnection.ToNetMsgType.MSG_SEND_MAP_THEME; -import static org.hedgewars.hedgeroid.netplay.ThreadedNetConnection.ToNetMsgType.MSG_SEND_MAZE_SIZE; -import static org.hedgewars.hedgeroid.netplay.ThreadedNetConnection.ToNetMsgType.MSG_SEND_SCHEME; -import static org.hedgewars.hedgeroid.netplay.ThreadedNetConnection.ToNetMsgType.MSG_SEND_WEAPONSET; +import static org.hedgewars.hedgeroid.netplay.ThreadedNetConnection.ToNetMsgType.*; +import static org.hedgewars.hedgeroid.util.ObjectUtils.equal; import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; -import org.hedgewars.hedgeroid.RoomStateManager; +import org.hedgewars.hedgeroid.BasicRoomState; import org.hedgewars.hedgeroid.Datastructures.GameConfig; import org.hedgewars.hedgeroid.Datastructures.MapRecipe; 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.Datastructures.Weaponset; import org.hedgewars.hedgeroid.netplay.ThreadedNetConnection.ToNetMsgType; /** * This class manages the room state in a network game. */ -class NetRoomState implements RoomStateManager { - private List<RoomStateManager.Observer> observers = new LinkedList<RoomStateManager.Observer>(); +class NetRoomState extends BasicRoomState { + final Map<String, TeamInGame> requestedTeams = new TreeMap<String, TeamInGame>(); private Netplay netplay; - boolean chief; - String gameStyle; - Scheme scheme; - MapRecipe map; - Weaponset weaponset; - public NetRoomState(Netplay netplay) { this.netplay = netplay; - this.map = MapRecipe.makeRandomMap(0, "seed", GameConfig.DEFAULT_THEME); - } - - public MapRecipe getMapRecipe() { - return map; - } - - public boolean getChiefStatus() { - return chief; - } - - public Scheme getScheme() { - return scheme; - } - - public String getGameStyle() { - return gameStyle; - } - - public Weaponset getWeaponset() { - return weaponset; + initRoomState(false); } public void changeWeaponset(Weaponset weaponset) { - if(chief && !weaponset.equals(this.weaponset)) { + if(getChiefStatus() && !equal(weaponset, getWeaponset())) { sendToNet(MSG_SEND_WEAPONSET, weaponset); setWeaponset(weaponset); } } public void changeMapRecipe(MapRecipe mapRecipe) { - if(chief && !mapRecipe.equals(this.map)) { + if(getChiefStatus() && !equal(mapRecipe, getMapRecipe())) { sendToNet(MSG_SEND_MAP, mapRecipe); setMapRecipe(mapRecipe); } } public void changeMapNameAndGenerator(String mapName) { - if(chief && !mapName.equals(this.map.name)) { + if(getChiefStatus() && !equal(mapName, getMapRecipe().name)) { int newGenerator = MapRecipe.generatorForMapname(mapName); - if(newGenerator != this.map.mapgen) { + if(newGenerator != getMapRecipe().mapgen) { sendToNet(MSG_SEND_MAP_GENERATOR, newGenerator, null); } sendToNet(MSG_SEND_MAP_NAME, mapName); - setMapRecipe(map.withName(mapName).withMapgen(newGenerator)); + setMapRecipe(getMapRecipe().withName(mapName).withMapgen(newGenerator)); } } public void changeMapTemplate(int template) { - if(chief && template != this.map.templateFilter) { + if(getChiefStatus() && template != getMapRecipe().templateFilter) { sendToNet(MSG_SEND_MAP_TEMPLATE, template, null); - setMapRecipe(map.withTemplateFilter(template)); + setMapRecipe(getMapRecipe().withTemplateFilter(template)); } } public void changeMazeSize(int mazeSize) { - if(chief && mazeSize != this.map.mazeSize) { + if(getChiefStatus() && mazeSize != getMapRecipe().mazeSize) { sendToNet(MSG_SEND_MAZE_SIZE, mazeSize, 0); - setMapRecipe(map.withMazeSize(mazeSize)); + setMapRecipe(getMapRecipe().withMazeSize(mazeSize)); } } public void changeMapSeed(String seed) { - if(chief && !seed.equals(this.map.seed)) { + if(getChiefStatus() && !equal(seed, getMapRecipe().seed)) { sendToNet(MSG_SEND_MAP_SEED, seed); - setMapRecipe(map.withSeed(seed)); + setMapRecipe(getMapRecipe().withSeed(seed)); } } public void changeMapTheme(String theme) { - if(chief && !theme.equals(this.map.theme)) { + if(getChiefStatus() && !equal(theme, getMapRecipe().theme)) { sendToNet(MSG_SEND_MAP_THEME, theme); - setMapRecipe(map.withTheme(theme)); + setMapRecipe(getMapRecipe().withTheme(theme)); } } public void changeMapDrawdata(byte[] drawdata) { - if(chief && !Arrays.equals(drawdata, this.map.getDrawData())) { + if(getChiefStatus() && !Arrays.equals(drawdata, getMapRecipe().getDrawData())) { sendToNet(MSG_SEND_MAP_DRAWDATA, drawdata); - setMapRecipe(map.withDrawData(drawdata)); + setMapRecipe(getMapRecipe().withDrawData(drawdata)); } } public void changeGameStyle(String gameStyle) { - if(chief && !gameStyle.equals(this.gameStyle)) { + if(getChiefStatus() && !equal(gameStyle, getGameStyle())) { sendToNet(MSG_SEND_GAMESTYLE, gameStyle); setGameStyle(gameStyle); } } public void changeScheme(Scheme scheme) { - if(chief && !scheme.equals(this.scheme)) { + if(getChiefStatus() && !equal(scheme, getScheme())) { sendToNet(MSG_SEND_SCHEME, scheme); setScheme(scheme); } } - void setWeaponset(Weaponset weaponset) { - if(!weaponset.equals(this.weaponset)) { - this.weaponset = weaponset; - for(RoomStateManager.Observer observer : observers) { - observer.onWeaponsetChanged(weaponset); - } - } - } - - void setMapRecipe(MapRecipe map) { - if(!map.equals(this.map)) { - this.map = map; - for(RoomStateManager.Observer observer : observers) { - observer.onMapChanged(map); - } - } - } - - void setGameStyle(String gameStyle) { - if(!gameStyle.equals(this.gameStyle)) { - this.gameStyle = gameStyle; - for(RoomStateManager.Observer observer : observers) { - observer.onGameStyleChanged(gameStyle); - } - } - } - - void setScheme(Scheme scheme) { - if(!scheme.equals(this.scheme)) { - this.scheme = scheme; - for(RoomStateManager.Observer observer : observers) { - observer.onSchemeChanged(scheme); - } - } - } - - void setChief(boolean chief) { - if(chief != this.chief) { - this.chief = chief; - for(RoomStateManager.Observer observer : observers) { - observer.onChiefStatusChanged(chief); - } - } + void initRoomState(boolean chief) { + setTeams(Collections.<String, TeamInGame>emptyMap()); + requestedTeams.clear(); + + setChief(chief); + setGameStyle(GameConfig.DEFAULT_STYLE); + setMapRecipe(MapRecipe.makeRandomMap(0, "seed", GameConfig.DEFAULT_THEME)); + setScheme(netplay.defaultScheme); + setWeaponset(netplay.defaultWeaponset); + sendFullConfig(); } void sendFullConfig() { - if(chief) { - sendToNet(MSG_SEND_GAMESTYLE, gameStyle); - sendToNet(MSG_SEND_SCHEME, scheme); - sendToNet(MSG_SEND_WEAPONSET, weaponset); - sendToNet(MSG_SEND_MAP, map); + if(getChiefStatus()) { + sendToNet(MSG_SEND_GAMESTYLE, getGameStyle()); + sendToNet(MSG_SEND_SCHEME, getScheme()); + sendToNet(MSG_SEND_WEAPONSET, getWeaponset()); + sendToNet(MSG_SEND_MAP, getMapRecipe()); } } - public void registerObserver(Observer observer) { - observers.add(observer); - } - - public void unregisterObserver(Observer observer) { - observers.remove(observer); - } - private boolean sendToNet(ToNetMsgType what, Object obj) { return netplay.sendToNet(what, 0, obj); } @@ -204,4 +132,35 @@ private boolean sendToNet(ToNetMsgType what, int arg1, Object obj) { return netplay.sendToNet(what, arg1, obj); } + + public void requestAddTeam(Team team, int colorIndex) { + TeamIngameAttributes tia = new TeamIngameAttributes(netplay.getPlayerName(), colorIndex, TeamIngameAttributes.DEFAULT_HOG_COUNT, false); + TeamInGame newTeamInGame = new TeamInGame(team, tia); + requestedTeams.put(team.name, newTeamInGame); + sendToNet(MSG_SEND_ADD_TEAM, newTeamInGame); + } + + public void requestRemoveTeam(String teamname) { + sendToNet(MSG_SEND_REMOVE_TEAM, teamname); + } + + public void changeTeamColorIndex(String teamname, int colorIndex) { + if(getChiefStatus()) { + TeamInGame team = getTeams().get(teamname); + if(team.ingameAttribs.colorIndex != colorIndex) { + sendToNet(MSG_SEND_TEAM_COLOR_INDEX, colorIndex, teamname); + putTeam(team.withAttribs(team.ingameAttribs.withColorIndex(colorIndex))); + } + } + } + + public void changeTeamHogCount(String teamname, int hogcount) { + if(getChiefStatus()) { + TeamInGame team = getTeams().get(teamname); + if(team.ingameAttribs.hogCount != hogcount) { + sendToNet(MSG_SEND_TEAM_HOG_COUNT, hogcount, teamname); + putTeam(team.withAttribs(team.ingameAttribs.withHogCount(hogcount))); + } + } + } } diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Netplay.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Netplay.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Netplay.java Mon Aug 20 20:19:35 2012 +0200 @@ -7,8 +7,6 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; -import java.util.Map; -import java.util.TreeMap; import org.hedgewars.hedgeroid.RoomStateManager; import org.hedgewars.hedgeroid.Datastructures.GameConfig; @@ -18,7 +16,6 @@ import org.hedgewars.hedgeroid.Datastructures.Room; import org.hedgewars.hedgeroid.Datastructures.Scheme; import org.hedgewars.hedgeroid.Datastructures.Schemes; -import org.hedgewars.hedgeroid.Datastructures.Team; import org.hedgewars.hedgeroid.Datastructures.TeamInGame; import org.hedgewars.hedgeroid.Datastructures.TeamIngameAttributes; import org.hedgewars.hedgeroid.Datastructures.Weaponset; @@ -42,7 +39,7 @@ * This class manages the application's networking state. */ public class Netplay { - public static enum State { NOT_CONNECTED, CONNECTING, LOBBY, ROOM, INGAME } + public static enum State { NOT_CONNECTED, CONNECTING, LOBBY, ROOM } // Extras in broadcasts public static final String EXTRA_PLAYERNAME = "playerName"; @@ -64,6 +61,8 @@ private final Context appContext; private final LocalBroadcastManager broadcastManager; private final FromNetHandler fromNetHandler = new FromNetHandler(); + public final Scheme defaultScheme; + public final Weaponset defaultWeaponset; private State state = State.NOT_CONNECTED; private String playerName; @@ -79,17 +78,17 @@ public final Roomlist roomList = new Roomlist(); public final MessageLog lobbyChatlog; public final MessageLog roomChatlog; - public final ObservableTreeMap<String, TeamInGame> roomTeamlist = new ObservableTreeMap<String, TeamInGame>(); - private final Map<String, TeamInGame> roomRequestedTeams = new TreeMap<String, TeamInGame>(); private final List<GameMessageListener> gameMessageListeners = new LinkedList<GameMessageListener>(); private final List<RunGameListener> runGameListeners = new LinkedList<RunGameListener>(); - public Netplay(Context appContext) { + public Netplay(Context appContext, Scheme defaultScheme, Weaponset defaultWeaponset) { this.appContext = appContext; broadcastManager = LocalBroadcastManager.getInstance(appContext); lobbyChatlog = new MessageLog(appContext); roomChatlog = new MessageLog(appContext); + this.defaultScheme = defaultScheme; + this.defaultWeaponset = defaultWeaponset; } public RoomStateManager getRoomStateManager() { @@ -105,21 +104,7 @@ private void initRoomState(boolean chief) { roomChatlog.clear(); roomPlayerlist.clear(); - roomTeamlist.clear(); - roomRequestedTeams.clear(); - - try { - netRoomState.setChief(chief); - netRoomState.setGameStyle(GameConfig.DEFAULT_STYLE); - List<Scheme> schemes = Schemes.loadBuiltinSchemes(appContext); - netRoomState.setScheme(schemes.get(Schemes.toNameList(schemes).indexOf(GameConfig.DEFAULT_SCHEME))); - netRoomState.setMapRecipe(MapRecipe.makeRandomMap(0, MapRecipe.makeRandomSeed(), GameConfig.DEFAULT_THEME)); - List<Weaponset> weaponsets = Weaponsets.loadBuiltinWeaponsets(appContext); - netRoomState.setWeaponset(weaponsets.get(Weaponsets.toNameList(weaponsets).indexOf(GameConfig.DEFAULT_WEAPONSET))); - netRoomState.sendFullConfig(); - } catch(IOException e) { - throw new RuntimeException(e); - } + netRoomState.initRoomState(chief); } public void registerGameMessageListener(GameMessageListener listener) { @@ -176,30 +161,10 @@ public void sendCreateRoom(String name) { sendToNet(MSG_SEND_CREATE_ROOM, name); } public void sendLeaveRoom(String message) { sendToNet(MSG_SEND_LEAVE_ROOM, message); } public void sendKick(String player) { sendToNet(MSG_SEND_KICK, player); } - public void sendAddTeam(Team newTeam, int colorIndex) { - TeamIngameAttributes tia = new TeamIngameAttributes(playerName, colorIndex, TeamIngameAttributes.DEFAULT_HOG_COUNT, false); - TeamInGame newTeamInGame = new TeamInGame(newTeam, tia); - roomRequestedTeams.put(newTeam.name, newTeamInGame); - sendToNet(MSG_SEND_ADD_TEAM, newTeamInGame); - } - public void sendRemoveTeam(String teamName) { sendToNet(MSG_SEND_REMOVE_TEAM, teamName); } - public void changeTeamColorIndex(String teamName, int colorIndex) { - if(isChief()) { - sendToNet(MSG_SEND_TEAM_COLOR_INDEX, colorIndex, teamName); - TeamInGame team = roomTeamlist.get(teamName); - roomTeamlist.put(teamName, team.withAttribs(team.ingameAttribs.withColorIndex(colorIndex))); - } - } - public void changeTeamHogCount(String teamName, int hogCount) { - if(isChief()) { - sendToNet(MSG_SEND_TEAM_HOG_COUNT, hogCount, teamName); - TeamInGame team = roomTeamlist.get(teamName); - roomTeamlist.put(teamName, team.withAttribs(team.ingameAttribs.withHogCount(hogCount))); - } - } public void sendEngineMessage(byte[] engineMessage) { sendToNet(MSG_SEND_ENGINE_MESSAGE, engineMessage); } public void sendRoundFinished(boolean withoutError) { sendToNet(MSG_SEND_ROUND_FINISHED, Boolean.valueOf(withoutError)); } public void sendToggleReady() { sendToNet(MSG_SEND_TOGGLE_READY); } + public void sendStartGame() { sendToNet(MSG_SEND_START_GAME); } public void disconnect() { sendToNet(MSG_DISCONNECT, "User Quit"); } @@ -218,7 +183,32 @@ if(Flib.INSTANCE.flib_init() != 0) { throw new RuntimeException("Unable to start frontlib"); } - instance = new Netplay(applicationContext); + + // We will need some default values for rooms, best load them here + Scheme defaultScheme = null; + Weaponset defaultWeaponset = null; + try { + List<Scheme> schemes = Schemes.loadBuiltinSchemes(applicationContext); + for(Scheme scheme : schemes) { + if(scheme.name.equals(GameConfig.DEFAULT_SCHEME)) { + defaultScheme = scheme; + } + } + List<Weaponset> weaponsets = Weaponsets.loadBuiltinWeaponsets(applicationContext); + for(Weaponset weaponset : weaponsets) { + if(weaponset.name.equals(GameConfig.DEFAULT_WEAPONSET)) { + defaultWeaponset = weaponset; + } + } + } catch(IOException e) { + throw new RuntimeException(e); + } + + if(defaultScheme==null || defaultWeaponset==null) { + throw new RuntimeException("Unable to load default scheme or weaponset"); + } + + instance = new Netplay(applicationContext, defaultScheme, defaultWeaponset); } return instance; } @@ -236,7 +226,7 @@ public boolean isChief() { if(netRoomState != null) { - return netRoomState.chief; + return netRoomState.getChiefStatus(); } else { return false; } @@ -264,7 +254,7 @@ } private MessageLog getCurrentLog() { - if(state == State.ROOM || state == State.INGAME) { + if(state == State.ROOM) { return roomChatlog; } else { return lobbyChatlog; @@ -435,22 +425,22 @@ case MSG_TEAM_ADDED: { TeamInGame newTeam = (TeamInGame)msg.obj; if(isChief()) { - int freeColor = TeamInGame.getUnusedOrRandomColorIndex(roomTeamlist.getMap().values()); + int freeColor = TeamInGame.getUnusedOrRandomColorIndex(netRoomState.getTeams().values()); sendToNet(MSG_SEND_TEAM_HOG_COUNT, newTeam.ingameAttribs.hogCount, newTeam.team.name); sendToNet(MSG_SEND_TEAM_COLOR_INDEX, freeColor, newTeam.team.name); newTeam = newTeam.withAttribs(newTeam.ingameAttribs.withColorIndex(freeColor)); } - roomTeamlist.put(newTeam.team.name, newTeam); + netRoomState.putTeam(newTeam); break; } case MSG_TEAM_DELETED: { - roomTeamlist.remove((String)msg.obj); + netRoomState.removeTeam((String)msg.obj); break; } case MSG_TEAM_ACCEPTED: { - TeamInGame requestedTeam = roomRequestedTeams.remove(msg.obj); + TeamInGame requestedTeam = netRoomState.requestedTeams.remove(msg.obj); if(requestedTeam!=null) { - roomTeamlist.put(requestedTeam.team.name, requestedTeam); + netRoomState.putTeam(requestedTeam); if(isChief()) { // Not strictly necessary, but QtFrontend does it... sendToNet(MSG_SEND_TEAM_HOG_COUNT, requestedTeam.ingameAttribs.hogCount, requestedTeam.team.name); @@ -461,7 +451,7 @@ break; } case MSG_TEAM_COLOR_CHANGED: { - TeamInGame oldEntry = roomTeamlist.get((String)msg.obj); + TeamInGame oldEntry = netRoomState.getTeams().get((String)msg.obj); if(oldEntry != null) { /* * If we are chief, we ignore colors from the outside. They only come from the server @@ -471,7 +461,7 @@ */ if(!isChief()) { TeamIngameAttributes newAttribs = oldEntry.ingameAttribs.withColorIndex(msg.arg1); - roomTeamlist.put(oldEntry.team.name, oldEntry.withAttribs(newAttribs)); + netRoomState.putTeam(oldEntry.withAttribs(newAttribs)); } } else { Log.e("Netplay", "Color update for unknown team "+msg.obj); @@ -479,10 +469,10 @@ break; } case MSG_HOG_COUNT_CHANGED: { - TeamInGame oldEntry = roomTeamlist.get((String)msg.obj); + TeamInGame oldEntry = netRoomState.getTeams().get((String)msg.obj); if(oldEntry != null) { TeamIngameAttributes newAttribs = oldEntry.ingameAttribs.withHogCount(msg.arg1); - roomTeamlist.put(oldEntry.team.name, oldEntry.withAttribs(newAttribs)); + netRoomState.putTeam(oldEntry.withAttribs(newAttribs)); } else { Log.e("Netplay", "Hog count update for unknown team "+msg.obj); } diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/ThreadedNetConnection.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/ThreadedNetConnection.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/ThreadedNetConnection.java Mon Aug 20 20:19:35 2012 +0200 @@ -110,7 +110,7 @@ } //FLIB.flib_netconn_onAdminAccess(conn, adminAccessCb, null) - FLIB.flib_netconn_onCfgScheme(conn, cfgSchemeCb, null); + FLIB.flib_netconn_onSchemeChanged(conn, cfgSchemeCb, null); FLIB.flib_netconn_onChat(conn, chatCb, null); FLIB.flib_netconn_onConnected(conn, connectedCb, null); FLIB.flib_netconn_onDisconnected(conn, disconnectCb, null); @@ -387,6 +387,7 @@ MSG_SEND_ENGINE_MESSAGE, MSG_SEND_ROUND_FINISHED, MSG_SEND_TOGGLE_READY, + MSG_SEND_START_GAME, MSG_SEND_WEAPONSET, MSG_SEND_MAP, MSG_SEND_MAP_NAME, @@ -505,6 +506,10 @@ FLIB.flib_netconn_send_toggleReady(conn); break; } + case MSG_SEND_START_GAME: { + FLIB.flib_netconn_send_startGame(conn); + break; + } case MSG_SEND_WEAPONSET: { FLIB.flib_netconn_send_weaponset(conn, WeaponsetPtr.createJavaOwned((Weaponset)msg.obj)); break; diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/ObjectUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/ObjectUtils.java Mon Aug 20 20:19:35 2012 +0200 @@ -0,0 +1,13 @@ +package org.hedgewars.hedgeroid.util; + +public final class ObjectUtils { + public static boolean equal(Object o1, Object o2) { + if(o1==o2) { + return true; + } else if(o1==null || o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } +} diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/TextInputDialog.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/TextInputDialog.java Mon Aug 20 20:16:37 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/TextInputDialog.java Mon Aug 20 20:19:35 2012 +0200 @@ -98,6 +98,7 @@ editText.setOnEditorActionListener(new OnEditorActionListener() { public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { listener.onTextInputDialogSubmitted(dialogId, v.getText().toString()); + dismiss(); return true; } }); diff -r c92596feac0d -r 714310efad8f project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/UiUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/UiUtils.java Mon Aug 20 20:19:35 2012 +0200 @@ -0,0 +1,34 @@ +package org.hedgewars.hedgeroid.util; + +import org.hedgewars.hedgeroid.R; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.TabHost; +import android.widget.TextView; + +public final class UiUtils { + private UiUtils() { + throw new AssertionError("This class is not meant to be instantiated"); + } + + public static View createTabIndicator(TabHost tabHost, int label, int icon) { + LayoutInflater inflater = (LayoutInflater) tabHost.getContext() + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + + View view = inflater.inflate(R.layout.tab_indicator_vertical, + tabHost.getTabWidget(), false); + + final TextView tv = (TextView) view.findViewById(R.id.title); + tv.setText(label); + + if (icon != 0) { + ImageView iconView = (ImageView) view.findViewById(R.id.icon); + iconView.setImageResource(icon); + } + + return view; + } +}