v0.1.2: Asynchronous master server connections, largefont, traitor mode ends when traitor dies or sub reaches end of level

This commit is contained in:
Regalis
2015-08-14 01:59:41 +03:00
parent 5771bc7e02
commit bc4ea098f7
23 changed files with 377 additions and 98 deletions

View File

@@ -54,6 +54,13 @@
<Sprite texture="Content\UI\uiBackground.png" size="0.0, 0.0" sourcerect ="0.0, 90.0, 0.0, 100.0"/>
</GUITextBox>
<GUITickBox
color="0.5, 0.5, 0.5, 1.0"
outlinecolor="0.5, 0.57, 0.6, 1.0">
<Sprite texture="Content\UI\uiBackground.png" size="0.0, 0.0" sourcerect ="0.0, 90.0, 0.0, 100.0"/>
</GUITickBox>
<GUIMessageBox
padding="40.0, 40.0, 40.0, 40.0"
color="1.0, 1.0, 1.0, 1.0"

View File

@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.1.1.0")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyVersion("0.1.2.0")]
[assembly: AssemblyFileVersion("0.1.2.0")]

View File

@@ -34,7 +34,7 @@ namespace Subsurface
{
get { return pickedItems; }
}
public Sprite HeadSprite
{
get
@@ -156,7 +156,7 @@ namespace Subsurface
break;
}
}
public GUIFrame CreateInfoFrame(Rectangle rect)
{
GUIFrame frame = new GUIFrame(rect, Color.Transparent);

View File

@@ -246,6 +246,9 @@ namespace Subsurface
hull.OxygenPercentage = 100.0f;
}
break;
case "tutorial":
TutorialMode.Start();
break;
case "lobbyscreen":
case "lobby":
Game1.LobbyScreen.Select();

View File

@@ -20,7 +20,7 @@ namespace Subsurface
public static GUIStyle style;
static Texture2D t;
public static SpriteFont Font, SmallFont;
public static SpriteFont Font, SmallFont, LargeFont;
private static GraphicsDevice graphicsDevice;

View File

@@ -27,6 +27,14 @@ namespace Subsurface
private bool enabled;
public GUIComponent Selected
{
get
{
return selected;
}
}
public object SelectedData
{
get

View File

@@ -76,9 +76,10 @@ namespace Subsurface
}
public GUITextBlock(Rectangle rect, string text, GUIStyle style, Alignment alignment = Alignment.TopLeft, Alignment textAlignment = Alignment.TopLeft, GUIComponent parent = null, bool wrap = false)
public GUITextBlock(Rectangle rect, string text, GUIStyle style, Alignment alignment = Alignment.TopLeft, Alignment textAlignment = Alignment.TopLeft, GUIComponent parent = null, bool wrap = false, SpriteFont font =null)
: this (rect, text, null, null, alignment, textAlignment, style, parent, wrap)
{
this.Font = font == null ? GUI.Font : font;
}
public GUITextBlock(Rectangle rect, string text, Color? color, Color? textColor, Alignment textAlignment = Alignment.Left, GUIStyle style = null, GUIComponent parent = null, bool wrap = false)

View File

@@ -25,6 +25,12 @@ namespace Subsurface
}
}
public bool Enabled
{
get;
set;
}
public GUITickBox(Rectangle rect, string label, Alignment alignment, GUIComponent parent)
: base(null)
{
@@ -36,12 +42,16 @@ namespace Subsurface
box.SelectedColor = Color.DarkGray;
text = new GUITextBlock(new Rectangle(rect.X + 40, rect.Y, 200, 30), label, Color.Transparent, Color.White, Alignment.TopLeft, null, this);
Enabled = true;
}
public override void Update(float deltaTime)
{
base.Update(deltaTime);
if (!Enabled) return;
if (box.Rect.Contains(PlayerInput.GetMouseState.Position))
{
box.State = ComponentState.Hover;

View File

@@ -165,6 +165,7 @@ namespace Subsurface
{
GUI.Font = ToolBox.TryLoadFont("SpriteFont1", Content);
GUI.SmallFont = ToolBox.TryLoadFont("SmallFont", Content);
GUI.LargeFont = ToolBox.TryLoadFont("LargeFont", Content);
sw = new Stopwatch();

View File

@@ -30,16 +30,7 @@ namespace Subsurface
base.Update(deltaTime);
if (!isRunning) return;
if (DateTime.Now >= endTime)
{
string endMessage = traitor.character.Info.Name + " was a traitor! ";
endMessage += (traitor.character.Info.Gender == Gender.Male) ? "His" : "Her";
endMessage += " task was to assassinate " + target.character.Info.Name + ". The task was unsuccesful.";
End(endMessage);
return;
}
if (traitor==null || target ==null)
{
@@ -68,6 +59,35 @@ namespace Subsurface
endMessage += " task was to assassinate " + target.character.Info.Name + ". The task was succesful.";
End(endMessage);
}
else if (traitor.character.IsDead)
{
string endMessage = traitor.character.Info.Name + " was a traitor! ";
endMessage += (traitor.character.Info.Gender == Gender.Male) ? "His" : "Her";
endMessage += " task was to assassinate " + target.character.Info.Name + ". ";
endMessage += "The task was unsuccessful - the has submarine reached its destination.";
End(endMessage);
return;
}
else if (Level.Loaded.AtEndPosition)
{
string endMessage = traitor.character.Info.Name + " was a traitor! ";
endMessage += (traitor.character.Info.Gender == Gender.Male) ? "His" : "Her";
endMessage += " task was to assassinate " + target.character.Info.Name + ", but ";
endMessage += (traitor.character.Info.Gender == Gender.Male) ? "he" : "she";
endMessage += " got " + ((traitor.character.Info.Gender == Gender.Male) ? "himself" : "herself");
endMessage += " killed before completing it.";
End(endMessage);
return;
}
else if (DateTime.Now >= endTime)
{
string endMessage = traitor.character.Info.Name + " was a traitor! ";
endMessage += (traitor.character.Info.Gender == Gender.Male) ? "His" : "Her";
endMessage += " task was to assassinate " + target.character.Info.Name + ". The task was unsuccesful.";
End(endMessage);
return;
}
}
}
}

View File

@@ -144,11 +144,11 @@ namespace Subsurface
//PutItem(item, i, false, false);
combined = true;
}
else if (items[i].Combine(item))
{
//PutItem(items[i], i, false, false);
combined = true;
}
//else if (items[i].Combine(item))
//{
// //PutItem(items[i], i, false, false);
// combined = true;
//}
if (!combined) return false;

View File

@@ -179,7 +179,7 @@ namespace Subsurface.Items.Components
foreach (Item contained in item.ContainedItems)
{
contained.Condition = 0.0f;
if (contained.body!=null)
if (contained.body != null)
{
contained.body.SetTransform(item.SimPosition, contained.body.Rotation);
}

View File

@@ -178,7 +178,7 @@ namespace Subsurface
get
{
ItemContainer c = GetComponent<ItemContainer>();
return (c == null) ? null : c.inventory.items;
return (c == null) ? null : Array.FindAll(c.inventory.items, i=>i!=null);
}
}

View File

@@ -50,9 +50,8 @@ namespace Subsurface.Networking
}
public void ConnectToServer(string hostIP)
public void ConnectToServer(string hostIP, string password = "")
{
string[] address = hostIP.Split(':');
if (address.Length==1)
{
@@ -65,7 +64,7 @@ namespace Subsurface.Networking
if (!int.TryParse(address[1], out Port))
{
DebugConsole.ThrowError("Invalid port: address[1]!");
DebugConsole.ThrowError("Invalid port: "+address[1]+"!");
Port = DefaultPort;
}
}
@@ -85,6 +84,7 @@ namespace Subsurface.Networking
client.Start();
outmsg.Write((byte)PacketTypes.Login);
outmsg.Write(password);
outmsg.Write(Game1.Version.ToString());
outmsg.Write(Game1.SelectedPackage.Name);
outmsg.Write(Game1.SelectedPackage.MD5hash.Hash);

View File

@@ -22,17 +22,23 @@ namespace Subsurface.Networking
private TimeSpan refreshMasterInterval = new TimeSpan(0, 0, 40);
private DateTime refreshMasterTimer;
private bool masterServerResponded;
private bool registeredToMaster;
private string password;
private Client myClient;
public GameServer(string name, int port)
public GameServer(string name, int port, bool isPublic = false, string password="")
{
var endRoundButton = new GUIButton(new Rectangle(Game1.GraphicsWidth - 290, 20, 150, 25), "End round", Alignment.TopLeft, GUI.style, inGameHUD);
endRoundButton.OnClicked = EndButtonHit;
this.name = name;
this.password = password;
config = new NetPeerConfiguration("subsurface");
//config.SimulatedLoss = 0.2f;
@@ -62,7 +68,11 @@ namespace Subsurface.Networking
DebugConsole.ThrowError("Couldn't start the server", e);
}
RegisterToMasterServer();
if (isPublic)
{
RegisterToMasterServer();
}
updateInterval = new TimeSpan(0, 0, 0, 0, 30);
@@ -78,6 +88,7 @@ namespace Subsurface.Networking
request.AddParameter("servername", name);
request.AddParameter("serverport", Port);
request.AddParameter("playercount", PlayerCountToByte(connectedClients.Count, config.MaximumConnections));
request.AddParameter("password", string.IsNullOrWhiteSpace(password) ? 0 : 1);
// execute the request
RestResponse response = (RestResponse)client.Execute(request);
@@ -98,7 +109,7 @@ namespace Subsurface.Networking
refreshMasterTimer = DateTime.Now + refreshMasterInterval;
}
private void RefreshMaster()
private IEnumerable<object> RefreshMaster()
{
var client = new RestClient(NetworkMember.MasterServerUrl);
@@ -112,17 +123,49 @@ namespace Subsurface.Networking
var sw = new Stopwatch();
sw.Start();
RestResponse response = (RestResponse)client.Execute(request);
masterServerResponded = false;
var restRequestHandle = client.ExecuteAsync(request, response => MasterServerCallBack(response));
sw.Stop();
System.Diagnostics.Debug.WriteLine("took "+sw.ElapsedMilliseconds+" ms");
if (response.StatusCode != System.Net.HttpStatusCode.OK)
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 10);
while (!masterServerResponded)
{
DebugConsole.ThrowError("Error while connecting to master server (" +response.StatusCode+": "+response.StatusDescription+")");
if (DateTime.Now > timeOut)
{
restRequestHandle.Abort();
DebugConsole.ThrowError("Couldn't connect to master server (request timed out)");
registeredToMaster = false;
}
System.Diagnostics.Debug.WriteLine("took "+sw.ElapsedMilliseconds+" ms");
yield return Status.Running;
}
yield return Status.Success;
}
private void MasterServerCallBack(IRestResponse response)
{
masterServerResponded = true;
if (response.ErrorException != null)
{
DebugConsole.ThrowError("Error while connecting to master server", response.ErrorException);
registeredToMaster = false;
return;
}
if (response.StatusCode != System.Net.HttpStatusCode.OK)
{
DebugConsole.ThrowError("Error while connecting to master server (" + response.StatusCode + ": " + response.StatusDescription + ")");
registeredToMaster = false;
return;
}
}
public override void Update(float deltaTime)
@@ -159,7 +202,7 @@ namespace Subsurface.Networking
if (registeredToMaster && refreshMasterTimer < DateTime.Now)
{
RefreshMaster();
CoroutineManager.StartCoroutine(RefreshMaster());
refreshMasterTimer = DateTime.Now + refreshMasterInterval;
}
@@ -204,9 +247,10 @@ namespace Subsurface.Networking
Client existingClient = connectedClients.Find(c=> c.Connection == inc.SenderConnection);
if (existingClient==null)
{
string version = "", packageName="", packageHash="", name = "";
string userPassword = "", version = "", packageName="", packageHash="", name = "";
try
{
userPassword = inc.ReadString();
version = inc.ReadString();
packageName = inc.ReadString();
packageHash = inc.ReadString();
@@ -218,7 +262,12 @@ namespace Subsurface.Networking
break;
}
if (version != Game1.Version.ToString())
if (userPassword != password)
{
inc.SenderConnection.Deny("Wrong password!");
break;
}
else if (version != Game1.Version.ToString())
{
inc.SenderConnection.Deny("Subsurface version " + Game1.Version + " required to connect to the server (Your version: " + version + ")");
break;

View File

@@ -18,9 +18,8 @@ namespace Subsurface
private GUITextBox saveNameBox, seedBox;
private GUITextBox clientNameBox, ipBox;
private GUITextBox serverNameBox, portBox;
private GUITextBox serverNameBox, portBox, passwordBox;
private GUITickBox isPublicBox;
private Game1 game;
@@ -38,10 +37,10 @@ namespace Subsurface
menuTabs[(int)Tabs.Main] = new GUIFrame(panelRect, GUI.style);
//menuTabs[(int)Tabs.Main].Padding = GUI.style.smallPadding;
GUIButton button = new GUIButton(new Rectangle(0, 0, 0, 30), "Tutorial", Alignment.CenterX, GUI.style, menuTabs[(int)Tabs.Main]);
button.OnClicked = TutorialButtonClicked;
//GUIButton button = new GUIButton(new Rectangle(0, 0, 0, 30), "Tutorial", Alignment.CenterX, GUI.style, menuTabs[(int)Tabs.Main]);
//button.OnClicked = TutorialButtonClicked;
button = new GUIButton(new Rectangle(0, 70, 0, 30), "New Game", Alignment.CenterX, GUI.style, menuTabs[(int)Tabs.Main]);
GUIButton button = new GUIButton(new Rectangle(0, 70, 0, 30), "New Game", Alignment.CenterX, GUI.style, menuTabs[(int)Tabs.Main]);
button.UserData = (int)Tabs.NewGame;
button.OnClicked = SelectTab;
//button.Enabled = false;
@@ -112,16 +111,21 @@ namespace Subsurface
menuTabs[(int)Tabs.HostServer] = new GUIFrame(panelRect, GUI.style);
//menuTabs[(int)Tabs.JoinServer].Padding = GUI.style.smallPadding;
new GUITextBlock(new Rectangle(0, 0, 0, 30), "Host Server", GUI.style, Alignment.CenterX, Alignment.CenterX, menuTabs[(int)Tabs.HostServer]);
new GUITextBlock(new Rectangle(0, -25, 0, 30), "Host Server", GUI.style, Alignment.CenterX, Alignment.CenterX, menuTabs[(int)Tabs.HostServer], false, GUI.LargeFont);
new GUITextBlock(new Rectangle(0, 30, 0, 30), "Server Name:", GUI.style, Alignment.CenterX, Alignment.CenterX, menuTabs[(int)Tabs.HostServer]);
serverNameBox = new GUITextBox(new Rectangle(0, 60, 200, 30), Color.White, Color.Black, Alignment.CenterX, Alignment.CenterX, null, menuTabs[(int)Tabs.HostServer]);
serverNameBox = new GUITextBox(new Rectangle(0, 60, 200, 30), null, null, Alignment.CenterX, Alignment.CenterX, GUI.style, menuTabs[(int)Tabs.HostServer]);
new GUITextBlock(new Rectangle(0, 100, 0, 30), "Server port:", GUI.style, Alignment.CenterX, Alignment.CenterX, menuTabs[(int)Tabs.HostServer]);
portBox = new GUITextBox(new Rectangle(0, 130, 200, 30), Color.White, Color.Black, Alignment.CenterX, Alignment.CenterX, null, menuTabs[(int)Tabs.HostServer]);
portBox = new GUITextBox(new Rectangle(0, 130, 200, 30), null, null, Alignment.CenterX, Alignment.CenterX, GUI.style, menuTabs[(int)Tabs.HostServer]);
portBox.Text = NetworkMember.DefaultPort.ToString();
portBox.ToolTip = "Server port";
isPublicBox = new GUITickBox(new Rectangle(portBox.Rect.X - menuTabs[(int)Tabs.HostServer].Rect.X, 200, 20, 20), "Public server", Alignment.TopLeft, menuTabs[(int)Tabs.HostServer]);
new GUITextBlock(new Rectangle(0, 240, 0, 30), "Password (optional):", GUI.style, Alignment.CenterX, Alignment.CenterX, menuTabs[(int)Tabs.HostServer]);
passwordBox = new GUITextBox(new Rectangle(0, 270, 200, 30), null, null, Alignment.CenterX, Alignment.CenterX, GUI.style, menuTabs[(int)Tabs.HostServer]);
GUIButton hostButton = new GUIButton(new Rectangle(0, 0, 200, 30), "Start", Alignment.BottomCenter, GUI.style, menuTabs[(int)Tabs.HostServer]);
hostButton.OnClicked = HostServerClicked;
@@ -177,7 +181,7 @@ namespace Subsurface
return false;
}
Game1.NetworkMember = new GameServer(name, port);
Game1.NetworkMember = new GameServer(name, port, isPublicBox.Selected, passwordBox.Text);
Game1.NetLobbyScreen.IsServer = true;
Game1.NetLobbyScreen.Select();
@@ -194,7 +198,7 @@ namespace Subsurface
{
menuTabs[(int)Tabs.LoadGame].ClearChildren();
new GUITextBlock(new Rectangle(0, 0, 0, 30), "Load Game", GUI.style, Alignment.CenterX, Alignment.CenterX, menuTabs[(int)Tabs.LoadGame]);
new GUITextBlock(new Rectangle(0, -25, 0, 30), "Load Game", GUI.style, Alignment.CenterX, Alignment.CenterX, menuTabs[(int)Tabs.LoadGame], false, GUI.LargeFont);
string[] saveFiles = SaveUtil.GetSaveFiles();
@@ -376,26 +380,5 @@ namespace Subsurface
return true;
}
private bool JoinServer(GUIButton button, object obj)
{
if (string.IsNullOrEmpty(clientNameBox.Text)) return false;
if (string.IsNullOrEmpty(ipBox.Text)) return false;
Game1.NetworkMember = new GameClient(clientNameBox.Text);
Game1.Client.ConnectToServer(ipBox.Text);
return true;
//{
// Game1.NetLobbyScreen.Select();
// return true;
//}
//else
//{
// Game1.NetworkMember = null;
// return false;
//}
}
}
}

View File

@@ -14,6 +14,9 @@ namespace Subsurface
{
class ServerListScreen : Screen
{
//how often the client is allowed to refresh servers
private TimeSpan AllowedRefreshInterval = new TimeSpan(0,0,3);
private GUIFrame menu;
private GUIListBox serverList;
@@ -22,6 +25,15 @@ namespace Subsurface
private GUITextBox clientNameBox, ipBox;
//private RestRequestAsyncHandle restRequestHandle;
private bool masterServerResponded;
private int[] columnX;
//a timer for
private DateTime refreshDisableTimer;
private bool waitingForRefresh;
public ServerListScreen()
{
int width = Math.Min(Game1.GraphicsWidth - 160, 1000);
@@ -30,37 +42,56 @@ namespace Subsurface
Rectangle panelRect = new Rectangle(0, 0, width, height);
menu = new GUIFrame(panelRect, null, Alignment.Center, GUI.style);
new GUITextBlock(new Rectangle(0, 0, 0, 30), "Join Server", GUI.style, Alignment.CenterX, Alignment.CenterX, menu);
new GUITextBlock(new Rectangle(0, -25, 0, 30), "Join Server", GUI.style, Alignment.CenterX, Alignment.CenterX, menu, false, GUI.LargeFont);
new GUITextBlock(new Rectangle(0, 30, 0, 30), "Your Name:", GUI.style, menu);
clientNameBox = new GUITextBox(new Rectangle(0, 60, 200, 30), GUI.style, menu);
new GUITextBlock(new Rectangle(0, 100, 0, 30), "Server IP:", GUI.style, menu);
ipBox = new GUITextBox(new Rectangle(0, 130, 200, 30), GUI.style, menu);
int middleX = (int)(width * 0.4f);
serverList = new GUIListBox(new Rectangle(middleX,60,0,(int)(height*0.7f)), GUI.style, menu);
serverList.OnSelected = SelectServer;
new GUITextBlock(new Rectangle(middleX, 30, 0, 30), "Name", GUI.style, menu);
new GUITextBlock(new Rectangle(middleX, 30, 0, 30), "Players", GUI.style, Alignment.TopLeft, Alignment.TopCenter, menu);
new GUITextBlock(new Rectangle(middleX, 30, 0, 30), "Game running", GUI.style, Alignment.TopLeft, Alignment.TopRight, menu);
float[] columnRelativeX = new float[] { 0.15f, 0.55f, 0.15f, 0.15f };
columnX = new int[columnRelativeX.Length];
for (int n = 0; n < columnX.Length; n++)
{
columnX[n] = (int)(columnRelativeX[n] * serverList.Rect.Width);
if (n > 0) columnX[n] += columnX[n - 1];
}
new GUITextBlock(new Rectangle(middleX, 30, 0, 30), "Password", GUI.style, menu);
new GUITextBlock(new Rectangle(middleX + columnX[0], 30, 0, 30), "Name", GUI.style, menu);
new GUITextBlock(new Rectangle(middleX + columnX[1], 30, 0, 30), "Players", GUI.style, menu);
new GUITextBlock(new Rectangle(middleX + columnX[2], 30, 0, 30), "Running", GUI.style, menu);
joinButton = new GUIButton(new Rectangle(-170, 0, 150, 30), "Refresh", Alignment.BottomRight, GUI.style, menu);
joinButton.OnClicked = RefreshServers;
joinButton = new GUIButton(new Rectangle(0,0,150,30), "Join", Alignment.BottomRight, GUI.style, menu);
joinButton.OnClicked = JoinServer;
//joinButton.Enabled = false;
refreshDisableTimer = DateTime.Now;
}
public override void Select()
{
base.Select();
UpdateServerList();
//RefreshServers(null, null);
//UpdateServerList();
}
private bool SelectServer(object obj)
@@ -75,16 +106,39 @@ namespace Subsurface
private bool RefreshServers(GUIButton button, object obj)
{
UpdateServerList();
if (waitingForRefresh) return false;
serverList.ClearChildren();
new GUITextBlock(new Rectangle(0, 0, 0, 20), "Refreshing server list...", GUI.style, serverList);
CoroutineManager.StartCoroutine(WaitForRefresh());
return true;
}
private void UpdateServerList()
private IEnumerable<object> WaitForRefresh()
{
waitingForRefresh = true;
if (refreshDisableTimer > DateTime.Now)
{
yield return new WaitForSeconds((float)(refreshDisableTimer - DateTime.Now).TotalSeconds);
}
//CoroutineManager.StartCoroutine(UpdateServerList());
CoroutineManager.StartCoroutine(SendMasterServerRequest());
waitingForRefresh = false;
refreshDisableTimer = DateTime.Now + AllowedRefreshInterval;
yield return Status.Success;
}
private void UpdateServerList(string masterServerData)
{
serverList.ClearChildren();
string masterServerData = GetMasterServerData();
//string masterServerData = GetMasterServerData();
if (string.IsNullOrWhiteSpace(masterServerData))
{
@@ -96,6 +150,7 @@ namespace Subsurface
if (masterServerData.Substring(0,5).ToLower()=="error")
{
DebugConsole.ThrowError("Error while connecting to master server ("+masterServerData+")!");
return;
}
@@ -112,23 +167,33 @@ namespace Subsurface
string gameStarted = (arguments.Length > 3) ? arguments[3] : "";
string playerCountStr = (arguments.Length > 4) ? arguments[4] : "";
string hasPassWordStr = (arguments.Length > 5) ? arguments[5] : "";
var serverFrame = new GUIFrame(new Rectangle(0,0,0,20), (i%2 == 0) ? Color.Transparent : Color.White*0.2f, null, serverList);
serverFrame.UserData = IP+":"+port;
serverFrame.HoverColor = Color.Gold * 0.2f;
serverFrame.SelectedColor = Color.Gold * 0.5f;
var nameText = new GUITextBlock(new Rectangle(0,0,0,0), serverName, GUI.style, serverFrame);
var passwordBox = new GUITickBox(new Rectangle(columnX[0]/2, 0, 20, 20), "", Alignment.TopLeft, serverFrame);
passwordBox.Selected = hasPassWordStr == "1";
passwordBox.Enabled = false;
passwordBox.UserData = "password";
var nameText = new GUITextBlock(new Rectangle(columnX[0], 0, 0, 0), serverName, GUI.style, serverFrame);
int playerCount, maxPlayers;
playerCount = GameClient.ByteToPlayerCount((byte)int.Parse(playerCountStr), out maxPlayers);
var playerCountText = new GUITextBlock(new Rectangle(0, 0, 0, 0), playerCount+"/"+maxPlayers, GUI.style, Alignment.Left, Alignment.TopCenter, serverFrame);
var gameStartedText = new GUITextBlock(new Rectangle(0, 0, 0, 0), gameStarted=="1" ? "Yes" : "No", GUI.style, Alignment.Left, Alignment.TopRight, serverFrame);
var playerCountText = new GUITextBlock(new Rectangle(columnX[1], 0, 0, 0), playerCount + "/" + maxPlayers, GUI.style, serverFrame);
var gameStartedBox = new GUITickBox(new Rectangle(columnX[2] + (columnX[3] - columnX[2])/ 2, 0, 20, 20), "", Alignment.TopLeft, serverFrame);
gameStartedBox.Selected = gameStarted == "1";
gameStartedBox.Enabled = false;
}
}
private string GetMasterServerData()
private IEnumerable<object> SendMasterServerRequest()
{
RestClient client = null;
try
@@ -137,10 +202,11 @@ namespace Subsurface
}
catch (Exception e)
{
DebugConsole.ThrowError("Error while connecting to master server", e);
return "";
DebugConsole.ThrowError("Error while connecting to master server", e);
}
if (client == null) yield return Status.Success;
var request = new RestRequest("masterserver.php", Method.GET);
request.AddParameter("gamename", "subsurface"); // adds to POST or URL querystring based on Method
@@ -154,17 +220,44 @@ namespace Subsurface
//request.AddFile(path);
// execute the request
RestResponse response = (RestResponse)client.Execute(request);
masterServerResponded = false;
var restRequestHandle = client.ExecuteAsync(request, response => MasterServerCallBack(response));
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 8);
while (!masterServerResponded)
{
if (DateTime.Now > timeOut)
{
serverList.ClearChildren();
restRequestHandle.Abort();
DebugConsole.ThrowError("Couldn't connect to master server (request timed out)");
}
yield return Status.Running;
}
yield return Status.Success;
}
private void MasterServerCallBack(IRestResponse response)
{
masterServerResponded = true;
if (response.ErrorException!=null)
{
serverList.ClearChildren();
DebugConsole.ThrowError("Error while connecting to master server", response.ErrorException);
return;
}
if (response.StatusCode!= System.Net.HttpStatusCode.OK)
{
serverList.ClearChildren();
DebugConsole.ThrowError("Error while connecting to master server (" +response.StatusCode+": "+response.StatusDescription+")");
return "";
return;
}
return response.Content; // raw content as string
UpdateServerList(response.Content);
}
private bool JoinServer(GUIButton button, object obj)
@@ -183,12 +276,41 @@ namespace Subsurface
return false;
}
Game1.NetworkMember = new GameClient(clientNameBox.Text);
Game1.Client.ConnectToServer(ip);
CoroutineManager.StartCoroutine(JoinServer(ip));
return true;
}
private IEnumerable<object> JoinServer(string ip)
{
string selectedPassword = "";
if ((serverList.Selected.GetChild("password") as GUITickBox).Selected)
{
var msgBox = new GUIMessageBox("Password required", "");
var passwordBox = new GUITextBox(new Rectangle(0,0,150,20), Alignment.BottomCenter, GUI.style, msgBox);
passwordBox.UserData = "password";
var okButton = msgBox.GetChild<GUIButton>();
while (GUIMessageBox.MessageBoxes.Contains(msgBox))
{
okButton.Enabled = !string.IsNullOrWhiteSpace(passwordBox.Text);
yield return Status.Running;
}
selectedPassword = passwordBox.Text;
}
Game1.NetworkMember = new GameClient(clientNameBox.Text);
Game1.Client.ConnectToServer(ip, selectedPassword);
Game1.NetLobbyScreen.Select();
yield return Status.Success;
}
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
{
graphics.Clear(Color.CornflowerBlue);
@@ -208,6 +330,8 @@ namespace Subsurface
public override void Update(double deltaTime)
{
menu.Update((float)deltaTime);
GUI.Update((float)deltaTime);

View File

@@ -155,7 +155,7 @@ namespace Subsurface
if (startDrone!=null)
{
if (!SoundManager.IsPlaying(startDrone.AlBufferId))
if (!startDrone.IsPlaying)
{
startDrone.Remove();
startDrone = null;

View File

@@ -19,6 +19,8 @@ namespace Subsurface
private OggSound oggSound;
string filePath;
private int alSourceId;
//public float Volume
@@ -71,7 +73,8 @@ namespace Subsurface
public int Play(float volume = 1.0f)
{
return SoundManager.Play(this, volume);
alSourceId = SoundManager.Play(this, volume);
return alSourceId;
}
public int Play(float baseVolume, float range, Vector2 position)
@@ -83,7 +86,9 @@ namespace Subsurface
Vector2 relativePos = GetRelativePosition(position);
float volume = GetVolume(relativePos, range, baseVolume);
return SoundManager.Play(this, relativePos, volume, volume);
alSourceId = SoundManager.Play(this, relativePos, volume, volume);
return alSourceId;
//if (newIndex == -1) return -1;
@@ -96,7 +101,9 @@ namespace Subsurface
//bodyPosition.Y = -bodyPosition.Y;
return Play(volume, range, ConvertUnits.ToDisplayUnits(body.Position));
alSourceId = Play(volume, range, ConvertUnits.ToDisplayUnits(body.Position));
return alSourceId;
}
private float GetVolume(Vector2 relativePosition, float range, float baseVolume)
@@ -178,6 +185,14 @@ namespace Subsurface
}
public bool IsPlaying
{
get
{
return SoundManager.IsPlaying(alSourceId);
}
}
//public int Loop(float volume = 1.0f)
//{
// return SoundManager.Loop(this, volume);

View File

@@ -38,7 +38,7 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x64</PlatformTarget>
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Windows\Release\</OutputPath>

View File

@@ -1,3 +1,19 @@
---------------------------------------------------------------------------------------------------------
v0.1.2
---------------------------------------------------------------------------------------------------------
Multiplayer:
- a "lobby screen" showing a list of servers that are currently running
- password protected servers
- traitor rounds end when the traitor dies/disconnects or if the submarine reaches the end of the level
Items:
- fixed the crashing when firing the railgun or activating a detonator
Other:
- optimized lightning and "line of sight" rendering
- an unfinished tutorial which can currently only be accessed by entering "tutorial" into the
debug console
---------------------------------------------------------------------------------------------------------
v0.1.1

Binary file not shown.

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file contains an xml description of a font, and will be read by the XNA
Framework Content Pipeline. Follow the comments to customize the appearance
of the font in your game, and to change the characters which are available to draw
with.
-->
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
<Asset Type="Graphics:FontDescription">
<FontName>Verdana</FontName>
<Size>16</Size>
<Spacing>0</Spacing>
<UseKerning>true</UseKerning>
<Style>Bold</Style>
<DefaultCharacter>_</DefaultCharacter>
<!--
CharacterRegions control what letters are available in the font. Every
character from Start to End will be built and made available for drawing. The
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
character set. The characters are ordered according to the Unicode standard.
See the documentation for more information.
-->
<CharacterRegions>
<CharacterRegion>
<Start>&#32;</Start>
<End>&#126;</End>
</CharacterRegion>
<CharacterRegion>
<Start>&#192;</Start>
<End>&#601;</End>
</CharacterRegion>
</CharacterRegions>
</Asset>
</XnaContent>