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:
@@ -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"
|
||||
|
||||
@@ -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")]
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -246,6 +246,9 @@ namespace Subsurface
|
||||
hull.OxygenPercentage = 100.0f;
|
||||
}
|
||||
break;
|
||||
case "tutorial":
|
||||
TutorialMode.Start();
|
||||
break;
|
||||
case "lobbyscreen":
|
||||
case "lobby":
|
||||
Game1.LobbyScreen.Select();
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -27,6 +27,14 @@ namespace Subsurface
|
||||
|
||||
private bool enabled;
|
||||
|
||||
public GUIComponent Selected
|
||||
{
|
||||
get
|
||||
{
|
||||
return selected;
|
||||
}
|
||||
}
|
||||
|
||||
public object SelectedData
|
||||
{
|
||||
get
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
//}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -155,7 +155,7 @@ namespace Subsurface
|
||||
|
||||
if (startDrone!=null)
|
||||
{
|
||||
if (!SoundManager.IsPlaying(startDrone.AlBufferId))
|
||||
if (!startDrone.IsPlaying)
|
||||
{
|
||||
startDrone.Remove();
|
||||
startDrone = null;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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.
@@ -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> </Start>
|
||||
<End>~</End>
|
||||
</CharacterRegion>
|
||||
|
||||
<CharacterRegion>
|
||||
<Start>À</Start>
|
||||
<End>ə</End>
|
||||
</CharacterRegion>
|
||||
</CharacterRegions>
|
||||
</Asset>
|
||||
</XnaContent>
|
||||
Reference in New Issue
Block a user