--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Netplay.java Sat Aug 18 00:22:33 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Netplay.java Sat Aug 18 00:47:51 2012 +0200
@@ -1,48 +1,42 @@
package org.hedgewars.hedgeroid.netplay;
-import java.io.File;
-import java.io.FileNotFoundException;
+import static org.hedgewars.hedgeroid.netplay.ThreadedNetConnection.ToNetMsgType.*;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
import java.util.TreeMap;
-import org.hedgewars.hedgeroid.R;
-import org.hedgewars.hedgeroid.Utils;
-import org.hedgewars.hedgeroid.Datastructures.RoomlistRoom;
+import org.hedgewars.hedgeroid.RoomStateManager;
+import org.hedgewars.hedgeroid.Datastructures.GameConfig;
+import org.hedgewars.hedgeroid.Datastructures.MapRecipe;
+import org.hedgewars.hedgeroid.Datastructures.Player;
+import org.hedgewars.hedgeroid.Datastructures.PlayerInRoom;
+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;
+import org.hedgewars.hedgeroid.Datastructures.Weaponsets;
import org.hedgewars.hedgeroid.frontlib.Flib;
-import org.hedgewars.hedgeroid.frontlib.Frontlib;
-import org.hedgewars.hedgeroid.frontlib.Frontlib.BoolCallback;
-import org.hedgewars.hedgeroid.frontlib.Frontlib.IntStrCallback;
-import org.hedgewars.hedgeroid.frontlib.Frontlib.MetaschemePtr;
-import org.hedgewars.hedgeroid.frontlib.Frontlib.NetconnPtr;
-import org.hedgewars.hedgeroid.frontlib.Frontlib.RoomArrayPtr;
-import org.hedgewars.hedgeroid.frontlib.Frontlib.RoomCallback;
-import org.hedgewars.hedgeroid.frontlib.Frontlib.RoomListCallback;
-import org.hedgewars.hedgeroid.frontlib.Frontlib.RoomPtr;
-import org.hedgewars.hedgeroid.frontlib.Frontlib.StrBoolCallback;
-import org.hedgewars.hedgeroid.frontlib.Frontlib.StrCallback;
-import org.hedgewars.hedgeroid.frontlib.Frontlib.StrIntCallback;
-import org.hedgewars.hedgeroid.frontlib.Frontlib.StrRoomCallback;
-import org.hedgewars.hedgeroid.frontlib.Frontlib.StrStrCallback;
-import org.hedgewars.hedgeroid.frontlib.Frontlib.TeamCallback;
-import org.hedgewars.hedgeroid.frontlib.Frontlib.TeamPtr;
-import org.hedgewars.hedgeroid.frontlib.Frontlib.VoidCallback;
+import org.hedgewars.hedgeroid.netplay.ThreadedNetConnection.ToNetMsgType;
+import org.hedgewars.hedgeroid.util.ObservableTreeMap;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
-import android.content.res.Resources;
import android.os.Handler;
-import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.util.Pair;
-import com.sun.jna.Pointer;
/**
* This class manages the application's networking state.
@@ -72,21 +66,25 @@
private final FromNetHandler fromNetHandler = new FromNetHandler();
private State state = State.NOT_CONNECTED;
- private int foregroundUsers = 0; // Reference counter of clients requesting foreground tick speed (fast ticks)
- private boolean chief; // Do we control the current room?
private String playerName;
+ // null or stale if not in room state
+ private final NetRoomState netRoomState = new NetRoomState(this);
+
// null if there is no running connection (==state is NOT_CONNECTED)
private ThreadedNetConnection connection;
- public final LobbyPlayerlist lobbyPlayerlist = new LobbyPlayerlist();
- public final RoomPlayerlist roomPlayerlist = new RoomPlayerlist();
+ public final ObservableTreeMap<String, Player> lobbyPlayerlist = new ObservableTreeMap<String, Player>();
+ public final ObservableTreeMap<String, PlayerInRoom> roomPlayerlist = new ObservableTreeMap<String, PlayerInRoom>();
public final Roomlist roomList = new Roomlist();
public final MessageLog lobbyChatlog;
public final MessageLog roomChatlog;
- public final Teamlist roomTeamlist = new Teamlist();
+ public final ObservableTreeMap<String, TeamInGame> roomTeamlist = new ObservableTreeMap<String, TeamInGame>();
private final Map<String, Team> roomRequestedTeams = new TreeMap<String, Team>();
+ private final List<GameMessageListener> gameMessageListeners = new LinkedList<GameMessageListener>();
+ private final List<RunGameListener> runGameListeners = new LinkedList<RunGameListener>();
+
public Netplay(Context appContext) {
this.appContext = appContext;
broadcastManager = LocalBroadcastManager.getInstance(appContext);
@@ -94,12 +92,52 @@
roomChatlog = new MessageLog(appContext);
}
- private void clearState() {
+ public RoomStateManager getRoomStateManager() {
+ return netRoomState;
+ }
+
+ private void clearLobbyState() {
lobbyPlayerlist.clear();
roomList.clear();
lobbyChatlog.clear();
}
+ 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);
+ }
+ }
+
+ public void registerGameMessageListener(GameMessageListener listener) {
+ gameMessageListeners.add(listener);
+ }
+
+ public void unregisterGameMessageListener(GameMessageListener listener) {
+ gameMessageListeners.remove(listener);
+ }
+
+ public void registerRunGameListener(RunGameListener listener) {
+ runGameListeners.add(listener);
+ }
+
+ public void unregisterRunGameListener(RunGameListener listener) {
+ runGameListeners.remove(listener);
+ }
+
public void connectToDefaultServer(String playerName) {
connect(playerName, DEFAULT_SERVER, DEFAULT_PORT);
}
@@ -117,35 +155,39 @@
throw new IllegalStateException("Attempt to start a new connection while the old one was still running.");
}
- clearState();
+ clearLobbyState();
changeState(State.CONNECTING);
connection = ThreadedNetConnection.startConnection(appContext, fromNetHandler, name, host, port);
- connection.setFastTickRate(foregroundUsers > 0);
+ connection.setFastTickRate(true);
}
public void sendNick(String nick) {
playerName = nick;
- sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_NICK, nick);
+ sendToNet(MSG_SEND_NICK, nick);
}
- public void sendPassword(String password) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_PASSWORD, password); }
- public void sendQuit(String message) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_QUIT, message); }
- public void sendRoomlistRequest() { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_ROOMLIST_REQUEST); }
- public void sendPlayerInfoQuery(String name) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_PLAYER_INFO_REQUEST, name); }
- 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 sendKick(String player) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_KICK, player); }
+ public void sendPassword(String password) { sendToNet(MSG_SEND_PASSWORD, password); }
+ public void sendQuit(String message) { sendToNet(MSG_SEND_QUIT, message); }
+ public void sendRoomlistRequest() { sendToNet(MSG_SEND_ROOMLIST_REQUEST); }
+ public void sendPlayerInfoQuery(String name) { sendToNet(MSG_SEND_PLAYER_INFO_REQUEST, name); }
+ public void sendChat(String s) { sendToNet(MSG_SEND_CHAT, s); }
+ public void sendTeamChat(String s) { sendToNet(MSG_SEND_TEAMCHAT, s); }
+ public void sendFollowPlayer(String nick) { sendToNet(MSG_SEND_FOLLOW_PLAYER, nick); }
+ public void sendJoinRoom(String name) { sendToNet(MSG_SEND_JOIN_ROOM, name); }
+ 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) {
roomRequestedTeams.put(newTeam.name, newTeam);
- sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_ADD_TEAM, newTeam);
+ sendToNet(MSG_SEND_ADD_TEAM, newTeam);
}
- public void sendRemoveTeam(String teamName) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_REMOVE_TEAM, teamName); }
- public void sendTeamColorIndex(String teamName, int colorIndex) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_TEAM_COLOR_INDEX, colorIndex, teamName); }
- public void sendTeamHogCount(String teamName, int hogCount) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_TEAM_HOG_COUNT, hogCount, teamName); }
+ public void sendRemoveTeam(String teamName) { sendToNet(MSG_SEND_REMOVE_TEAM, teamName); }
+ public void sendTeamColorIndex(String teamName, int colorIndex) { sendToNet(MSG_SEND_TEAM_COLOR_INDEX, colorIndex, teamName); }
+ public void sendTeamHogCount(String teamName, int hogCount) { sendToNet(MSG_SEND_TEAM_HOG_COUNT, hogCount, teamName); }
+ 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 disconnect() { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_DISCONNECT, "User Quit"); }
+ public void disconnect() { sendToNet(MSG_DISCONNECT, "User Quit"); }
private static Netplay instance;
@@ -179,51 +221,29 @@
}
public boolean isChief() {
- return chief;
+ if(netRoomState != null) {
+ return netRoomState.chief;
+ } else {
+ return false;
+ }
}
public String getPlayerName() {
return playerName;
}
- /**
- * Indicate that you want network messages to be checked regularly (several times per second).
- * As long as nobody requests fast ticks, the network is only checked once every few seconds
- * to conserve battery power.
- * Once you no longer need fast updates, call unrequestFastTicks.
- */
- public void requestFastTicks() {
- if(foregroundUsers == Integer.MAX_VALUE) {
- throw new RuntimeException("Reference counter overflow");
- }
- if(foregroundUsers == 0 && connection != null) {
- connection.setFastTickRate(true);
- }
- foregroundUsers++;
- }
-
- public void unrequestFastTicks() {
- if(foregroundUsers == 0) {
- throw new RuntimeException("Reference counter underflow");
- }
- foregroundUsers--;
- if(foregroundUsers == 0 && connection != null) {
- connection.setFastTickRate(false);
- }
- }
-
- private boolean sendToNet(int what) {
+ boolean sendToNet(ToNetMsgType what) {
return sendToNet(what, 0, null);
}
- private boolean sendToNet(int what, Object obj) {
+ boolean sendToNet(ToNetMsgType what, Object obj) {
return sendToNet(what, 0, obj);
}
- private boolean sendToNet(int what, int arg1, Object obj) {
+ boolean sendToNet(ToNetMsgType what, int arg1, Object obj) {
if(connection != null) {
Handler handler = connection.toNetHandler;
- return handler.sendMessage(handler.obtainMessage(what, arg1, 0, obj));
+ return handler.sendMessage(handler.obtainMessage(what.ordinal(), arg1, 0, obj));
} else {
return false;
}
@@ -237,33 +257,44 @@
}
}
+ public static enum FromNetMsgType {
+ MSG_LOBBY_JOIN,
+ MSG_LOBBY_LEAVE,
+ MSG_ROOM_JOIN,
+ MSG_ROOM_LEAVE,
+ MSG_CHAT,
+ MSG_MESSAGE,
+ MSG_ROOM_ADD,
+ MSG_ROOM_UPDATE,
+ MSG_ROOM_DELETE,
+ MSG_ROOMLIST,
+ MSG_CONNECTED,
+ MSG_DISCONNECTED,
+ MSG_PASSWORD_REQUEST,
+ MSG_ENTER_ROOM_FROM_LOBBY,
+ MSG_LEAVE_ROOM,
+ MSG_READYSTATE,
+ MSG_TEAM_ADDED,
+ MSG_TEAM_DELETED,
+ MSG_TEAM_ACCEPTED,
+ MSG_TEAM_COLOR_CHANGED,
+ MSG_HOG_COUNT_CHANGED,
+ MSG_ENGINE_MESSAGE,
+ MSG_RUN_GAME,
+ MSG_SCHEME_CHANGED,
+ MSG_MAP_CHANGED,
+ MSG_ROOM_CHIEF_STATUS_CHANGED,
+ MSG_SCRIPT_CHANGED,
+ MSG_WEAPONSET_CHANGED;
+
+ static final List<FromNetMsgType> values = Collections.unmodifiableList(Arrays.asList(FromNetMsgType.values()));
+ }
+
/**
* Processes messages from the networking system. Always runs on the main thread.
*/
@SuppressLint("HandlerLeak")
final class FromNetHandler extends Handler {
- public static final int MSG_LOBBY_JOIN = 0;
- public static final int MSG_LOBBY_LEAVE = 1;
- 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 static final int MSG_READYSTATE = 15;
- public static final int MSG_TEAM_ADDED = 16;
- public static final int MSG_TEAM_DELETED = 17;
- public static final int MSG_TEAM_ACCEPTED = 18;
- public static final int MSG_TEAM_COLOR_CHANGED = 19;
- public static final int MSG_HOG_COUNT_CHANGED = 20;
-
public FromNetHandler() {
super(Looper.getMainLooper());
}
@@ -271,10 +302,10 @@
@SuppressWarnings("unchecked")
@Override
public void handleMessage(Message msg) {
- switch(msg.what) {
+ switch(FromNetMsgType.values.get(msg.what)) {
case MSG_LOBBY_JOIN: {
String name = (String)msg.obj;
- lobbyPlayerlist.addPlayerWithNewId(name);
+ lobbyPlayerlist.put(name, new Player(name, false, false));
lobbyChatlog.appendPlayerJoin(name);
break;
}
@@ -286,7 +317,12 @@
}
case MSG_ROOM_JOIN: {
String name = (String)msg.obj;
- roomPlayerlist.addPlayerWithNewId(name);
+ Player p = lobbyPlayerlist.get(name);
+ if(p==null) {
+ Log.w("Netplay", "Unknown player joined room: "+name);
+ p = new Player(name, false, false);
+ }
+ roomPlayerlist.put(name, new PlayerInRoom(p, false));
roomChatlog.appendPlayerJoin(name);
break;
}
@@ -299,18 +335,25 @@
case MSG_CHAT: {
Pair<String, String> args = (Pair<String, String>)msg.obj;
getCurrentLog().appendChat(args.first, args.second);
+ for(GameMessageListener listener : gameMessageListeners) {
+ listener.onChatMessage(args.first, args.second);
+ }
break;
}
case MSG_MESSAGE: {
getCurrentLog().appendMessage(msg.arg1, (String)msg.obj);
+ for(GameMessageListener listener : gameMessageListeners) {
+ listener.onMessage(1, (String)msg.obj);
+ }
break;
}
case MSG_ROOM_ADD: {
- roomList.addRoomWithNewId((RoomlistRoom)msg.obj);
+ Room room = (Room)msg.obj;
+ roomList.addRoomWithNewId(room);
break;
}
case MSG_ROOM_UPDATE: {
- Pair<String, RoomlistRoom> args = (Pair<String, RoomlistRoom>)msg.obj;
+ Pair<String, Room> args = (Pair<String, Room>)msg.obj;
roomList.updateRoom(args.first, args.second);
break;
}
@@ -319,7 +362,8 @@
break;
}
case MSG_ROOMLIST: {
- roomList.updateList((RoomlistRoom[])msg.obj);
+ Room[] rooms = (Room[])msg.obj;
+ roomList.updateList(rooms);
break;
}
case MSG_CONNECTED: {
@@ -330,6 +374,9 @@
}
case MSG_DISCONNECTED: {
Pair<Boolean, String> args = (Pair<Boolean, String>)msg.obj;
+ for(GameMessageListener listener : gameMessageListeners) {
+ listener.onNetDisconnected();
+ }
changeState(State.NOT_CONNECTED);
connection = null;
Intent intent = new Intent(ACTION_DISCONNECTED);
@@ -345,12 +392,8 @@
break;
}
case MSG_ENTER_ROOM_FROM_LOBBY: {
- roomChatlog.clear();
- roomPlayerlist.clear();
- roomTeamlist.clear();
- roomRequestedTeams.clear();
+ initRoomState((Boolean)msg.obj);
changeState(State.ROOM);
- chief = (Boolean)msg.obj;
Intent intent = new Intent(ACTION_ENTERED_ROOM_FROM_LOBBY);
broadcastManager.sendBroadcastSync(intent);
break;
@@ -365,15 +408,23 @@
}
case MSG_READYSTATE: {
Pair<String, Boolean> args = (Pair<String, Boolean>)msg.obj;
- roomPlayerlist.setReady(args.first, args.second);
+ String name = args.first;
+ Boolean newReadyState = args.second;
+ PlayerInRoom oldEntry = roomPlayerlist.get(name);
+ if(oldEntry==null) {
+ Log.e("Netplay", "Setting readystate for unknown player "+name);
+ } else {
+ roomPlayerlist.put(name, new PlayerInRoom(oldEntry.player, newReadyState));
+ }
break;
}
case MSG_TEAM_ADDED: {
Team newTeam = (Team)msg.obj;
- TeamIngameAttributes attrs = new TeamIngameAttributes(playerName, roomTeamlist.getUnusedOrRandomColorIndex(), TeamIngameAttributes.DEFAULT_HOG_COUNT, false);
+ int colorIndex = TeamInGame.getUnusedOrRandomColorIndex(roomTeamlist.getMap().values());
+ TeamIngameAttributes attrs = new TeamIngameAttributes(playerName, colorIndex, TeamIngameAttributes.DEFAULT_HOG_COUNT, true);
TeamInGame tig = new TeamInGame(newTeam, attrs);
- roomTeamlist.addTeamWithNewId(tig);
- if(chief) {
+ roomTeamlist.put(newTeam.name, tig);
+ if(isChief()) {
sendTeamColorIndex(newTeam.name, attrs.colorIndex);
sendTeamHogCount(newTeam.name, attrs.hogCount);
}
@@ -386,10 +437,11 @@
case MSG_TEAM_ACCEPTED: {
Team requestedTeam = roomRequestedTeams.remove(msg.obj);
if(requestedTeam!=null) {
- TeamIngameAttributes attrs = new TeamIngameAttributes(playerName, roomTeamlist.getUnusedOrRandomColorIndex(), TeamIngameAttributes.DEFAULT_HOG_COUNT, false);
+ int colorIndex = TeamInGame.getUnusedOrRandomColorIndex(roomTeamlist.getMap().values());
+ TeamIngameAttributes attrs = new TeamIngameAttributes(playerName, colorIndex, TeamIngameAttributes.DEFAULT_HOG_COUNT, false);
TeamInGame tig = new TeamInGame(requestedTeam, attrs);
- roomTeamlist.addTeamWithNewId(tig);
- if(chief) {
+ roomTeamlist.put(requestedTeam.name, tig);
+ if(isChief()) {
sendTeamColorIndex(requestedTeam.name, attrs.colorIndex);
sendTeamHogCount(requestedTeam.name, attrs.hogCount);
}
@@ -399,27 +451,59 @@
break;
}
case MSG_TEAM_COLOR_CHANGED: {
- Pair<TeamInGame, Long> oldEntry = roomTeamlist.get((String)msg.obj);
+ TeamInGame oldEntry = roomTeamlist.get((String)msg.obj);
if(oldEntry != null) {
- TeamInGame tig = oldEntry.first;
- TeamIngameAttributes tiga = tig.ingameAttribs.withColorIndex(msg.arg1);
- roomTeamlist.put(tig.team.name, Pair.create(tig.withAttribs(tiga), oldEntry.second));
+ TeamIngameAttributes newAttribs = oldEntry.ingameAttribs.withColorIndex(msg.arg1);
+ roomTeamlist.put(oldEntry.team.name, oldEntry.withAttribs(newAttribs));
} else {
Log.e("Netplay", "Color update for unknown team "+msg.obj);
}
break;
}
case MSG_HOG_COUNT_CHANGED: {
- Pair<TeamInGame, Long> oldEntry = roomTeamlist.get((String)msg.obj);
+ TeamInGame oldEntry = roomTeamlist.get((String)msg.obj);
if(oldEntry != null) {
- TeamInGame tig = oldEntry.first;
- TeamIngameAttributes tiga = tig.ingameAttribs.withHogCount(msg.arg1);
- roomTeamlist.put(tig.team.name, Pair.create(tig.withAttribs(tiga), oldEntry.second));
+ TeamIngameAttributes newAttribs = oldEntry.ingameAttribs.withHogCount(msg.arg1);
+ roomTeamlist.put(oldEntry.team.name, oldEntry.withAttribs(newAttribs));
} else {
Log.e("Netplay", "Hog count update for unknown team "+msg.obj);
}
break;
}
+ case MSG_ENGINE_MESSAGE: {
+ byte[] em = (byte[])msg.obj;
+ for(GameMessageListener listener : gameMessageListeners) {
+ listener.onEngineMessage(em);
+ }
+ break;
+ }
+ case MSG_RUN_GAME: {
+ GameConfig config = (GameConfig)msg.obj;
+ for(RunGameListener listener : runGameListeners) {
+ listener.runGame(config);
+ }
+ break;
+ }
+ case MSG_MAP_CHANGED: {
+ netRoomState.setMapRecipe((MapRecipe)msg.obj);
+ break;
+ }
+ case MSG_ROOM_CHIEF_STATUS_CHANGED: {
+ netRoomState.setChief((Boolean)msg.obj);
+ break;
+ }
+ case MSG_SCHEME_CHANGED: {
+ netRoomState.setScheme((Scheme)msg.obj);
+ break;
+ }
+ case MSG_SCRIPT_CHANGED: {
+ netRoomState.setGameStyle((String)msg.obj);
+ break;
+ }
+ case MSG_WEAPONSET_CHANGED: {
+ netRoomState.setWeaponset((Weaponset)msg.obj);
+ break;
+ }
default: {
Log.e("FromNetHandler", "Unknown message type: "+msg.what);
break;
@@ -427,376 +511,4 @@
}
}
}
-
- /**
- * This class handles the actual communication with the networking library, on a separate thread.
- */
- private static class ThreadedNetConnection {
- private static final long TICK_INTERVAL_FAST = 100;
- private static final long TICK_INTERVAL_SLOW = 5000;
- private static final Frontlib FLIB = Flib.INSTANCE;
-
- public final ToNetHandler toNetHandler;
-
- private final Context appContext;
- private final FromNetHandler fromNetHandler;
- private final TickHandler tickHandler;
-
- /**
- * conn can only be null while connecting (the first thing in the thread), and directly after disconnecting,
- * in the same message (the looper is shut down on disconnect, so there will be no messages after that).
- */
- private NetconnPtr conn;
- private String playerName;
-
- private ThreadedNetConnection(Context appContext, FromNetHandler fromNetHandler) {
- this.appContext = appContext;
- this.fromNetHandler = fromNetHandler;
-
- HandlerThread thread = new HandlerThread("NetThread");
- thread.start();
- toNetHandler = new ToNetHandler(thread.getLooper());
- tickHandler = new TickHandler(thread.getLooper(), TICK_INTERVAL_FAST, tickCb);
- }
-
- private void connect(final String name, final String host, final int port) {
- toNetHandler.post(new Runnable() {
- public void run() {
- playerName = name == null ? "Player" : name;
- MetaschemePtr meta = null;
- File dataPath;
- try {
- dataPath = Utils.getDataPathFile(appContext);
- } catch (FileNotFoundException e) {
- shutdown(true, appContext.getString(R.string.sdcard_not_mounted));
- return;
- }
- String metaschemePath = new File(dataPath, "metasettings.ini").getAbsolutePath();
- meta = FLIB.flib_metascheme_from_ini(metaschemePath);
- if(meta == null) {
- shutdown(true, appContext.getString(R.string.error_unexpected, "Missing metasettings.ini"));
- return;
- }
- conn = FLIB.flib_netconn_create(playerName, meta, dataPath.getAbsolutePath(), host, port);
- if(conn == null) {
- shutdown(true, appContext.getString(R.string.error_connection_failed));
- return;
- }
- 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);
- FLIB.flib_netconn_onRoomUpdate(conn, roomUpdateCb, null);
- FLIB.flib_netconn_onRoomDelete(conn, roomDeleteCb, null);
- FLIB.flib_netconn_onConnected(conn, connectedCb, null);
- 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_netconn_onReadyState(conn, readyStateCb, null);
- FLIB.flib_netconn_onTeamAdd(conn, teamAddedCb, null);
- FLIB.flib_netconn_onTeamDelete(conn, teamDeletedCb, null);
- FLIB.flib_netconn_onTeamAccepted(conn, teamAcceptedCb, null);
- FLIB.flib_netconn_onTeamColorChanged(conn, teamColorChangedCb, null);
- FLIB.flib_netconn_onHogCountChanged(conn, hogCountChangedCb, null);
-
- FLIB.flib_metascheme_release(meta);
- tickHandler.start();
- }
- });
- }
-
- public static ThreadedNetConnection startConnection(Context appContext, FromNetHandler fromNetHandler, String playerName, String host, int port) {
- ThreadedNetConnection result = new ThreadedNetConnection(appContext, fromNetHandler);
- result.connect(playerName, host, port);
- return result;
- }
-
- public void setFastTickRate(boolean fastTickRate) {
- tickHandler.setInterval(fastTickRate ? TICK_INTERVAL_FAST : TICK_INTERVAL_SLOW);
- }
-
- private final Runnable tickCb = new Runnable() {
- public void run() {
- FLIB.flib_netconn_tick(conn);
- }
- };
-
- private final StrCallback lobbyJoinCb = new StrCallback() {
- public void callback(Pointer context, String name) {
- sendFromNet(FromNetHandler.MSG_LOBBY_JOIN, name);
- }
- };
-
- private final StrStrCallback lobbyLeaveCb = new StrStrCallback() {
- public void callback(Pointer context, String name, String msg) {
- sendFromNet(FromNetHandler.MSG_LOBBY_LEAVE, Pair.create(name, msg));
- }
- };
-
- 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));
- }
- };
-
- private final IntStrCallback messageCb = new IntStrCallback() {
- public void callback(Pointer context, int type, String msg) {
- sendFromNet(FromNetHandler.MSG_MESSAGE, type, msg);
- }
- };
-
- private final RoomCallback roomAddCb = new RoomCallback() {
- public void callback(Pointer context, RoomPtr roomPtr) {
- sendFromNet(FromNetHandler.MSG_ROOM_ADD, roomPtr.deref());
- }
- };
-
- private final StrRoomCallback roomUpdateCb = new StrRoomCallback() {
- public void callback(Pointer context, String name, RoomPtr roomPtr) {
- sendFromNet(FromNetHandler.MSG_ROOM_UPDATE, Pair.create(name, roomPtr.deref()));
- }
- };
-
- private final StrCallback roomDeleteCb = new StrCallback() {
- public void callback(Pointer context, final String name) {
- sendFromNet(FromNetHandler.MSG_ROOM_DELETE, name);
- }
- };
-
- private final RoomListCallback roomlistCb = new RoomListCallback() {
- public void callback(Pointer context, RoomArrayPtr arg1, int count) {
- sendFromNet(FromNetHandler.MSG_ROOMLIST, arg1.getRooms(count));
- }
- };
-
- private final VoidCallback connectedCb = new VoidCallback() {
- public void callback(Pointer context) {
- FLIB.flib_netconn_send_request_roomlist(conn);
- playerName = FLIB.flib_netconn_get_playername(conn);
- sendFromNet(FromNetHandler.MSG_CONNECTED, playerName);
- }
- };
-
- private final StrCallback passwordRequestCb = new StrCallback() {
- public void callback(Pointer context, String nickname) {
- sendFromNet(FromNetHandler.MSG_PASSWORD_REQUEST, playerName);
- }
- };
-
- private final BoolCallback enterRoomCb = new BoolCallback() {
- public void callback(Pointer context, boolean isChief) {
- sendFromNet(FromNetHandler.MSG_ENTER_ROOM_FROM_LOBBY, isChief);
- }
- };
-
- private final IntStrCallback leaveRoomCb = new IntStrCallback() {
- public void callback(Pointer context, int reason, String message) {
- sendFromNet(FromNetHandler.MSG_LEAVE_ROOM, reason, message);
- }
- };
-
- private final StrBoolCallback readyStateCb = new StrBoolCallback() {
- public void callback(Pointer context, String player, boolean ready) {
- sendFromNet(FromNetHandler.MSG_READYSTATE, Pair.create(player, ready));
- }
- };
-
- private final TeamCallback teamAddedCb = new TeamCallback() {
- public void callback(Pointer context, TeamPtr team) {
- sendFromNet(FromNetHandler.MSG_TEAM_ADDED, team.deref().team);
- }
- };
-
- private final StrCallback teamDeletedCb = new StrCallback() {
- public void callback(Pointer context, String teamName) {
- sendFromNet(FromNetHandler.MSG_TEAM_DELETED, teamName);
- }
- };
-
- private final StrCallback teamAcceptedCb = new StrCallback() {
- public void callback(Pointer context, String teamName) {
- sendFromNet(FromNetHandler.MSG_TEAM_ACCEPTED, teamName);
- }
- };
-
- private final StrIntCallback teamColorChangedCb = new StrIntCallback() {
- public void callback(Pointer context, String teamName, int colorIndex) {
- sendFromNet(FromNetHandler.MSG_TEAM_COLOR_CHANGED, colorIndex, teamName);
- }
- };
-
- private final StrIntCallback hogCountChangedCb = new StrIntCallback() {
- public void callback(Pointer context, String teamName, int hogCount) {
- sendFromNet(FromNetHandler.MSG_HOG_COUNT_CHANGED, hogCount, teamName);
- }
- };
-
- private void shutdown(boolean error, String message) {
- if(conn != null) {
- FLIB.flib_netconn_destroy(conn);
- conn = null;
- }
- tickHandler.stop();
- toNetHandler.getLooper().quit();
- sendFromNet(FromNetHandler.MSG_DISCONNECTED, Pair.create(error, message));
- }
-
- private final IntStrCallback disconnectCb = new IntStrCallback() {
- public void callback(Pointer context, int reason, String message) {
- Boolean error = reason != Frontlib.NETCONN_DISCONNECT_NORMAL;
- String messageForUser = createDisconnectUserMessage(appContext.getResources(), reason, message);
- shutdown(error, messageForUser);
- }
- };
-
- private static String createDisconnectUserMessage(Resources res, int reason, String message) {
- switch(reason) {
- case Frontlib.NETCONN_DISCONNECT_AUTH_FAILED:
- return res.getString(R.string.error_auth_failed);
- case Frontlib.NETCONN_DISCONNECT_CONNLOST:
- return res.getString(R.string.error_connection_lost);
- case Frontlib.NETCONN_DISCONNECT_INTERNAL_ERROR:
- return res.getString(R.string.error_unexpected, message);
- case Frontlib.NETCONN_DISCONNECT_SERVER_TOO_OLD:
- return res.getString(R.string.error_server_too_old);
- default:
- return message;
- }
- }
-
- private boolean sendFromNet(int what, Object obj) {
- return fromNetHandler.sendMessage(fromNetHandler.obtainMessage(what, obj));
- }
-
- private boolean sendFromNet(int what, int arg1, Object obj) {
- return fromNetHandler.sendMessage(fromNetHandler.obtainMessage(what, arg1, 0, obj));
- }
-
- /**
- * Processes messages to the networking system. Runs on a non-main thread.
- */
- @SuppressLint("HandlerLeak")
- public final class ToNetHandler extends Handler {
- public static final int MSG_SEND_NICK = 0;
- public static final int MSG_SEND_PASSWORD = 1;
- public static final int MSG_SEND_QUIT = 2;
- 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_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_SEND_KICK = 10;
- public static final int MSG_SEND_ADD_TEAM = 11;
- public static final int MSG_SEND_REMOVE_TEAM = 12;
- public static final int MSG_DISCONNECT = 13;
- public static final int MSG_SEND_TEAM_COLOR_INDEX = 14;
- public static final int MSG_SEND_TEAM_HOG_COUNT = 15;
-
- public ToNetHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch(msg.what) {
- case MSG_SEND_NICK: {
- FLIB.flib_netconn_send_nick(conn, (String)msg.obj);
- break;
- }
- case MSG_SEND_PASSWORD: {
- FLIB.flib_netconn_send_password(conn, (String)msg.obj);
- break;
- }
- case MSG_SEND_QUIT: {
- FLIB.flib_netconn_send_quit(conn, (String)msg.obj);
- break;
- }
- case MSG_SEND_ROOMLIST_REQUEST: {
- FLIB.flib_netconn_send_request_roomlist(conn);
- break;
- }
- case MSG_SEND_PLAYER_INFO_REQUEST: {
- FLIB.flib_netconn_send_playerInfo(conn, (String)msg.obj);
- break;
- }
- case MSG_SEND_CHAT: {
- if(FLIB.flib_netconn_send_chat(conn, (String)msg.obj) == 0) {
- sendFromNet(FromNetHandler.MSG_CHAT, Pair.create(playerName, (String)msg.obj));
- }
- 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_SEND_KICK: {
- FLIB.flib_netconn_send_kick(conn, (String)msg.obj);
- break;
- }
- case MSG_SEND_ADD_TEAM: {
- FLIB.flib_netconn_send_addTeam(conn, TeamPtr.createJavaOwned((Team)msg.obj));
- break;
- }
- case MSG_SEND_REMOVE_TEAM: {
- if(FLIB.flib_netconn_send_removeTeam(conn, (String)msg.obj)==0) {
- sendFromNet(FromNetHandler.MSG_TEAM_DELETED, msg.obj);
- }
- break;
- }
- case MSG_DISCONNECT: {
- FLIB.flib_netconn_send_quit(conn, (String)msg.obj);
- shutdown(false, "User quit");
- break;
- }
- case MSG_SEND_TEAM_COLOR_INDEX: {
- if(FLIB.flib_netconn_send_teamColor(conn, (String)msg.obj, msg.arg1)==0) {
- sendFromNet(FromNetHandler.MSG_TEAM_COLOR_CHANGED, msg.arg1, msg.obj);
- }
- break;
- }
- case MSG_SEND_TEAM_HOG_COUNT: {
- if(FLIB.flib_netconn_send_teamHogCount(conn, (String)msg.obj, msg.arg1)==0) {
- sendFromNet(FromNetHandler.MSG_HOG_COUNT_CHANGED, msg.arg1, msg.obj);
- }
- break;
- }
- default: {
- Log.e("ToNetHandler", "Unknown message type: "+msg.what);
- break;
- }
- }
- }
- }
- }
}