Can now start a game and disconnect from lobby without triggering a reload.

It is now possible to crash the game by starting a new server before the previous one has had time to timeout and release the port binding (the previous loadscreen pause meant this was always hidden).
This commit is contained in:
Paul Chote
2011-05-06 23:18:26 +12:00
parent 03264fa2ca
commit 6cb0cb7d0e
9 changed files with 590 additions and 19 deletions

View File

@@ -101,6 +101,18 @@ namespace OpenRA
return Widget.OpenWindow(widget, new Dictionary<string,object>{{ "world", world }, { "orderManager", orderManager }, { "worldRenderer", worldRenderer }}); return Widget.OpenWindow(widget, new Dictionary<string,object>{{ "world", world }, { "orderManager", orderManager }, { "worldRenderer", worldRenderer }});
} }
// Who came up with the great idea of making these things
// impossible for the things that want them to access them directly?
public static Widget OpenWindow(string widget, Dictionary<string, object> args)
{
return Widget.OpenWindow(widget, new Dictionary<string,object>(args)
{
{ "world", worldRenderer.world },
{ "orderManager", orderManager },
{ "worldRenderer", worldRenderer },
});
}
static ActionQueue afterTickActions = new ActionQueue(); static ActionQueue afterTickActions = new ActionQueue();
public static void RunAfterTick(Action a) { afterTickActions.Add(a); } public static void RunAfterTick(Action a) { afterTickActions.Add(a); }
@@ -317,18 +329,26 @@ namespace OpenRA
AddChatLine(Color.White, "Debug", String.Format(s,args)); AddChatLine(Color.White, "Debug", String.Format(s,args));
} }
// TODO: Fix ra relying on this behavior, then make this sane
public static void Disconnect() public static void Disconnect()
{
DisconnectOnly();
var shellmap = ChooseShellmap();
StartGame(shellmap);
}
public static void DisconnectOnly()
{ {
if (orderManager.world != null) if (orderManager.world != null)
orderManager.world.traitDict.PrintReport(); orderManager.world.traitDict.PrintReport();
if (IsHost && server != null) if (IsHost && server != null)
{
Console.WriteLine("Closing server");
server.Shutdown(); server.Shutdown();
}
orderManager.Dispose();
var shellmap = ChooseShellmap();
JoinLocal(); JoinLocal();
StartGame(shellmap); orderManager.Dispose();
} }
public static T CreateObject<T>( string name ) public static T CreateObject<T>( string name )

View File

@@ -111,6 +111,7 @@ namespace OpenRA.Server
if (shutdown) if (shutdown)
break; break;
} }
Console.WriteLine("Server loop finished");
GameStarted = false; GameStarted = false;
foreach (var t in ServerTraits.WithInterface<INotifyServerShutdown>()) foreach (var t in ServerTraits.WithInterface<INotifyServerShutdown>())

View File

@@ -30,17 +30,62 @@ namespace OpenRA.Mods.Cnc.Widgets
public static ColorRamp CurrentColorPreview; public static ColorRamp CurrentColorPreview;
// Must be set only once on game start
// TODO: This is stupid
static bool staticSetup;
public static void GameStartingStub()
{
var panel = Widget.RootWidget.GetWidget("SERVER_LOBBY");
// The panel may not be open anymore
if (panel == null)
return;
var lobbyLogic = panel.DelegateObject as CncLobbyLogic;
if (lobbyLogic == null)
return;
lobbyLogic.onGameStart();
}
public static void UpdateCurrentMapStub()
{
var panel = Widget.RootWidget.GetWidget("SERVER_LOBBY");
// The panel may not be open anymore
if (panel == null)
return;
var lobbyLogic = panel.DelegateObject as CncLobbyLogic;
if (lobbyLogic == null)
return;
lobbyLogic.UpdateCurrentMap();
}
readonly Action onGameStart;
readonly OrderManager orderManager; readonly OrderManager orderManager;
readonly WorldRenderer worldRenderer; readonly WorldRenderer worldRenderer;
[ObjectCreator.UseCtor] [ObjectCreator.UseCtor]
internal CncLobbyLogic([ObjectCreator.Param( "widget" )] Widget lobby, internal CncLobbyLogic([ObjectCreator.Param( "widget" )] Widget lobby,
[ObjectCreator.Param] OrderManager orderManager, [ObjectCreator.Param] OrderManager orderManager,
[ObjectCreator.Param] Action onExit,
[ObjectCreator.Param] Action onStart,
[ObjectCreator.Param] WorldRenderer worldRenderer) [ObjectCreator.Param] WorldRenderer worldRenderer)
{ {
this.orderManager = orderManager; this.orderManager = orderManager;
this.worldRenderer = worldRenderer; this.worldRenderer = worldRenderer;
this.onGameStart = onStart;
if (!staticSetup)
{
staticSetup = true;
Game.LobbyInfoChanged += UpdateCurrentMapStub;
Game.BeforeGameStart += GameStartingStub;
}
Game.LobbyInfoChanged += UpdateCurrentMap;
UpdateCurrentMap(); UpdateCurrentMap();
CurrentColorPreview = Game.Settings.Player.ColorRamp; CurrentColorPreview = Game.Settings.Player.ColorRamp;
@@ -103,9 +148,7 @@ namespace OpenRA.Mods.Cnc.Widgets
var disconnectButton = lobby.GetWidget("DISCONNECT_BUTTON"); var disconnectButton = lobby.GetWidget("DISCONNECT_BUTTON");
disconnectButton.OnMouseUp = mi => disconnectButton.OnMouseUp = mi =>
{ {
Game.Disconnect(); onExit();
Widget.CloseWindow();
Widget.LoadWidget("MENU_BACKGROUND");
return true; return true;
}; };

View File

@@ -51,8 +51,7 @@ namespace OpenRA.Mods.Cnc.Widgets
multiplayerMenu.GetWidget("JOIN_BUTTON").OnMouseUp = mi => multiplayerMenu.GetWidget("JOIN_BUTTON").OnMouseUp = mi =>
{ {
Menu = MenuType.None; Menu = MenuType.None;
Widget.OpenWindow("SERVERBROWSER_PANEL", Widget.OpenWindow("SERVERBROWSER_PANEL", new Dictionary<string, object>()
new Dictionary<string, object>()
{ {
{"onExit", new Action(() => {Menu = MenuType.Multiplayer; Widget.CloseWindow();})} {"onExit", new Action(() => {Menu = MenuType.Multiplayer; Widget.CloseWindow();})}
}); });
@@ -77,6 +76,28 @@ namespace OpenRA.Mods.Cnc.Widgets
settings.Server.ListenPort = 1234; settings.Server.ListenPort = 1234;
settings.Server.ExternalPort = 1234; settings.Server.ExternalPort = 1234;
Game.CreateAndJoinServer(settings, map); Game.CreateAndJoinServer(settings, map);
Menu = MenuType.None;
Game.OpenWindow("SERVER_LOBBY", new Dictionary<string, object>()
{
// Returning to main menu
{"onExit", new Action(() =>
{
Game.DisconnectOnly();
Menu = MenuType.Main;
Widget.CloseWindow();
})
},
// Starting a game: remove all shellmap ui
{"onStart", new Action(() =>
{
Widget.CloseWindow();
Widget.RootWidget.RemoveChild(Widget.RootWidget.GetWidget("MENU_BACKGROUND"));
})
}
});
} }
} }
} }

View File

@@ -36,13 +36,14 @@ namespace OpenRA.Mods.RA.Widgets.Delegates
{ {
if (Info.InstallMode == "cnc") if (Info.InstallMode == "cnc")
{ {
/*
Game.ConnectionStateChanged += orderManager => Game.ConnectionStateChanged += orderManager =>
{ {
Widget.CloseWindow(); Widget.CloseWindow();
switch (orderManager.Connection.ConnectionState) switch (orderManager.Connection.ConnectionState)
{ {
case ConnectionState.PreConnecting: case ConnectionState.PreConnecting:
Widget.OpenWindow("MENU_BACKGROUND"); Widget.LoadWidget("MENU_BACKGROUND");
break; break;
case ConnectionState.Connecting: case ConnectionState.Connecting:
Widget.OpenWindow("CONNECTING_BG", Widget.OpenWindow("CONNECTING_BG",
@@ -62,6 +63,7 @@ namespace OpenRA.Mods.RA.Widgets.Delegates
break; break;
} }
}; };
*/
} }
else else
{ {

482
mods/cnc/chrome/ingame.yaml Normal file
View File

@@ -0,0 +1,482 @@
Container@INGAME_ROOT:
Id:INGAME_ROOT
Delegate:IngameChromeDelegate
Children:
WorldInteractionController:
Id:INTERACTION_CONTROLLER
X:0
Y:0
Width:WINDOW_RIGHT
Height:WINDOW_BOTTOM
ViewportScrollController:
X:0
Y:0
Width:WINDOW_RIGHT
Height:WINDOW_BOTTOM
WorldCommand:
X:0
Y:0
Width:WINDOW_RIGHT
Height:WINDOW_BOTTOM
Timer@GAME_TIMER:
Id:GAME_TIMER
X: WINDOW_RIGHT/2
Y: 10
StrategicProgress@STRATEGIC_PROGRESS:
Id:STRATEGIC_PROGRESS
X: WINDOW_RIGHT/2
Y: 40
Background@POSTGAME_BG:
Id:POSTGAME_BG
X:(WINDOW_RIGHT - WIDTH)/2
Y:(WINDOW_BOTTOM - HEIGHT)/2
Width:400
Height:100
Background:dialog4
Visible:false
Children:
Label@TEXT:
Id:TEXT
X:(PARENT_RIGHT - WIDTH)/2
Y:(PARENT_BOTTOM - HEIGHT)/2
Width:200
Height:40
Align:Center
Bold:True
SpecialPowerBin@INGAME_POWERS_BIN:
Id:INGAME_POWERS_BIN
X:0
Y:25
BuildPalette@INGAME_BUILD_PALETTE:
Id:INGAME_BUILD_PALETTE
X:WINDOW_RIGHT - 250
Y:280
Width:250
Height:500
TabClick: button.aud
BuildPaletteOpen: appear1.aud
BuildPaletteClose: appear1.aud
Button@INGAME_OPTIONS_BUTTON:
Id:INGAME_OPTIONS_BUTTON
X:0
Y:0
Width:160
Height:25
Text:Options
Bold:True
Button@INGAME_DIPLOMACY_BUTTON:
Id:INGAME_DIPLOMACY_BUTTON
X:162
Y:0
Width:160
Height:25
Text:Diplomacy
Bold:True
Button@INGAME_DEVELOPERMODE_BUTTON:
Id:INGAME_DEVELOPERMODE_BUTTON
X:324
Y:0
Width:160
Height:25
Text:Developer Mode
Visible:false
Bold:True
RadarBin@INGAME_RADAR_BIN:
Id:INGAME_RADAR_BIN
WorldInteractionController:INTERACTION_CONTROLLER
PowerBin@INGAME_POWER_BIN:
Id:INGAME_POWER_BIN
MoneyBin@INGAME_MONEY_BIN:
Id:INGAME_MONEY_BIN
X:WINDOW_RIGHT - WIDTH
Y:0
Width:320
Height: 32
SplitOreAndCash: yes
Children:
OrderButton@SELL:
Id:SELL
Delegate:OrderButtonsChromeDelegate
X:39
Y:0
Width:30
Height:30
Image:sell
Description:Sell
LongDesc:Sell buildings, reclaiming a \nproportion of their build cost
OrderButton@REPAIR:
Id:REPAIR
Delegate:OrderButtonsChromeDelegate
X:75
Y:0
Width:30
Height:30
Image:repair
Description:Repair
LongDesc:Repair damaged buildings
WorldTooltip:
Background@INGAME_OPTIONS_BG:
Id:INGAME_OPTIONS_BG
X:(WINDOW_RIGHT - WIDTH)/2
Y:(WINDOW_BOTTOM - HEIGHT)/2
Width:300
Height:320
Visible:false
Children:
Label@LABEL_TITLE:
Id:LABEL_TITLE
X:(PARENT_RIGHT - WIDTH)/2
Y:20
Width:250
Height:25
Text:Options
Align:Center
Bold:True
Button@RESUME:
Id:RESUME
X:(PARENT_RIGHT - WIDTH)/2
Y:60
Width:160
Height:25
Text:Resume
Bold:True
Button@SETTINGS:
Id:SETTINGS
X:(PARENT_RIGHT - WIDTH)/2
Y:100
Width:160
Height:25
Text:Settings
Bold:True
Button@MUSIC:
Id:MUSIC
X:(PARENT_RIGHT - WIDTH)/2
Y:140
Width:160
Height:25
Text:Music
Bold:True
Button@SURRENDER:
Id:SURRENDER
X:(PARENT_RIGHT - WIDTH)/2
Y:180
Width:160
Height:25
Text:Surrender
Bold:True
Button@DISCONNECT:
Id:DISCONNECT
X:(PARENT_RIGHT - WIDTH)/2
Y:220
Width:160
Height:25
Text:Disconnect
Bold:True
Button@QUIT:
Id:QUIT
X:(PARENT_RIGHT - WIDTH)/2
Y:260
Width:160
Height:25
Text:Quit
Bold:True
Background@DIPLOMACY_BG:
Id:DIPLOMACY_BG
Delegate:DiplomacyDelegate
X:(WINDOW_RIGHT - WIDTH)/2
Y:(WINDOW_BOTTOM - HEIGHT)/2
Width:450
Height:400
Visible:false
Children:
Label@LABEL_TITLE:
Id:LABEL_TITLE
X:(PARENT_RIGHT - WIDTH)/2
Y:20
Width:250
Height:25
Text:Diplomacy
Align:Center
Bold:True
ChatDisplay@CHAT_DISPLAY:
Id:CHAT_DISPLAY
X:250
Y:WINDOW_BOTTOM - HEIGHT - 30
Width: 760
Height: 200
DrawBackground: False
RemoveTime:250
UseContrast: yes
ChatEntry@CHAT_ENTRY:
Id:CHAT_ENTRY
X:250
Y:WINDOW_BOTTOM - HEIGHT
Width: 760
Height: 30
UseContrast: yes
Background@DEVELOPERMODE_BG:
Id:DEVELOPERMODE_BG
Delegate:DeveloperModeDelegate
X:(WINDOW_RIGHT - WIDTH)/2
Y:(WINDOW_BOTTOM - HEIGHT)/2
Width:350
Height:370
Visible:false
Children:
Label@LABEL_TITLE:
Id:LABEL_TITLE
X:(PARENT_RIGHT - WIDTH)/2
Y:20
Width:250
Height:25
Text:Developer Mode
Align:Center
Checkbox@CHECKBOX_SHROUD
Id:CHECKBOX_SHROUD
X:30
Y:50
Height:20
Width:PARENT_RIGHT - 30
Text:Disable Shroud
Button@GIVE_EXPLORATION
Id:GIVE_EXPLORATION
X:30
Y:80
Width:200
Height:20
Text: Give Exploration
Checkbox@CHECKBOX_PATHDEBUG:
Id:CHECKBOX_PATHDEBUG
X:30
Y:110
Width:PARENT_RIGHT - 30
Height:20
Text:Show Unit Paths
Button@GIVE_CASH
Id:GIVE_CASH
X:30
Y:140
Width:200
Height:20
Text: Give Cash
Checkbox@INSTANT_BUILD
Id:INSTANT_BUILD
X:30
Y:170
Width:PARENT_RIGHT - 30
Height:20
Text:Instant Build Speed
Checkbox@INSTANT_CHARGE
Id:INSTANT_CHARGE
X:30
Y:200
Width:PARENT_RIGHT - 30
Height:20
Text:Instant Charge Time (Special Powers)
Checkbox@ENABLE_TECH
Id:ENABLE_TECH
X:30
Y:230
Width:PARENT_RIGHT - 30
Height:20
Text:Build Everything
Checkbox@UNLIMITED_POWER
Id:UNLIMITED_POWER
X:30
Y:260
Width:PARENT_RIGHT - 30
Height:20
Text:Unlimited Power
Checkbox@BUILD_ANYWHERE
Id:BUILD_ANYWHERE
X:30
Y:290
Width:PARENT_RIGHT - 30
Height:20
Text:Build Anywhere
Background@PERF_BG:
ClickThrough:true
Id:PERF_BG
Background:dialog4
Delegate:PerfDebugDelegate
X:10
Y:WINDOW_BOTTOM - 250
Width: 210
Height: 250
Children:
PerfGraph@GRAPH:
Id:GRAPH
X:5
Y:5
Width:200
Height:200
Label@TEXT:
Id:TEXT
Bold: false
X:20
Y:205
Width:170
Height:40
Container@OBSERVER_ROOT:
Id:OBSERVER_ROOT
Visible:true
Delegate:IngameObserverChromeDelegate
Children:
WorldInteractionController:
X:0
Y:0
Width:WINDOW_RIGHT
Height:WINDOW_BOTTOM
ViewportScrollController:
X:0
Y:0
Width:WINDOW_RIGHT
Height:WINDOW_BOTTOM
Timer@GAME_TIMER:
Id:GAME_TIMER
X: WINDOW_RIGHT/2
Y: 10
Background@POSTGAME_BG:
Id:POSTGAME_BG
X:(WINDOW_RIGHT - WIDTH)/2
Y:(WINDOW_BOTTOM - HEIGHT)/2
Width:400
Height:100
Background:dialog4
Visible:false
Children:
Label@TEXT:
Id:TEXT
X:(PARENT_RIGHT - WIDTH)/2
Y:(PARENT_BOTTOM - HEIGHT)/2
Width:200
Height:40
Align:Center
Bold:True
SpecialPowerBin@INGAME_POWERS_BIN:
Id:INGAME_POWERS_BIN
X:0
Y:25
Button@INGAME_OPTIONS_BUTTON:
Id:INGAME_OPTIONS_BUTTON
X:0
Y:0
Width:160
Height:25
Text:Options
Bold:True
WorldTooltip:
Background@INGAME_OPTIONS_BG:
Id:INGAME_OPTIONS_BG
X:(WINDOW_RIGHT - WIDTH)/2
Y:(WINDOW_BOTTOM - HEIGHT)/2
Width:300
Height:320
Visible:false
Children:
Label@LABEL_TITLE:
Id:LABEL_TITLE
X:(PARENT_RIGHT - WIDTH)/2
Y:20
Width:250
Height:25
Text:Options
Align:Center
Bold:True
Button@RESUME:
Id:RESUME
X:(PARENT_RIGHT - WIDTH)/2
Y:60
Width:160
Height:25
Text:Resume
Bold:True
Button@SETTINGS:
Id:SETTINGS
X:(PARENT_RIGHT - WIDTH)/2
Y:100
Width:160
Height:25
Text:Settings
Bold:True
Button@MUSIC:
Id:MUSIC
X:(PARENT_RIGHT - WIDTH)/2
Y:140
Width:160
Height:25
Text:Music
Bold:True
Button@SURRENDER:
Id:SURRENDER
X:(PARENT_RIGHT - WIDTH)/2
Y:180
Width:160
Height:25
Text:Surrender
Bold:True
Button@DISCONNECT:
Id:DISCONNECT
X:(PARENT_RIGHT - WIDTH)/2
Y:220
Width:160
Height:25
Text:Disconnect
Bold:True
Button@QUIT:
Id:QUIT
X:(PARENT_RIGHT - WIDTH)/2
Y:260
Width:160
Height:25
Text:Quit
Bold:True
ChatDisplay@CHAT_DISPLAY:
Id:CHAT_DISPLAY
X:250
Y:WINDOW_BOTTOM - HEIGHT - 30
Width: 760
Height: 200
DrawBackground: False
RemoveTime:250
ChatEntry@CHAT_ENTRY:
Id:CHAT_ENTRY
X:250
Y:WINDOW_BOTTOM - HEIGHT
Width: 760
Height: 30
Background@PERF_BG:
ClickThrough:true
Id:PERF_BG
Background:dialog4
Delegate:PerfDebugDelegate
X:10
Y:WINDOW_BOTTOM - 250
Width: 210
Height: 250
Children:
PerfGraph@GRAPH:
Id:GRAPH
X:5
Y:5
Width:200
Height:200
Label@TEXT:
Id:TEXT
Bold: false
X:20
Y:205
Width:170
Height:40
Background@FMVPLAYER:
Id:FMVPLAYER
Width:WINDOW_RIGHT
Height:WINDOW_BOTTOM
Background:dialog4
Children:
VqaPlayer:
Id:PLAYER
X:0
Y:0
Width:WINDOW_RIGHT
Height:WINDOW_BOTTOM

View File

@@ -1014,6 +1014,7 @@ Rules:
-CrateSpawner: -CrateSpawner:
CncShellmapScript: CncShellmapScript:
DesaturatedPaletteEffect: DesaturatedPaletteEffect:
-OpenWidgetAtGameStart:
LST: LST:
Mobile: Mobile:
Speed: 3 Speed: 3

View File

@@ -64,6 +64,7 @@ ChromeLayout:
mods/cnc/chrome/serverbrowser.yaml mods/cnc/chrome/serverbrowser.yaml
mods/cnc/chrome/directconnect.yaml mods/cnc/chrome/directconnect.yaml
mods/cnc/chrome/lobby.yaml mods/cnc/chrome/lobby.yaml
mods/cnc/chrome/ingame.yaml
Weapons: Weapons:
mods/cnc/weapons.yaml mods/cnc/weapons.yaml

View File

@@ -44,9 +44,9 @@ Player:
SurrenderOnDisconnect: SurrenderOnDisconnect:
World: World:
# OpenWidgetAtGameStart: OpenWidgetAtGameStart:
# Widget: INGAME_ROOT Widget: INGAME_ROOT
# ObserverWidget: OBSERVER_ROOT ObserverWidget: OBSERVER_ROOT
ScreenShaker: ScreenShaker:
NukePaletteEffect: NukePaletteEffect:
CncWaterPaletteRotation: CncWaterPaletteRotation: