/*
SubspaceMobile - A subspace/continuum client for mobile phones
Copyright (C) 2012 Kingsley Masters
Email: kshade2001 at users.sourceforge.net
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 3 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, see <http://www.gnu.org/licenses/>.
REVISIONS:
*/
package com.subspace.network;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Timer;
import android.content.Context;
import android.util.Log;
import com.subspace.android.Arena;
import com.subspace.android.Information;
import com.subspace.android.LVL;
import com.subspace.android.News;
import com.subspace.android.Player;
import com.subspace.network.messages.LvlSettings;
import com.subspace.network.messages.Chat;
import com.subspace.network.messages.FileTransfer;
import com.subspace.network.messages.LoginResponse;
import com.subspace.network.messages.MapInformation;
import com.subspace.network.messages.PlayerEnter;
import com.subspace.network.messages.PlayerLeave;
import com.subspace.network.messages.SynchronizationRequest;
import com.subspace.snrrrub.Checksum;
/**
*
* @author Kingsley
*/
public class NetworkGame extends NetworkSubspace implements INetworkCallback {
static final String TAG = "Subspace";
public static boolean LOG_GAME_PACKETS = true;
public final String ZoneName;
boolean loginResponseReceived = false;
LoginResponse loginResponse = null;
IGameCallback gameCallback;
News news;
Arena currentArena;
Timer positionTimer = new Timer();
public NetworkGame(Context context,String zonename) {
super(context);
this.ZoneName = zonename;
news = new News(_context,this.ZoneName);
this.setCallback(this);
}
public final void setGameCallback(IGameCallback callback) {
this.gameCallback = callback;
}
public LoginResponse Login(Boolean isNewUser, String username,
String password) throws IOException {
loginResponseReceived = false;
loginResponse = null;
try {
// TODO: create mac id
Log.d(TAG, "C2S_PASSWORD");
this.SSSendReliable(NetworkPacket.CreatePassword(isNewUser,
username, password, 12346789));
//now send sync
this.SSSync();
//and wait
synchronized (this) {
this.wait();
// this.wait(RESPONSE_TIMEOUT);
}
// if no response received return null
if (!loginResponseReceived) {
return null;
}
} catch (InterruptedException ie) {
Log.d(TAG, Log.getStackTraceString(ie));
}
return loginResponse;
}
public void EnterArena() {
EnterArena(null);
}
public void EnterArena(String name) {
try {
Log.d(TAG, "C2S_ARENALOGIN");
this.SSSendReliable(NetworkPacket.CreateArenaLogin((byte) 7,
(short)1024, (short)800, name, (byte)0));
//create new arena
currentArena = new Arena();
} catch (IOException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
}
public ByteBuffer Recv(ByteBuffer data, boolean decrypt) {
// decrypt
data = super.Recv(data, decrypt);
// analyse
if (data != null) {
if (LOG_GAME_PACKETS) {
if(data.limit() > 520)
{
Log.v(TAG,"Game: packet in excess of 520 recieived, cannot log at the moment");
} else {
Log.v(TAG, "Game: " + Util.ToHex(data));
}
}
try {
if (data.get(0) == NetworkPacket.S2C_PASSWORDACK) {
Log.d(TAG, "S2C_PASSWORDACK");
// its saved in the array file
loginResponse = new LoginResponse(data);
if(!loginResponse.isLoginOK())
{
//login failed
Log.e(TAG,loginResponse.getLoginMessage());
if(gameCallback!=null)
{
gameCallback.ConsoleMessageReceived(loginResponse.getLoginMessage());
}
SSDisconnect();
}
else
{
//send sync
SSSync();
//now ask for news
if(news.getCRC32()!=loginResponse.NewsChecksum)
{
Log.d(TAG, "Downloading News");
SSSendReliable(
NetworkPacket.CreateNewsTxtRequest()
);
} else {
// notify completion of task
synchronized (this) {
loginResponseReceived = true;
this.notify();
}
Log.d(TAG, "No News Changes");
}
}
} else if (data.get(0) == NetworkPacket.S2C_NOW_IN_GAME) {
Log.d(TAG, "S2C_NOW_IN_GAME");
//start sending position
/* positionTimer.scheduleAtFixedRate(new TimerTask()
{
@Override
public void run() {
try {
//TODO finish this
SSSend(NetworkPacket.Position(
(short)0,
(short)0,
(byte)0,
(short)0,
(short)0,
(short)0,
(short)0,
(short)0,
(byte)0
));
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e(TAG,Log.getStackTraceString(e));
}
}
}, 200, 200); */
if (gameCallback != null) {
gameCallback.NowInGameRecieved();
}
} else if (data.get(0) == NetworkPacket.S2C_MY_UID) {
Log.d(TAG, "S2C_MY_UID");
currentArena.SetMyId(data.getShort(1));
if (gameCallback != null) {
gameCallback.PlayerIdRecieved(data.getShort(1));
}
} else if (data.get(0) == NetworkPacket.S2C_ArenaSettings) {
Log.d(TAG, "S2C_ArenaSettings");
currentArena.LoadSettings(data);
//notify for ui
if (gameCallback != null) {
gameCallback.LvlSettingsReceived(currentArena.Settings);
}
} else if (data.get(0) == NetworkPacket.S2C_PlayerEntering) {
Log.d(TAG, "S2C_PlayerEntering");
PlayerEnter playerEntering = new PlayerEnter(data);
currentArena.Add(playerEntering);
//notify for ui
if (gameCallback != null) {
gameCallback.PlayerEntering(playerEntering);
}
} else if (data.get(0) == NetworkPacket.S2C_PlayerLeaving) {
Log.d(TAG, "S2C_PlayerLeaving");
PlayerLeave playerLeaving = new PlayerLeave(data);
currentArena.Remove(playerLeaving);
//notify for ui
if (gameCallback != null) {
gameCallback.PlayerLeaving(playerLeaving);
}
} else if (data.get(0) == NetworkPacket.S2C_LargePosition) {
Log.d(TAG, "S2C_LargePosition");
} else if (data.get(0) == NetworkPacket.S2C_PlayerDeath) {
Log.d(TAG, "S2C_PlayerDeath");
} else if (data.get(0) == NetworkPacket.S2C_ChatMessage) {
Log.d(TAG, "S2C_ChatMessage");
Chat chatMessage = new Chat(data);
Player player = currentArena.Get(chatMessage.PlayerId);
if(player!=null)
{
chatMessage.PlayerName = player.Name;
}
if (gameCallback != null) {
gameCallback.ChatMessageReceived(chatMessage);
}
} else if (data.get(0) == NetworkPacket.S2C_FlagPosition) {
Log.d(TAG, "S2C_FlagPosition");
} else if (data.get(0) == NetworkPacket.S2C_FileTransfer) {
Log.d(TAG, "S2C_FileTransfer");
FileTransfer ft = new FileTransfer(data);
Log.d(TAG, "S2C_FileTransfer Received: " + ft.Filename);
if(ft.Filename=="news.txt")
{
news.Save(ft.Data,ft.Compressed);
if (gameCallback != null) {
gameCallback.NewsReceieved(news);
}
// notify login completed
synchronized (this) {
loginResponseReceived = true;
this.notify();
}
}
} else if (data.get(0) == NetworkPacket.S2C_CompressedMapFile) {
Log.d(TAG, "S2C_CompressedMapFile");
FileTransfer ft = new FileTransfer(data);
Log.d(TAG, "S2C_CompressedMapFile Received: " + ft.Filename);
currentArena.Lvl.Save(ft.Data,ft.Compressed);
if (gameCallback != null) {
gameCallback.MapReceived(currentArena.Lvl);
}
} else if (data.get(0) == NetworkPacket.S2C_ChecksumRecv) {
Log.d(TAG, "S2C_ChecksumRecv");
SynchronizationRequest syncRequest = new SynchronizationRequest(data);
SSSend(NetworkPacket.CreateSecurityChecksum(
currentArena.SettingsCheckSum(syncRequest.ChecksumKey),
Checksum.EXEChecksum(syncRequest.ChecksumKey),
currentArena.LvlCheckSum(syncRequest.ChecksumKey)
));
} else if (data.get(0) == NetworkPacket.S2C_KeepAlive) {
Log.d(TAG, "S2C_KeepAlive");
//send postion
SSSend(NetworkPacket.CreatePosition(
(short)0,
(short)0,
(byte)0,
(short)0,
(short)0,
(short)0,
(short)0,
(short)0,
(byte)0
));
} else if (data.get(0) == NetworkPacket.S2C_BrickDropped) {
Log.d(TAG, "S2C_BrickDropped");
} else if (data.get(0) == NetworkPacket.S2C_MapInformation) {
Log.d(TAG, "S2C_MapInformation");
MapInformation mapInfo = new MapInformation(data);
currentArena.Lvl = new LVL(_context,ZoneName,mapInfo.Filename);
//we dont have this map so request it
if(mapInfo.CRC32!= currentArena.Lvl.getCRC32())
{
Log.d(TAG, "Request Map " + mapInfo.Filename);
SSSendReliable(
NetworkPacket.CreateMapRequest()
);
}
if (gameCallback != null) {
gameCallback.MapInformationRecieved(mapInfo);
}
} else {
Log.i(TAG, String.format("Unhandled Packet %d H%x",data.get(0),data.get(0)));
}
} catch (Exception e) {
Log.e(TAG, Log.getStackTraceString(e));
}
}
return null;
}
public void SendChat(String message) {
// send reliable
try {
SSSendReliable(
NetworkPacket.CreateChat((byte)2,(byte)0,(short)0,message)
);
} catch (IOException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
}
public Arena getArena() {
return currentArena;
}
}