--- a/project_files/Android-build/SDL-android-project/AndroidManifest.xml Thu Aug 02 16:35:12 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/AndroidManifest.xml Thu Aug 02 16:36:11 2012 +0200
@@ -72,5 +72,11 @@
android:screenOrientation="landscape"
android:windowSoftInputMode="adjustPan" >
</activity>
+ <activity
+ android:name=".netplay.RoomActivity"
+ android:label="@string/title_activity_room"
+ android:screenOrientation="landscape"
+ android:windowSoftInputMode="adjustPan" >
+ </activity>
</application>
</manifest>
\ No newline at end of file
--- a/project_files/Android-build/SDL-android-project/res/layout/activity_netroom.xml Thu Aug 02 16:35:12 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/res/layout/activity_netroom.xml Thu Aug 02 16:36:11 2012 +0200
@@ -30,10 +30,10 @@
android:layout_marginRight="10dp"
android:background="@drawable/box" >
- <fragment
+ <!-- <fragment
android:id="@+id/mapFragment"
class="org.hedgewars.hedgeroid.netplay.MapFragment"
- tools:layout="@layout/fragment_map" />
+ tools:layout="@layout/fragment_map" /> -->
</FrameLayout>
<FrameLayout
@@ -44,10 +44,10 @@
android:layout_weight="1"
android:background="@drawable/box" >
- <fragment
+ <!-- <fragment
android:id="@+id/settingsFragment"
class="org.hedgewars.hedgeroid.netplay.SettingsFragment"
- tools:layout="@layout/fragment_settings" />
+ tools:layout="@layout/fragment_settings" /> -->
</FrameLayout>
<FrameLayout
@@ -57,10 +57,10 @@
android:layout_weight="1"
android:background="@drawable/box" >
- <fragment
+ <!-- <fragment
android:id="@+id/teamsFragment"
class="org.hedgewars.hedgeroid.netplay.TeamsFragment"
- tools:layout="@layout/fragment_teamlist" />
+ tools:layout="@layout/fragment_teamlist" /> -->
</FrameLayout>
</LinearLayout>
@@ -74,12 +74,12 @@
android:layout_below="@id/upperFrame"
android:background="@drawable/box" >
- <fragment
+ <!-- <fragment
android:id="@+id/playerListFragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
class="org.hedgewars.hedgeroid.netplay.PlayerlistFragment"
- tools:layout="@layout/lobby_players_fragment" />
+ tools:layout="@layout/lobby_players_fragment" /> -->
</FrameLayout>
<FrameLayout
--- a/project_files/Android-build/SDL-android-project/res/values/strings.xml Thu Aug 02 16:35:12 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/res/values/strings.xml Thu Aug 02 16:36:11 2012 +0200
@@ -62,6 +62,8 @@
<string name="bot1">Level 1</string>
<string name="title_activity_lobby">Hedgewars Server Lobby</string>
+ <string name="title_activity_room">Room</string>
+
<string name="chat_hint">Type here to chat</string>
<!-- Map settings -->
@@ -118,7 +120,7 @@
<string name="error_unexpected">An unexpected error has occurred: %1$s</string>
<string name="error_server_too_old">The server you tried to connect to is using an incompatible protocol.</string>
<string name="error_auth_failed">Unable to authenticate for your username.</string>
- <string name="error_connection_lost">The connection to the server was lost: %1$s</string>
+ <string name="error_connection_lost">The connection to the server was lost.</string>
<!-- Dialogs -->
<string name="dialog_connecting_title">Please wait</string>
@@ -127,4 +129,10 @@
<string name="dialog_password_message">The server has requested a password to connect as "%1$s".</string>
<string name="dialog_password_hint">Password</string>
<string name="dialog_password_remember">remember password</string>
+ <string name="dialog_create_room_hint">Room name</string>
+ <string name="dialog_create_room_title">Create new room</string>
+
+ <string name="toast_disconnected">Disconnected: %1$s</string>
+ <string name="toast_room_abandoned">The room was closed because the owner left.</string>
+ <string name="toast_kicked">You were kicked from the room.</string>
</resources>
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/LobbyActivity.java Thu Aug 02 16:35:12 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/LobbyActivity.java Thu Aug 02 16:36:11 2012 +0200
@@ -1,8 +1,13 @@
package org.hedgewars.hedgeroid.netplay;
import org.hedgewars.hedgeroid.R;
+import org.hedgewars.hedgeroid.StartGameActivity;
+import org.hedgewars.hedgeroid.netplay.Netplay.State;
+import org.hedgewars.hedgeroid.netplay.NetplayStateFragment.NetplayStateListener;
+import org.hedgewars.hedgeroid.netplay.TextInputDialog.TextInputDialogListener;
import android.content.Context;
+import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
@@ -15,9 +20,10 @@
import android.widget.LinearLayout;
import android.widget.TabHost;
import android.widget.TextView;
-import android.widget.Toast;
-public class LobbyActivity extends FragmentActivity {
+public class LobbyActivity extends FragmentActivity implements TextInputDialogListener, NetplayStateListener {
+ private static final int DIALOG_CREATE_ROOM = 0;
+
private TabHost tabHost;
private Netplay netplay;
@@ -79,7 +85,8 @@
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.room_create:
- Toast.makeText(this, R.string.not_implemented_yet, Toast.LENGTH_SHORT).show();
+ TextInputDialog dialog = new TextInputDialog(DIALOG_CREATE_ROOM, R.string.dialog_create_room_title, 0, R.string.dialog_create_room_hint);
+ dialog.show(getSupportFragmentManager(), "create_room_dialog");
return true;
case R.id.disconnect:
netplay.disconnect();
@@ -102,4 +109,31 @@
icicle.putString("currentTab", tabHost.getCurrentTabTag());
}
}
+
+ public void onTextInputDialogSubmitted(int dialogId, String text) {
+ if(text != null && text.length()>0) {
+ netplay.sendCreateRoom(text);
+ }
+ }
+
+ public void onTextInputDialogCancelled(int dialogId) {
+ }
+
+ public void onNetplayStateChanged(State newState) {
+ switch(newState) {
+ case CONNECTING:
+ case NOT_CONNECTED:
+ finish();
+ break;
+ case ROOM:
+ case INGAME:
+ startActivity(new Intent(getApplicationContext(), RoomActivity.class));
+ break;
+ case LOBBY:
+ // Do nothing
+ break;
+ default:
+ throw new IllegalStateException("Unknown connection state: "+newState);
+ }
+ }
}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Netplay.java Thu Aug 02 16:35:12 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Netplay.java Thu Aug 02 16:36:11 2012 +0200
@@ -5,6 +5,7 @@
import org.hedgewars.hedgeroid.R;
import org.hedgewars.hedgeroid.Utils;
+import org.hedgewars.hedgeroid.netplay.JnaFrontlib.BoolCallback;
import org.hedgewars.hedgeroid.netplay.JnaFrontlib.IntStrCallback;
import org.hedgewars.hedgeroid.netplay.JnaFrontlib.MetaschemePtr;
import org.hedgewars.hedgeroid.netplay.JnaFrontlib.NetconnPtr;
@@ -40,11 +41,15 @@
public static final String EXTRA_PLAYERNAME = "playerName";
public static final String EXTRA_MESSAGE = "message";
public static final String EXTRA_HAS_ERROR = "hasError";
+ public static final String EXTRA_REASON = "reason";
private static final String ACTIONPREFIX = "org.hedgewars.hedgeroid.netconn.";
public static final String ACTION_DISCONNECTED = ACTIONPREFIX+"DISCONNECTED";
public static final String ACTION_CONNECTED = ACTIONPREFIX+"CONNECTED";
public static final String ACTION_PASSWORD_REQUESTED = ACTIONPREFIX+"PASSWORD_REQUESTED";
+ public static final String ACTION_ENTERED_ROOM_FROM_LOBBY = ACTIONPREFIX+"ENTERED_ROOM";
+ public static final String ACTION_LEFT_ROOM = ACTIONPREFIX+"LEFT_ROOM";
+ public static final String ACTION_STATE_CHANGED = ACTIONPREFIX+"STATE_CHANGED";
public static final String DEFAULT_SERVER = "netserver.hedgewars.org";
public static final int DEFAULT_PORT = 46631;
@@ -54,13 +59,14 @@
private final FromNetHandler fromNetHandler = new FromNetHandler();
private State state;
- private int foregroundUsers = 0;
+ private int foregroundUsers = 0; // Reference counter of clients requesting foreground tick speed (fast ticks)
+ private boolean chief; // Do we control the current room?
// null if there is no running connection (==state is NOT_CONNECTED)
private ThreadedNetConnection connection;
- public final PlayerList playerList = new PlayerList();
- public final RoomList roomList = new RoomList();
+ public final Playerlist playerList = new Playerlist();
+ public final Roomlist roomList = new Roomlist();
public final MessageLog lobbyChatlog;
public final MessageLog roomChatlog;
@@ -96,7 +102,7 @@
}
clearState();
- state = State.CONNECTING;
+ changeState(State.CONNECTING);
connection = ThreadedNetConnection.startConnection(appContext, fromNetHandler, name, host, port);
connection.setFastTickRate(foregroundUsers > 0);
}
@@ -106,7 +112,12 @@
public void sendQuit(String message) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_QUIT, message); }
public void sendRoomlistRequest() { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_ROOMLIST_REQUEST); }
public void sendPlayerInfoQuery(String name) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_PLAYER_INFO_REQUEST, name); }
- public void sendChat(final String s) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_CHAT, s); }
+ public void sendChat(String s) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_CHAT, s); }
+ public void sendFollowPlayer(String nick) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_FOLLOW_PLAYER, nick); }
+ public void sendJoinRoom(String name) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_JOIN_ROOM, name); }
+ public void sendCreateRoom(String name) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_CREATE_ROOM, name); }
+ public void sendLeaveRoom(String message) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_LEAVE_ROOM, message); }
+
public void disconnect() { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_DISCONNECT, "User Quit"); }
private static Netplay instance;
@@ -133,6 +144,17 @@
return state;
}
+ private void changeState(State newState) {
+ if(newState != state) {
+ state = newState;
+ broadcastManager.sendBroadcastSync(new Intent(ACTION_STATE_CHANGED));
+ }
+ }
+
+ public boolean isChief() {
+ return chief;
+ }
+
/**
* Indicate that you want network messages to be checked regularly (several times per second).
* As long as nobody requests fast ticks, the network is only checked once every few seconds
@@ -191,15 +213,19 @@
final class FromNetHandler extends Handler {
public static final int MSG_LOBBY_JOIN = 0;
public static final int MSG_LOBBY_LEAVE = 1;
- public static final int MSG_CHAT = 2;
- public static final int MSG_MESSAGE = 3;
- public static final int MSG_ROOM_ADD = 4;
- public static final int MSG_ROOM_UPDATE = 5;
- public static final int MSG_ROOM_DELETE = 6;
- public static final int MSG_ROOMLIST = 7;
- public static final int MSG_CONNECTED = 8;
- public static final int MSG_DISCONNECTED = 9;
- public static final int MSG_PASSWORD_REQUEST = 10;
+ public static final int MSG_ROOM_JOIN = 2;
+ public static final int MSG_ROOM_LEAVE = 3;
+ public static final int MSG_CHAT = 4;
+ public static final int MSG_MESSAGE = 5;
+ public static final int MSG_ROOM_ADD = 6;
+ public static final int MSG_ROOM_UPDATE = 7;
+ public static final int MSG_ROOM_DELETE = 8;
+ public static final int MSG_ROOMLIST = 9;
+ public static final int MSG_CONNECTED = 10;
+ public static final int MSG_DISCONNECTED = 11;
+ public static final int MSG_PASSWORD_REQUEST = 12;
+ public static final int MSG_ENTER_ROOM_FROM_LOBBY = 13;
+ public static final int MSG_LEAVE_ROOM = 14;
public FromNetHandler() {
super(Looper.getMainLooper());
@@ -221,6 +247,18 @@
lobbyChatlog.appendPlayerLeave(args.first, args.second);
break;
}
+ case MSG_ROOM_JOIN: {
+ String name = (String)msg.obj;
+ // TODO roomPlayerList.addPlayerWithNewId(name);
+ roomChatlog.appendPlayerJoin(name);
+ break;
+ }
+ case MSG_ROOM_LEAVE: {
+ Pair<String, String> args = (Pair<String, String>)msg.obj;
+ // TODO roomPlayerList.removePlayer(args.first);
+ roomChatlog.appendPlayerLeave(args.first, args.second);
+ break;
+ }
case MSG_CHAT: {
Pair<String, String> args = (Pair<String, String>)msg.obj;
getCurrentLog().appendChat(args.first, args.second);
@@ -248,13 +286,13 @@
break;
}
case MSG_CONNECTED: {
- state = State.LOBBY;
+ changeState(State.LOBBY);
broadcastManager.sendBroadcast(new Intent(ACTION_CONNECTED));
break;
}
case MSG_DISCONNECTED: {
Pair<Boolean, String> args = (Pair<Boolean, String>)msg.obj;
- state = State.NOT_CONNECTED;
+ changeState(State.NOT_CONNECTED);
connection = null;
Intent intent = new Intent(ACTION_DISCONNECTED);
intent.putExtra(EXTRA_HAS_ERROR, args.first);
@@ -268,6 +306,22 @@
broadcastManager.sendBroadcast(intent);
break;
}
+ case MSG_ENTER_ROOM_FROM_LOBBY: {
+ roomChatlog.clear();
+ changeState(State.ROOM);
+ chief = (Boolean)msg.obj;
+ Intent intent = new Intent(ACTION_ENTERED_ROOM_FROM_LOBBY);
+ broadcastManager.sendBroadcastSync(intent);
+ break;
+ }
+ case MSG_LEAVE_ROOM: {
+ changeState(State.LOBBY);
+ Intent intent = new Intent(ACTION_LEFT_ROOM);
+ intent.putExtra(EXTRA_MESSAGE, (String)msg.obj);
+ intent.putExtra(EXTRA_REASON, msg.arg1);
+ broadcastManager.sendBroadcastSync(intent);
+ break;
+ }
default: {
Log.e("FromNetHandler", "Unknown message type: "+msg.what);
break;
@@ -332,6 +386,8 @@
}
FLIB.flib_netconn_onLobbyJoin(conn, lobbyJoinCb, null);
FLIB.flib_netconn_onLobbyLeave(conn, lobbyLeaveCb, null);
+ FLIB.flib_netconn_onRoomJoin(conn, roomJoinCb, null);
+ FLIB.flib_netconn_onRoomLeave(conn, roomLeaveCb, null);
FLIB.flib_netconn_onChat(conn, chatCb, null);
FLIB.flib_netconn_onMessage(conn, messageCb, null);
FLIB.flib_netconn_onRoomAdd(conn, roomAddCb, null);
@@ -341,6 +397,9 @@
FLIB.flib_netconn_onRoomlist(conn, roomlistCb, null);
FLIB.flib_netconn_onDisconnected(conn, disconnectCb, null);
FLIB.flib_netconn_onPasswordRequest(conn, passwordRequestCb, null);
+ FLIB.flib_netconn_onEnterRoom(conn, enterRoomCb, null);
+ FLIB.flib_netconn_onLeaveRoom(conn, leaveRoomCb, null);
+
FLIB.flib_metascheme_release(meta);
tickHandler.start();
}
@@ -375,6 +434,16 @@
}
};
+ private final StrCallback roomJoinCb = new StrCallback() {
+ public void callback(Pointer context, String name) {
+ sendFromNet(FromNetHandler.MSG_ROOM_JOIN, name);
+ }
+ };
+ private final StrStrCallback roomLeaveCb = new StrStrCallback() {
+ public void callback(Pointer context, String name, String message) {
+ sendFromNet(FromNetHandler.MSG_ROOM_LEAVE, Pair.create(name, message));
+ }
+ };
private final StrStrCallback chatCb = new StrStrCallback() {
public void callback(Pointer context, String name, String msg) {
sendFromNet(FromNetHandler.MSG_CHAT, Pair.create(name, msg));
@@ -425,6 +494,18 @@
}
};
+ private final BoolCallback enterRoomCb = new BoolCallback() {
+ public void callback(Pointer context, boolean isChief) {
+ sendFromNet(FromNetHandler.MSG_ENTER_ROOM_FROM_LOBBY, Boolean.TRUE);
+ }
+ };
+
+ private final IntStrCallback leaveRoomCb = new IntStrCallback() {
+ public void callback(Pointer context, int reason, String message) {
+ sendFromNet(FromNetHandler.MSG_LEAVE_ROOM, reason, message);
+ }
+ };
+
private void shutdown(boolean error, String message) {
if(conn != null) {
FLIB.flib_netconn_destroy(conn);
@@ -448,7 +529,7 @@
case JnaFrontlib.NETCONN_DISCONNECT_AUTH_FAILED:
return res.getString(R.string.error_auth_failed);
case JnaFrontlib.NETCONN_DISCONNECT_CONNLOST:
- return res.getString(R.string.error_connection_lost, message);
+ return res.getString(R.string.error_connection_lost);
case JnaFrontlib.NETCONN_DISCONNECT_INTERNAL_ERROR:
return res.getString(R.string.error_unexpected, message);
case JnaFrontlib.NETCONN_DISCONNECT_SERVER_TOO_OLD:
@@ -476,7 +557,12 @@
public static final int MSG_SEND_ROOMLIST_REQUEST = 3;
public static final int MSG_SEND_PLAYER_INFO_REQUEST = 4;
public static final int MSG_SEND_CHAT = 5;
- public static final int MSG_DISCONNECT = 6;
+ public static final int MSG_SEND_FOLLOW_PLAYER = 6;
+ public static final int MSG_SEND_JOIN_ROOM = 7;
+ public static final int MSG_SEND_CREATE_ROOM = 8;
+ public static final int MSG_SEND_LEAVE_ROOM = 9;
+
+ public static final int MSG_DISCONNECT = 10;
public ToNetHandler(Looper looper) {
super(looper);
@@ -511,6 +597,24 @@
}
break;
}
+ case MSG_SEND_FOLLOW_PLAYER: {
+ FLIB.flib_netconn_send_playerFollow(conn, (String)msg.obj);
+ break;
+ }
+ case MSG_SEND_JOIN_ROOM: {
+ FLIB.flib_netconn_send_joinRoom(conn, (String)msg.obj);
+ break;
+ }
+ case MSG_SEND_CREATE_ROOM: {
+ FLIB.flib_netconn_send_createRoom(conn, (String)msg.obj);
+ break;
+ }
+ case MSG_SEND_LEAVE_ROOM: {
+ if(FLIB.flib_netconn_send_leaveRoom(conn, (String)msg.obj) == 0) {
+ sendFromNet(FromNetHandler.MSG_LEAVE_ROOM, -1, "");
+ }
+ break;
+ }
case MSG_DISCONNECT: {
FLIB.flib_netconn_send_quit(conn, (String)msg.obj);
shutdown(false, "User quit");
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/NetplayStateFragment.java Thu Aug 02 16:35:12 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/NetplayStateFragment.java Thu Aug 02 16:36:11 2012 +0200
@@ -1,7 +1,9 @@
package org.hedgewars.hedgeroid.netplay;
+import org.hedgewars.hedgeroid.R;
import org.hedgewars.hedgeroid.netplay.Netplay.State;
+import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -13,30 +15,45 @@
/**
* Fragment for use by an activity that depends on the state of the network
- * connection.
+ * connection. The activity must implement the NetplayStateListener interface.
*
* This fragment manages a few aspects of the netplay connection: Requesting
* the network system loop to run at high frequency while the activity is in
- * the foreground, and reacting to changes in the networking state by switching
- * to the appropriate activity or finishing the activity if the network connection
- * is closed.
+ * the foreground, and reacting to changes in the networking state by calling
+ * a callback method on the activity.
*/
public class NetplayStateFragment extends Fragment {
private Netplay netplay;
private Context appContext;
private LocalBroadcastManager broadcastManager;
+ private NetplayStateListener listener;
+ private State knownState;
- private final BroadcastReceiver disconnectReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if(intent.getBooleanExtra(Netplay.EXTRA_HAS_ERROR, true)) {
- String message = intent.getStringExtra(Netplay.EXTRA_MESSAGE);
- Toast.makeText(appContext, "Disconnected: "+message, Toast.LENGTH_LONG).show();
- }
- getActivity().finish();
+ interface NetplayStateListener {
+ /**
+ * This is called while the activity is running, and every time during resume, if
+ * a change in the networking state is detected. It is also called once
+ * with the initial state (which could be called a change from the "unknown" state).
+ */
+ void onNetplayStateChanged(State newState);
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ try {
+ listener = (NetplayStateListener) activity;
+ } catch(ClassCastException e) {
+ throw new ClassCastException("Activity " + activity + " must implement NetplayStateListener to use NetplayStateFragment.");
}
- };
-
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ listener = null;
+ }
+
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -49,10 +66,14 @@
public void onResume() {
super.onResume();
broadcastManager.registerReceiver(disconnectReceiver, new IntentFilter(Netplay.ACTION_DISCONNECTED));
+ broadcastManager.registerReceiver(leaveRoomReceiver, new IntentFilter(Netplay.ACTION_LEFT_ROOM));
+ broadcastManager.registerReceiver(stateChangeReceiver, new IntentFilter(Netplay.ACTION_STATE_CHANGED));
netplay.requestFastTicks();
- if(netplay.getState() == State.NOT_CONNECTED) {
- getActivity().finish();
+ State newState = netplay.getState();
+ if(knownState != newState) {
+ listener.onNetplayStateChanged(newState);
+ knownState = newState;
}
}
@@ -60,6 +81,40 @@
public void onPause() {
super.onPause();
broadcastManager.unregisterReceiver(disconnectReceiver);
+ broadcastManager.unregisterReceiver(leaveRoomReceiver);
+ broadcastManager.unregisterReceiver(stateChangeReceiver);
netplay.unrequestFastTicks();
}
+
+ private final BroadcastReceiver disconnectReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if(intent.getBooleanExtra(Netplay.EXTRA_HAS_ERROR, true)) {
+ String message = intent.getStringExtra(Netplay.EXTRA_MESSAGE);
+ String toastText = getString(R.string.toast_disconnected, message);
+ Toast.makeText(appContext, toastText, Toast.LENGTH_LONG).show();
+ }
+ }
+ };
+
+ private final BroadcastReceiver leaveRoomReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int reason = intent.getIntExtra(Netplay.EXTRA_REASON, -1);
+ if(reason == JnaFrontlib.NETCONN_ROOMLEAVE_ABANDONED) {
+ Toast.makeText(appContext, R.string.toast_room_abandoned, Toast.LENGTH_LONG).show();
+ } else if(reason == JnaFrontlib.NETCONN_ROOMLEAVE_KICKED) {
+ Toast.makeText(appContext, R.string.toast_kicked, Toast.LENGTH_LONG).show();
+ }
+ }
+ };
+
+ private final BroadcastReceiver stateChangeReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ State newState = netplay.getState();
+ listener.onNetplayStateChanged(newState);
+ knownState = newState;
+ }
+ };
}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Player.java Thu Aug 02 16:35:12 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Player.java Thu Aug 02 16:36:11 2012 +0200
@@ -6,4 +6,4 @@
public Player(String name) {
this.name = name;
}
-}
\ No newline at end of file
+}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerList.java Thu Aug 02 16:35:12 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerList.java Thu Aug 02 16:36:11 2012 +0200
@@ -7,7 +7,7 @@
import android.database.DataSetObservable;
import android.util.Pair;
-public class PlayerList extends DataSetObservable {
+public class Playerlist extends DataSetObservable {
private long nextId = 1;
private Map<String, Pair<Player, Long>> players = new TreeMap<String, Pair<Player, Long>>();
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerListAdapter.java Thu Aug 02 16:35:12 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerListAdapter.java Thu Aug 02 16:36:11 2012 +0200
@@ -16,15 +16,15 @@
import android.widget.BaseAdapter;
import android.widget.TextView;
-public class PlayerListAdapter extends BaseAdapter {
+public class PlayerlistAdapter extends BaseAdapter {
private List<Pair<Player, Long>> players = new ArrayList<Pair<Player, Long>>();
private Context context;
- private PlayerList playerList;
+ private Playerlist playerlist;
private DataSetObserver observer = new DataSetObserver() {
@Override
public void onChanged() {
- reloadFromList(playerList);
+ reloadFromList(playerlist);
}
@Override
@@ -33,7 +33,7 @@
}
};
- public PlayerListAdapter(Context context) {
+ public PlayerlistAdapter(Context context) {
this.context = context;
}
@@ -53,24 +53,24 @@
return true;
}
- public void setList(PlayerList playerList) {
- if(this.playerList != null) {
- this.playerList.unregisterObserver(observer);
+ public void setList(Playerlist playerlist) {
+ if(this.playerlist != null) {
+ this.playerlist.unregisterObserver(observer);
}
- this.playerList = playerList;
- this.playerList.registerObserver(observer);
- reloadFromList(playerList);
+ this.playerlist = playerlist;
+ this.playerlist.registerObserver(observer);
+ reloadFromList(playerlist);
}
public void invalidate() {
- if(playerList != null) {
- playerList.unregisterObserver(observer);
+ if(playerlist != null) {
+ playerlist.unregisterObserver(observer);
}
- playerList = null;
+ playerlist = null;
notifyDataSetInvalidated();
}
- private void reloadFromList(PlayerList list) {
+ private void reloadFromList(Playerlist list) {
players = new ArrayList<Pair<Player, Long>>(list.getMap().values());
Collections.sort(players, AlphabeticalOrderComparator.INSTANCE);
notifyDataSetChanged();
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerlistFragment.java Thu Aug 02 16:35:12 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerlistFragment.java Thu Aug 02 16:36:11 2012 +0200
@@ -12,17 +12,16 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView.AdapterContextMenuInfo;
-import android.widget.Toast;
public class PlayerlistFragment extends ListFragment {
private Netplay netconn;
- private PlayerListAdapter playerListAdapter;
+ private PlayerlistAdapter playerListAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
netconn = Netplay.getAppInstance(getActivity().getApplicationContext());
- playerListAdapter = new PlayerListAdapter(getActivity());
+ playerListAdapter = new PlayerlistAdapter(getActivity());
playerListAdapter.setList(Netplay.getAppInstance(getActivity().getApplicationContext()).playerList);
setListAdapter(playerListAdapter);
}
@@ -53,13 +52,13 @@
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo)item.getMenuInfo();
+ Player player = playerListAdapter.getItem(info.position);
switch(item.getItemId()) {
case R.id.player_info:
- Player p = playerListAdapter.getItem(info.position);
- netconn.sendPlayerInfoQuery(p.name);
+ netconn.sendPlayerInfoQuery(player.name);
return true;
case R.id.player_follow:
- Toast.makeText(getActivity(), R.string.not_implemented_yet, Toast.LENGTH_SHORT).show();
+ netconn.sendFollowPlayer(player.name);
return true;
default:
return super.onContextItemSelected(item);
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomActivity.java Thu Aug 02 16:35:12 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomActivity.java Thu Aug 02 16:36:11 2012 +0200
@@ -2,29 +2,38 @@
import org.hedgewars.hedgeroid.R;
import org.hedgewars.hedgeroid.netplay.JnaFrontlib.NetconnPtr;
+import org.hedgewars.hedgeroid.netplay.Netplay.State;
+import org.hedgewars.hedgeroid.netplay.NetplayStateFragment.NetplayStateListener;
+import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.LocalBroadcastManager;
import android.widget.LinearLayout;
import android.widget.TabHost;
+import android.widget.Toast;
-public class RoomActivity extends FragmentActivity {
+public class RoomActivity extends FragmentActivity implements NetplayStateListener {
private TabHost tabHost;
- private Netplay netconn;
+ private Netplay netplay;
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
- netconn = Netplay.getAppInstance(getApplicationContext());
+ netplay = Netplay.getAppInstance(getApplicationContext());
+
+ setContentView(R.layout.activity_netroom);
+ ChatFragment chatFragment = (ChatFragment)getSupportFragmentManager().findFragmentById(R.id.chatFragment);
+ chatFragment.setInRoom(true);
- setContentView(R.layout.activity_lobby);
- Fragment chatFragment = getSupportFragmentManager().findFragmentById(R.id.chatFragment);
- chatFragment.getArguments().putBoolean(ChatFragment.ARGUMENT_INROOM, true);
+ FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
+ trans.add(new NetplayStateFragment(), "netplayFragment");
+ trans.commit();
- tabHost = (TabHost)findViewById(android.R.id.tabhost);
+ /*tabHost = (TabHost)findViewById(android.R.id.tabhost);
if(tabHost != null) {
tabHost.setup();
tabHost.getTabWidget().setOrientation(LinearLayout.VERTICAL);
@@ -35,9 +44,14 @@
if (icicle != null) {
tabHost.setCurrentTabByTag(icicle.getString("currentTab"));
}
- }
+ }*/
}
+ @Override
+ public void onBackPressed() {
+ netplay.sendLeaveRoom(null);
+ }
+
@Override
protected void onSaveInstanceState(Bundle icicle) {
super.onSaveInstanceState(icicle);
@@ -45,4 +59,23 @@
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);
+ }
+ }
}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomList.java Thu Aug 02 16:35:12 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomList.java Thu Aug 02 16:36:11 2012 +0200
@@ -8,7 +8,7 @@
import android.util.Log;
import android.util.Pair;
-public class RoomList extends DataSetObservable {
+public class Roomlist extends DataSetObservable {
private long nextId = 1;
private Map<String, Pair<Room, Long>> rooms = new TreeMap<String, Pair<Room, Long>>();
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomListAdapter.java Thu Aug 02 16:35:12 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomListAdapter.java Thu Aug 02 16:36:11 2012 +0200
@@ -17,15 +17,15 @@
import android.widget.BaseAdapter;
import android.widget.TextView;
-public class RoomListAdapter extends BaseAdapter {
+public class RoomlistAdapter extends BaseAdapter {
private List<Pair<Room, Long>> rooms = new ArrayList<Pair<Room, Long>>();
private Context context;
- private RoomList roomList;
+ private Roomlist roomlist;
private DataSetObserver observer = new DataSetObserver() {
@Override
public void onChanged() {
- reloadFromList(roomList);
+ reloadFromList(roomlist);
}
@Override
@@ -34,7 +34,7 @@
}
};
- public RoomListAdapter(Context context) {
+ public RoomlistAdapter(Context context) {
this.context = context;
}
@@ -54,25 +54,25 @@
return true;
}
- public void setList(RoomList roomList) {
- if(this.roomList != null) {
- this.roomList.unregisterObserver(observer);
+ public void setList(Roomlist roomlist) {
+ if(this.roomlist != null) {
+ this.roomlist.unregisterObserver(observer);
}
- this.roomList = roomList;
- this.roomList.registerObserver(observer);
- reloadFromList(roomList);
+ this.roomlist = roomlist;
+ this.roomlist.registerObserver(observer);
+ reloadFromList(roomlist);
}
public void invalidate() {
- if(roomList != null) {
- roomList.unregisterObserver(observer);
+ if(roomlist != null) {
+ roomlist.unregisterObserver(observer);
}
- roomList = null;
+ roomlist = null;
notifyDataSetInvalidated();
}
- private void reloadFromList(RoomList list) {
- rooms = new ArrayList<Pair<Room, Long>>(roomList.getMap().values());
+ private void reloadFromList(Roomlist list) {
+ rooms = new ArrayList<Pair<Room, Long>>(roomlist.getMap().values());
Collections.sort(rooms, RoomAgeComparator.INSTANCE);
notifyDataSetChanged();
}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomlistFragment.java Thu Aug 02 16:35:12 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomlistFragment.java Thu Aug 02 16:36:11 2012 +0200
@@ -10,17 +10,16 @@
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
-import android.widget.Toast;
public class RoomlistFragment extends ListFragment implements OnItemClickListener {
private static final int AUTO_REFRESH_INTERVAL_MS = 15000;
- private Netplay netconn;
- private RoomListAdapter adapter;
+ private Netplay netplay;
+ private RoomlistAdapter adapter;
private CountDownTimer autoRefreshTimer = new CountDownTimer(Long.MAX_VALUE, AUTO_REFRESH_INTERVAL_MS) {
@Override
public void onTick(long millisUntilFinished) {
- netconn.sendRoomlistRequest();
+ netplay.sendRoomlistRequest();
}
@Override
@@ -30,9 +29,9 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- netconn = Netplay.getAppInstance(getActivity().getApplicationContext());
- adapter = new RoomListAdapter(getActivity());
- adapter.setList(netconn.roomList);
+ netplay = Netplay.getAppInstance(getActivity().getApplicationContext());
+ adapter = new RoomlistAdapter(getActivity());
+ adapter.setList(netplay.roomList);
setListAdapter(adapter);
}
@@ -67,6 +66,6 @@
}
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- Toast.makeText(getActivity(), R.string.not_implemented_yet, Toast.LENGTH_SHORT).show();
+ netplay.sendJoinRoom(adapter.getItem(position).name);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/TextInputDialog.java Thu Aug 02 16:36:11 2012 +0200
@@ -0,0 +1,128 @@
+package org.hedgewars.hedgeroid.netplay;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.v4.app.DialogFragment;
+import android.view.KeyEvent;
+import android.view.inputmethod.EditorInfo;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+
+/**
+ * A generic text input dialog with configurable text. The Activity must implement the callback
+ * interface TextInputDialogListener, which will be called by the dialog if it is submitted or cancelled.
+ */
+public class TextInputDialog extends DialogFragment {
+ private static final String BUNDLE_DIALOG_ID = "dialogId";
+ private static final String BUNDLE_TITLE_TEXT = "title";
+ private static final String BUNDLE_MESSAGE_TEXT = "message";
+ private static final String BUNDLE_HINT_TEXT = "hint";
+
+ private int dialogId, titleText, messageText, hintText;
+ private TextInputDialogListener listener;
+
+ public interface TextInputDialogListener {
+ void onTextInputDialogSubmitted(int dialogId, String text);
+ void onTextInputDialogCancelled(int dialogId);
+ }
+
+ /**
+ * The dialogId is only used for passing back to the callback on the activity, the
+ * other parameters are text resource IDs. Pass 0 for any of them to not use this
+ * text.
+ */
+ public TextInputDialog(int dialogId, int titleText, int messageText, int hintText) {
+ this.dialogId = dialogId;
+ this.titleText = titleText;
+ this.messageText = messageText;
+ this.hintText = hintText;
+ }
+
+ public TextInputDialog() {
+ // Only for reflection-based instantiation by the framework
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ try {
+ listener = (TextInputDialogListener) activity;
+ } catch(ClassCastException e) {
+ throw new ClassCastException("Activity " + activity + " must implement TextInputDialogListener to use TextInputDialog.");
+ }
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ listener = null;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ if(savedInstanceState != null) {
+ dialogId = savedInstanceState.getInt(BUNDLE_DIALOG_ID, dialogId);
+ titleText = savedInstanceState.getInt(BUNDLE_TITLE_TEXT, titleText);
+ messageText = savedInstanceState.getInt(BUNDLE_MESSAGE_TEXT, messageText);
+ hintText = savedInstanceState.getInt(BUNDLE_HINT_TEXT, hintText);
+ }
+
+ final EditText editText = new EditText(getActivity());
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+
+ if(titleText != 0) {
+ builder.setTitle(titleText);
+ }
+ if(messageText != 0) {
+ builder.setTitle(messageText);
+ }
+ if(hintText != 0) {
+ editText.setHint(hintText);
+ }
+
+ editText.setId(android.R.id.text1);
+ editText.setImeOptions(EditorInfo.IME_ACTION_DONE);
+ editText.setSingleLine();
+
+ builder.setView(editText);
+ builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.cancel();
+ }
+ });
+
+ editText.setOnEditorActionListener(new OnEditorActionListener() {
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ listener.onTextInputDialogSubmitted(dialogId, v.getText().toString());
+ return true;
+ }
+ });
+
+ builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ listener.onTextInputDialogSubmitted(dialogId, editText.getText().toString());
+ }
+ });
+
+ return builder.create();
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle icicle) {
+ super.onSaveInstanceState(icicle);
+ icicle.putInt(BUNDLE_DIALOG_ID, dialogId);
+ icicle.putInt(BUNDLE_TITLE_TEXT, titleText);
+ icicle.putInt(BUNDLE_MESSAGE_TEXT, messageText);
+ icicle.putInt(BUNDLE_HINT_TEXT, hintText);
+ }
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ super.onCancel(dialog);
+ listener.onTextInputDialogCancelled(dialogId);
+ }
+}