Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Fixer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,6 @@ private static void TestPwMatchMaker()
{
var server = new global::ZkLobbyServer.ZkLobbyServer("", new PlanetwarsEventCreator());
var mm = server.PlanetWarsMatchMaker;
mm.AttackerSideCounter = 1;
mm.GenerateLobbyCommand();

// simulate defend phase with a formed squad
Expand Down
35 changes: 34 additions & 1 deletion Shared/LobbyClient/Protocol/Messages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,11 @@ public enum ModeType
Defend = 2
}

public string AttackerFaction { get; set; }
/// <summary>
/// Distinct attacker faction shortcuts across all <see cref="Options"/>. In parallel-turn PW every
/// faction can be attacking simultaneously; each option also carries its own <see cref="VoteOption.AttackerFaction"/>.
/// </summary>
public List<string> AttackerFactions { get; set; }

public DateTime Deadline { get; set; }

Expand All @@ -690,6 +694,7 @@ public PwMatchCommand(ModeType mode)
Mode = mode;
Options = new List<VoteOption>();
DefenderFactions = new List<string>();
AttackerFactions = new List<string>();
}

public class VoteOption
Expand All @@ -705,32 +710,60 @@ public class VoteOption
public bool CanSelectForBattle { get; set; }
public bool PlayerIsAttacker { get; set; }
public bool PlayerIsDefender { get; set; }
/// <summary>
/// Faction shortcut of the attacker. Together with <see cref="PlanetID"/> forms the (planet, attacker)
/// key that identifies this attack slot. Clients must echo it back in <see cref="PwJoinPlanet"/>.
/// </summary>
public string AttackerFaction { get; set; }
/// <summary>Average PW-WHR of the projected attacker squad (top-TeamSize volunteers). 0 when none.</summary>
public int AttackerAvgWhr { get; set; }
/// <summary>Average PW-WHR of the projected defender squad. Null in AttackCollect phase or when no volunteers.</summary>
public int? DefenderAvgWhr { get; set; }
/// <summary>Attacker win chance 0-100 derived from WHR delta. Null when either side is empty.</summary>
public int? WinChance { get; set; }
}
}

[Message(Origin.Client)]
public class PwJoinPlanet
{
public int PlanetID { get; set; }
/// <summary>
/// Which attack slot the player is interacting with. Required — a planet can be attacked by multiple
/// factions simultaneously, each a separate slot. For an attacker this should equal the user's own
/// faction; for a defender it identifies which incoming attack to defend against.
/// </summary>
public string AttackerFaction { get; set; }
}

/// <summary>
/// Client → server: cancel the player's current attack or defense commitment for the cycle.
/// </summary>
[Message(Origin.Client)]
public class PwCancel
{
}

[Message(Origin.Server)]
public class PwRequestJoinPlanet
{
public int PlanetID { get; set; }
public string AttackerFaction { get; set; }
}


[Message(Origin.Server)]
public class PwJoinPlanetSuccess
{
public int PlanetID { get; set; }
public string AttackerFaction { get; set; }
}

[Message(Origin.Server)]
public class PwAttackingPlanet
{
public int PlanetID { get; set; }
public string AttackerFaction { get; set; }
}

[Message(Origin.Client)]
Expand Down
14 changes: 8 additions & 6 deletions Zero-K.info/Controllers/PlanetwarsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -797,10 +797,11 @@ public ActionResult MatchMakerAttack(int planetID)
{
var db = new ZkDataContext();
var planet = db.Planets.Single(x => x.PlanetID == planetID);
if (Global.IsAccountAuthorized && Global.Account.CanPlayerPlanetWars() && planet.CanMatchMakerPlay(db.CurrentAccount().Faction))
var account = db.CurrentAccount();
if (Global.IsAccountAuthorized && Global.Account.CanPlayerPlanetWars() && account?.FactionID != null && planet.CanMatchMakerPlay(account.Faction))
{
Global.Server.PlanetWarsMatchMaker.AddAttackOption(planet);
Global.Server.RequestJoinPlanet(Global.Account.Name, planet.PlanetID);
Global.Server.PlanetWarsMatchMaker.AddAttackOption(planet, account.FactionID.Value);
Global.Server.RequestJoinPlanet(Global.Account.Name, planet.PlanetID, account.Faction.Shortcut);
}
return RedirectToAction("Planet", new { id = planetID });
}
Expand All @@ -812,16 +813,17 @@ public ActionResult MatchMaker()
var pwm = Global.Server.PlanetWarsMatchMaker;
if (pwm != null)
{
var state = Global.Server.PlanetWarsMatchMaker.GenerateLobbyCommand();
// admin view gets a per-viewer command so per-option flags render correctly
var state = Global.Server.PlanetWarsMatchMaker.GenerateLobbyCommand(Global.Account?.Name, Global.Account?.Faction?.Shortcut);
if (state != null) return View("PwMatchMaker", state);
}
return Content("Match maker offline");
}

[Auth]
public ActionResult MatchMakerJoin(int planetID)
public ActionResult MatchMakerJoin(int planetID, string attackerFaction)
{
Global.Server.RequestJoinPlanet(Global.Account.Name, planetID);
Global.Server.RequestJoinPlanet(Global.Account.Name, planetID, attackerFaction);
return MatchMaker();
}

Expand Down
2 changes: 1 addition & 1 deletion Zero-K.info/Views/Planetwars/Planet.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
</tr>
</table>

@if (Global.IsAccountAuthorized && db.CurrentAccount().CanPlayerPlanetWars() && (Global.Server.PlanetWarsMatchMaker != null && Global.Server?.PlanetWarsMatchMaker?.AttackingFaction?.FactionID == Global.FactionID) && Model.CanMatchMakerPlay(db.CurrentAccount().Faction))
@if (Global.IsAccountAuthorized && db.CurrentAccount().CanPlayerPlanetWars() && Global.Server.PlanetWarsMatchMaker != null && Global.Server.PlanetWarsMatchMaker.Phase == ZeroKWeb.PwPhase.AttackCollect && Model.OwnerFactionID != Global.FactionID && Model.CanMatchMakerPlay(db.CurrentAccount().Faction))
{
<a href="@Url.Action("MatchMakerAttack", "Planetwars", new { planetID = Model.PlanetID })">ATTACK PLANET</a>
}
Expand Down
27 changes: 17 additions & 10 deletions Zero-K.info/Views/Planetwars/PwMatchMaker.cshtml
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
@using LobbyClient
@using LobbyClient
@using PlasmaShared
@using ZeroKWeb
@using ZkData
@model LobbyClient.PwMatchCommand
@{
PwMatchCommand pw = Model;
string text = "";
string text;
var db = new ZkDataContext();
if (pw.Mode == PwMatchCommand.ModeType.Attack)
{
text = string.Format("{0} picks a planet to attack", pw.AttackerFaction);
text = "Pick a planet to attack";
}
else
{
var planetNames = string.Join(", ", pw.Options.Select(o => o.PlanetName));
text = string.Format("{0} attacks {2}, {1} defends", pw.AttackerFaction, string.Join(",", pw.DefenderFactions), planetNames);
var planetNames = string.Join(", ", pw.Options.Select(o => o.PlanetName + " (" + (o.AttackerFaction ?? "?") + ")"));
text = string.Format("Defend options: {0}", planetNames);
}

bool canClick = (pw.Mode == PwMatchCommand.ModeType.Attack && pw.AttackerFaction == Global.Account.Faction.Shortcut) || (pw.Mode == PwMatchCommand.ModeType.Defend && pw.DefenderFactions.Contains(Global.Account.Faction.Shortcut));
}

<div id="matchMaker">
Expand All @@ -30,14 +28,23 @@
foreach (PwMatchCommand.VoteOption opt in pw.Options)
{
<span style="border: 1px solid cyan;">
@if (canClick)
@if (opt.CanSelectForBattle)
{
@Ajax.ActionLink("Join", "MatchMakerJoin", new { planetID = opt.PlanetID }, new AjaxOptions { UpdateTargetId = "matchMaker", InsertionMode = InsertionMode.Replace })
@Ajax.ActionLink("Join", "MatchMakerJoin", new { planetID = opt.PlanetID, attackerFaction = opt.AttackerFaction }, new AjaxOptions { UpdateTargetId = "matchMaker", InsertionMode = InsertionMode.Replace })
}
@Html.PrintPlanet(db.Planets.First(x => x.PlanetID == opt.PlanetID))
<span>[@opt.AttackerFaction]</span>
<span>[@opt.Count/@opt.Needed]</span>
@if (opt.WinChance != null)
{
<span>(WHR A:@opt.AttackerAvgWhr D:@opt.DefenderAvgWhr, @opt.WinChance% attacker)</span>
}
else if (opt.AttackerAvgWhr > 0)
{
<span>(WHR @opt.AttackerAvgWhr)</span>
}
</span>
<text>&nbsp; &nbsp;&nbsp;</text>
}
}
</div>
</div>
9 changes: 6 additions & 3 deletions ZeroKLobby/Notifications/PwBar.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using LobbyClient;
Expand Down Expand Up @@ -59,9 +60,11 @@ void UpdateGui()
deadline = DateTime.Now.AddSeconds(pw.DeadlineSeconds);
timerLabel.Text = PlasmaShared.Utils.PrintTimeRemaining(pw.DeadlineSeconds);

var attackerFactionsText = string.Join(",", pw.AttackerFactions ?? new List<string>());

if (pw.Mode == PwMatchCommand.ModeType.Attack)
{
headerLabel.Text = string.Format("{0} picks a planet to attack", pw.AttackerFaction);
headerLabel.Text = string.Format("{0} picks a planet to attack", attackerFactionsText);

foreach (Button c in pnl.Controls.OfType<Button>().ToList()) pnl.Controls.Remove(c);

Expand All @@ -72,7 +75,7 @@ void UpdateGui()
var but = new Button { Text = string.Format("{0} [{1}/{2}]", opt.PlanetName, opt.Count, opt.Needed), AutoSize = true };
Program.ToolTip.SetMap(but, opt.Map);

if (pw.AttackerFaction == tas.MyUser.Faction) // NOTE this is for cases where nightwatch self faction info is delayed
if (pw.AttackerFactions != null && pw.AttackerFactions.Contains(tas.MyUser.Faction))
{
AddButtonClick(opt, but);
}
Expand All @@ -83,7 +86,7 @@ void UpdateGui()
else if (pw.Mode == PwMatchCommand.ModeType.Defend)
{
headerLabel.Text = string.Format("{0} attacks, {1} defends",
pw.AttackerFaction,
attackerFactionsText,
string.Join(",", pw.DefenderFactions));

foreach (Button c in pnl.Controls.OfType<Button>().ToList()) pnl.Controls.Remove(c);
Expand Down
5 changes: 5 additions & 0 deletions ZkLobbyServer/ConnectedUser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ public async Task Process(PwJoinPlanet args)
await server.PlanetWarsMatchMaker.OnJoinPlanet(this, args);
}

public async Task Process(PwCancel args)
{
await server.PlanetWarsMatchMaker.OnCancel(this);
}


public async Task Process(KickFromBattle batKick)
{
Expand Down
Loading
Loading