- Modified item buying logic: selected items are purchased immediately without having to click the "buy" button, and they stay in the list of purchased items until the round is started. (-> It's possible to see which items have been purchased and cancel purchases).

- Clients can be given a permission to manage the campaign (atm selecting which location to head towards and buying items).
- Syncing cargomanager state with clients.
- Misc fixes.
This commit is contained in:
Joonas Rikkonen
2017-09-17 15:55:24 +03:00
parent b292a301cf
commit 9114ae658f
13 changed files with 271 additions and 151 deletions
@@ -1,7 +1,5 @@
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using System;
using System.Xml.Linq;
namespace Barotrauma namespace Barotrauma
{ {
@@ -29,7 +29,7 @@ namespace Barotrauma
bool gameOver = gameSession.CrewManager.characters.All(c => c.IsDead); bool gameOver = gameSession.CrewManager.characters.All(c => c.IsDead);
bool progress = Submarine.MainSub.AtEndPosition; bool progress = Submarine.MainSub.AtEndPosition;
GUIFrame frame = new GUIFrame(new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.Black * 0.8f); GUIFrame frame = new GUIFrame(new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.Black * 0.8f, null);
int width = 760, height = 400; int width = 760, height = 400;
GUIFrame innerFrame = new GUIFrame(new Rectangle(0, 0, width, height), null, Alignment.Center, "", frame); GUIFrame innerFrame = new GUIFrame(new Rectangle(0, 0, width, height), null, Alignment.Center, "", frame);
@@ -44,9 +44,13 @@ namespace Barotrauma
{ {
selectedConnection = connection; selectedConnection = connection;
selectedLocation = highlightedLocation; selectedLocation = highlightedLocation;
OnLocationSelected?.Invoke(selectedLocation, selectedConnection); //clients aren't allowed to select the location without a permission
//GameMain.LobbyScreen.SelectLocation(highlightedLocation, connection); if (GameMain.Client == null || GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign))
{
OnLocationSelected?.Invoke(selectedLocation, selectedConnection);
GameMain.Client?.SendCampaignState();
}
} }
} }
@@ -54,6 +58,7 @@ namespace Barotrauma
if (PlayerInput.DoubleClicked() && highlightedLocation != null) if (PlayerInput.DoubleClicked() && highlightedLocation != null)
{ {
currentLocation = highlightedLocation; currentLocation = highlightedLocation;
OnLocationChanged?.Invoke(currentLocation);
} }
#endif #endif
} }
@@ -1312,6 +1312,24 @@ namespace Barotrauma.Networking
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered); client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
} }
public void SendCampaignState()
{
MultiplayerCampaign campaign = GameMain.GameSession.GameMode as MultiplayerCampaign;
if (campaign == null)
{
DebugConsole.ThrowError("Failed send campaign state to the server (no campaign active).\n" + Environment.StackTrace);
return;
}
NetOutgoingMessage msg = client.CreateMessage();
msg.Write((byte)ClientPacketHeader.SERVER_COMMAND);
msg.Write((byte)ClientPermissions.ManageCampaign);
campaign.ClientWrite(msg);
msg.Write((byte)ServerNetObject.END_OF_MESSAGE);
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
}
public void RequestRoundEnd() public void RequestRoundEnd()
{ {
NetOutgoingMessage msg = client.CreateMessage(); NetOutgoingMessage msg = client.CreateMessage();
@@ -24,10 +24,8 @@ namespace Barotrauma
private CampaignMode campaign; private CampaignMode campaign;
private GUIFrame previewFrame; private GUIFrame characterPreviewFrame;
private GUIButton buyButton;
private Level selectedLevel; private Level selectedLevel;
private float mapZoom = 3.0f; private float mapZoom = 3.0f;
@@ -44,27 +42,7 @@ namespace Barotrauma
{ {
get { return campaign; } get { return campaign; }
} }
private string CostTextGetter()
{
return "Cost: " + selectedItemCost.ToString() + " credits";
}
private int selectedItemCost
{
get
{
int cost = 0;
foreach (GUIComponent child in selectedItemList.children)
{
MapEntityPrefab ep = child.UserData as MapEntityPrefab;
if (ep == null) continue;
cost += ep.Price;
}
return cost;
}
}
public CampaignUI(CampaignMode campaign, GUIFrame container) public CampaignUI(CampaignMode campaign, GUIFrame container)
{ {
this.campaign = campaign; this.campaign = campaign;
@@ -107,16 +85,10 @@ namespace Barotrauma
int sellColumnWidth = (tabs[(int)Tab.Store].Rect.Width - 40) / 2 - 20; int sellColumnWidth = (tabs[(int)Tab.Store].Rect.Width - 40) / 2 - 20;
selectedItemList = new GUIListBox(new Rectangle(0, 30, sellColumnWidth, tabs[(int)Tab.Store].Rect.Height - 80), Color.White * 0.7f, "", tabs[(int)Tab.Store]); selectedItemList = new GUIListBox(new Rectangle(0, 30, sellColumnWidth, tabs[(int)Tab.Store].Rect.Height - 80), Color.White * 0.7f, "", tabs[(int)Tab.Store]);
selectedItemList.OnSelected = DeselectItem; selectedItemList.OnSelected = SellItem;
var costText = new GUITextBlock(new Rectangle(0, 0, 100, 25), "Cost: ", "", Alignment.BottomLeft, Alignment.TopLeft, tabs[(int)Tab.Store]);
costText.TextGetter = CostTextGetter;
buyButton = new GUIButton(new Rectangle(selectedItemList.Rect.Width - 100, 0, 100, 25), "Buy", Alignment.Bottom, "", tabs[(int)Tab.Store]);
buyButton.OnClicked = BuyItems;
storeItemList = new GUIListBox(new Rectangle(0, 30, sellColumnWidth, tabs[(int)Tab.Store].Rect.Height - 80), Color.White * 0.7f, Alignment.TopRight, "", tabs[(int)Tab.Store]); storeItemList = new GUIListBox(new Rectangle(0, 30, sellColumnWidth, tabs[(int)Tab.Store].Rect.Height - 80), Color.White * 0.7f, Alignment.TopRight, "", tabs[(int)Tab.Store]);
storeItemList.OnSelected = SelectItem; storeItemList.OnSelected = BuyItem;
int x = storeItemList.Rect.X - storeItemList.Parent.Rect.X; int x = storeItemList.Rect.X - storeItemList.Parent.Rect.X;
@@ -140,11 +112,21 @@ namespace Barotrauma
SelectTab(Tab.Map); SelectTab(Tab.Map);
GameMain.GameSession.Map.OnLocationSelected += SelectLocation; UpdateLocationTab(campaign.Map.CurrentLocation);
campaign.Map.OnLocationSelected += SelectLocation;
campaign.Map.OnLocationChanged += (location) => UpdateLocationTab(location);
campaign.CargoManager.OnItemsChanged += RefreshItemTab;
} }
private void UpdateLocationTab(Location location) private void UpdateLocationTab(Location location)
{ {
if (characterPreviewFrame != null)
{
characterPreviewFrame.Parent.RemoveChild(characterPreviewFrame);
characterPreviewFrame = null;
}
if (location.HireManager == null) if (location.HireManager == null)
{ {
hireList.ClearChildren(); hireList.ClearChildren();
@@ -173,7 +155,7 @@ namespace Barotrauma
{ {
mapZoom += PlayerInput.ScrollWheelSpeed / 1000.0f; mapZoom += PlayerInput.ScrollWheelSpeed / 1000.0f;
mapZoom = MathHelper.Clamp(mapZoom, 1.0f, 4.0f); mapZoom = MathHelper.Clamp(mapZoom, 1.0f, 4.0f);
if (GameMain.GameSession?.Map != null) if (GameMain.GameSession?.Map != null)
{ {
GameMain.GameSession.Map.Update(deltaTime, new Rectangle( GameMain.GameSession.Map.Update(deltaTime, new Rectangle(
@@ -186,29 +168,14 @@ namespace Barotrauma
public void Draw(SpriteBatch spriteBatch) public void Draw(SpriteBatch spriteBatch)
{ {
/*if (characterList.CountChildren != CrewManager.CharacterInfos.Count) if (selectedTab == Tab.Map && GameMain.GameSession?.Map != null)
{ {
UpdateCharacterLists(); GameMain.GameSession.Map.Draw(spriteBatch, new Rectangle(
tabs[(int)selectedTab].Rect.X + 20,
tabs[(int)selectedTab].Rect.Y + 20,
tabs[(int)selectedTab].Rect.Width - 310,
tabs[(int)selectedTab].Rect.Height - 40), mapZoom);
} }
spriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, GameMain.ScissorTestEnable);
*/
if (selectedTab == Tab.Map && GameMain.GameSession?.Map != null)
{
GameMain.GameSession.Map.Draw(spriteBatch, new Rectangle(
tabs[(int)selectedTab].Rect.X + 20,
tabs[(int)selectedTab].Rect.Y + 20,
tabs[(int)selectedTab].Rect.Width - 310,
tabs[(int)selectedTab].Rect.Height - 40), mapZoom);
}
/*if (topPanel.UserData as Location != GameMain.GameSession.Map.CurrentLocation)
{
UpdateLocationTab(GameMain.GameSession.Map.CurrentLocation);
}
spriteBatch.End();*/
} }
public void UpdateCharacterLists() public void UpdateCharacterLists()
@@ -220,6 +187,34 @@ namespace Barotrauma
} }
} }
public void SelectLocation(Location location, LocationConnection connection)
{
GUIComponent locationPanel = tabs[(int)Tab.Map].GetChild("selectedlocation");
if (locationPanel != null) tabs[(int)Tab.Map].RemoveChild(locationPanel);
locationPanel = new GUIFrame(new Rectangle(0, 0, 250, 190), Color.Transparent, Alignment.TopRight, null, tabs[(int)Tab.Map]);
locationPanel.UserData = "selectedlocation";
if (location == null) return;
var titleText = new GUITextBlock(new Rectangle(0, 0, 250, 0), location.Name, "", Alignment.TopLeft, Alignment.TopCenter, locationPanel, true, GUI.LargeFont);
if (GameMain.GameSession.Map.SelectedConnection != null && GameMain.GameSession.Map.SelectedConnection.Mission != null)
{
var mission = GameMain.GameSession.Map.SelectedConnection.Mission;
new GUITextBlock(new Rectangle(0, titleText.Rect.Height + 20, 0, 20), "Mission: " + mission.Name, "", locationPanel);
new GUITextBlock(new Rectangle(0, titleText.Rect.Height + 40, 0, 20), "Reward: " + mission.Reward + " credits", "", locationPanel);
new GUITextBlock(new Rectangle(0, titleText.Rect.Height + 70, 0, 0), mission.Description, "", Alignment.TopLeft, Alignment.TopLeft, locationPanel, true, GUI.SmallFont);
}
if (startButton != null) startButton.Enabled = true;
selectedLevel = connection.Level;
OnLocationSelected?.Invoke(location, connection);
}
private void CreateItemFrame(MapEntityPrefab ep, GUIListBox listBox, int width) private void CreateItemFrame(MapEntityPrefab ep, GUIListBox listBox, int width)
{ {
@@ -255,82 +250,49 @@ namespace Barotrauma
Alignment.TopLeft, "", frame); Alignment.TopLeft, "", frame);
textBlock.Font = font; textBlock.Font = font;
textBlock.ToolTip = ep.Description; textBlock.ToolTip = ep.Description;
} }
private bool SelectItem(GUIComponent component, object obj) private bool BuyItem(GUIComponent component, object obj)
{ {
MapEntityPrefab prefab = obj as MapEntityPrefab; ItemPrefab prefab = obj as ItemPrefab;
if (prefab == null) return false; if (prefab == null) return false;
CreateItemFrame(prefab, selectedItemList, selectedItemList.Rect.Width); if (GameMain.Client != null && !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign))
{
return false;
}
buyButton.Enabled = campaign.Money >= selectedItemCost; if (prefab.Price > campaign.Money) return false;
campaign.CargoManager.PurchaseItem(prefab);
GameMain.Client?.SendCampaignState();
return false; return false;
} }
private bool DeselectItem(GUIComponent component, object obj) private bool SellItem(GUIComponent component, object obj)
{ {
MapEntityPrefab prefab = obj as MapEntityPrefab; ItemPrefab prefab = obj as ItemPrefab;
if (prefab == null) return false; if (prefab == null) return false;
selectedItemList.RemoveChild(selectedItemList.children.Find(c => c.UserData == obj)); if (GameMain.Client != null && !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign))
{
return false;
}
campaign.CargoManager.SellItem(prefab);
GameMain.Client?.SendCampaignState();
return false; return false;
} }
private void RefreshItemTab()
public void SelectLocation(Location location, LocationConnection connection)
{ {
GUIComponent locationPanel = tabs[(int)Tab.Map].GetChild("selectedlocation"); selectedItemList.ClearChildren();
foreach (ItemPrefab ip in campaign.CargoManager.PurchasedItems)
if (locationPanel != null) tabs[(int)Tab.Map].RemoveChild(locationPanel);
locationPanel = new GUIFrame(new Rectangle(0, 0, 250, 190), Color.Transparent, Alignment.TopRight, null, tabs[(int)Tab.Map]);
locationPanel.UserData = "selectedlocation";
if (location == null) return;
var titleText = new GUITextBlock(new Rectangle(0, 0, 250, 0), location.Name, "", Alignment.TopLeft, Alignment.TopCenter, locationPanel, true, GUI.LargeFont);
if (GameMain.GameSession.Map.SelectedConnection != null && GameMain.GameSession.Map.SelectedConnection.Mission != null)
{ {
var mission = GameMain.GameSession.Map.SelectedConnection.Mission; CreateItemFrame(ip, selectedItemList, selectedItemList.Rect.Width);
new GUITextBlock(new Rectangle(0, titleText.Rect.Height + 20, 0, 20), "Mission: " + mission.Name, "", locationPanel);
new GUITextBlock(new Rectangle(0, titleText.Rect.Height + 40, 0, 20), "Reward: " + mission.Reward + " credits", "", locationPanel);
new GUITextBlock(new Rectangle(0, titleText.Rect.Height + 70, 0, 0), mission.Description, "", Alignment.TopLeft, Alignment.TopLeft, locationPanel, true, GUI.SmallFont);
} }
if (startButton != null) startButton.Enabled = true;
selectedLevel = connection.Level;
OnLocationSelected?.Invoke(location, connection);
}
private bool BuyItems(GUIButton button, object obj)
{
int cost = selectedItemCost;
if (campaign.Money < cost) return false;
campaign.Money -= cost;
for (int i = selectedItemList.children.Count - 1; i >= 0; i--)
{
GUIComponent child = selectedItemList.children[i];
ItemPrefab ip = child.UserData as ItemPrefab;
if (ip == null) continue;
campaign.CargoManager.AddItem(ip);
selectedItemList.RemoveChild(child);
}
return false;
} }
public void SelectTab(Tab tab) public void SelectTab(Tab tab)
@@ -373,7 +335,7 @@ namespace Barotrauma
return true; return true;
} }
private string GetMoney() public string GetMoney()
{ {
return "Money: " + ((GameMain.GameSession == null) ? "0" : string.Format(CultureInfo.InvariantCulture, "{0:N0}", campaign.Money)) + " credits"; return "Money: " + ((GameMain.GameSession == null) ? "0" : string.Format(CultureInfo.InvariantCulture, "{0:N0}", campaign.Money)) + " credits";
} }
@@ -398,22 +360,23 @@ namespace Barotrauma
if (Character.Controlled != null && characterInfo == Character.Controlled.Info) return false; if (Character.Controlled != null && characterInfo == Character.Controlled.Info) return false;
if (previewFrame == null || previewFrame.UserData != characterInfo) if (characterPreviewFrame == null || characterPreviewFrame.UserData != characterInfo)
{ {
int width = Math.Min(300, tabs[(int)Tab.Crew].Rect.Width - hireList.Rect.Width - characterList.Rect.Width - 50); int width = Math.Min(300, tabs[(int)Tab.Crew].Rect.Width - hireList.Rect.Width - characterList.Rect.Width - 50);
previewFrame = new GUIFrame(new Rectangle(0, 60, width, 300), characterPreviewFrame = new GUIFrame(new Rectangle(0, 60, width, 300),
new Color(0.0f, 0.0f, 0.0f, 0.8f), new Color(0.0f, 0.0f, 0.0f, 0.8f),
Alignment.TopCenter, "", tabs[(int)selectedTab]); Alignment.TopCenter, "", tabs[(int)selectedTab]);
previewFrame.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f); characterPreviewFrame.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
previewFrame.UserData = characterInfo; characterPreviewFrame.UserData = characterInfo;
characterInfo.CreateInfoFrame(previewFrame); characterInfo.CreateInfoFrame(characterPreviewFrame);
} }
if (component.Parent == hireList) if (component.Parent == hireList)
{ {
GUIButton hireButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Hire", Alignment.BottomCenter, "", previewFrame); GUIButton hireButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Hire", Alignment.BottomCenter, "", characterPreviewFrame);
hireButton.Enabled = campaign.Money >= characterInfo.Salary;
hireButton.UserData = characterInfo; hireButton.UserData = characterInfo;
hireButton.OnClicked = HireCharacter; hireButton.OnClicked = HireCharacter;
} }
@@ -423,15 +386,22 @@ namespace Barotrauma
private bool HireCharacter(GUIButton button, object selection) private bool HireCharacter(GUIButton button, object selection)
{ {
/*CharacterInfo characterInfo = selection as CharacterInfo; CharacterInfo characterInfo = selection as CharacterInfo;
if (characterInfo == null) return false; if (characterInfo == null) return false;
if (campaign.TryHireCharacter(GameMain.GameSession.Map.CurrentLocation.HireManager, characterInfo)) SinglePlayerCampaign spCampaign = campaign as SinglePlayerCampaign;
if (spCampaign == null)
{
DebugConsole.ThrowError("Characters can only be hired in the single player campaign.\n" + Environment.StackTrace);
return false;
}
if (spCampaign.TryHireCharacter(GameMain.GameSession.Map.CurrentLocation.HireManager, characterInfo))
{ {
UpdateLocationTab(GameMain.GameSession.Map.CurrentLocation); UpdateLocationTab(GameMain.GameSession.Map.CurrentLocation);
SelectCharacter(null, null); SelectCharacter(null, null);
}*/ UpdateCharacterLists();
}
return false; return false;
} }
@@ -20,6 +20,11 @@ namespace Barotrauma
get { return GameMain.GameSession.CrewManager; } get { return GameMain.GameSession.CrewManager; }
} }
public string GetMoney()
{
return campaignUI == null ? "" : campaignUI.GetMoney();
}
public LobbyScreen() public LobbyScreen()
{ {
Rectangle panelRect = new Rectangle( Rectangle panelRect = new Rectangle(
@@ -37,7 +42,7 @@ namespace Barotrauma
GUITextBlock moneyText = new GUITextBlock(new Rectangle(0, 0, 0, 25), "", "", GUITextBlock moneyText = new GUITextBlock(new Rectangle(0, 0, 0, 25), "", "",
Alignment.BottomLeft, Alignment.BottomLeft, topPanel); Alignment.BottomLeft, Alignment.BottomLeft, topPanel);
//moneyText.TextGetter = GetMoney; moneyText.TextGetter = GetMoney;
GUIButton button = new GUIButton(new Rectangle(-240, 0, 100, 30), "Map", null, Alignment.BottomRight, "", topPanel); GUIButton button = new GUIButton(new Rectangle(-240, 0, 100, 30), "Map", null, Alignment.BottomRight, "", topPanel);
button.UserData = CampaignUI.Tab.Map; button.UserData = CampaignUI.Tab.Map;
@@ -1022,16 +1022,14 @@ namespace Barotrauma
menu.Draw(spriteBatch); menu.Draw(spriteBatch);
if (jobInfoFrame != null) jobInfoFrame.Draw(spriteBatch); if (jobInfoFrame != null) jobInfoFrame.Draw(spriteBatch);
//if (previewPlayer!=null) previewPlayer.Draw(spriteBatch);
if (playerFrame != null) playerFrame.Draw(spriteBatch);
if (campaignContainer.Visible && campaignUI != null) if (campaignContainer.Visible && campaignUI != null)
{ {
campaignUI.Draw(spriteBatch); campaignUI.Draw(spriteBatch);
} }
if (playerFrame != null) playerFrame.Draw(spriteBatch);
GUI.Draw((float)deltaTime, spriteBatch, null); GUI.Draw((float)deltaTime, spriteBatch, null);
spriteBatch.End(); spriteBatch.End();
@@ -1180,6 +1178,9 @@ namespace Barotrauma
}; };
buttonX += 110; buttonX += 110;
} }
var moneyText = new GUITextBlock(new Rectangle(120,0,200,20), "Money", "", Alignment.BottomLeft, Alignment.TopLeft, campaignContainer);
moneyText.TextGetter = campaignUI.GetMoney;
} }
modeList.Select(2, true); modeList.Select(2, true);
} }
@@ -1,20 +1,56 @@
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
namespace Barotrauma namespace Barotrauma
{ {
class CargoManager class CargoManager
{ {
private List<ItemPrefab> purchasedItems; private readonly List<ItemPrefab> purchasedItems;
private readonly CampaignMode campaign;
public Action OnItemsChanged;
public List<ItemPrefab> PurchasedItems
{
get { return purchasedItems; }
}
public CargoManager() public CargoManager(CampaignMode campaign)
{ {
purchasedItems = new List<ItemPrefab>(); purchasedItems = new List<ItemPrefab>();
this.campaign = campaign;
} }
public void AddItem(ItemPrefab item) public void SetPurchasedItems(List<ItemPrefab> items)
{ {
purchasedItems.Clear();
purchasedItems.AddRange(items);
OnItemsChanged?.Invoke();
}
public void PurchaseItem(ItemPrefab item)
{
campaign.Money -= item.Price;
purchasedItems.Add(item); purchasedItems.Add(item);
OnItemsChanged?.Invoke();
}
public void SellItem(ItemPrefab item)
{
campaign.Money += item.Price;
purchasedItems.Remove(item);
OnItemsChanged?.Invoke();
}
public int GetTotalItemCost()
{
return purchasedItems.Sum(i => i.Price);
} }
public void CreateItems() public void CreateItems()
@@ -35,7 +35,7 @@ namespace Barotrauma
: base(preset, param) : base(preset, param)
{ {
Money = InitialMoney; Money = InitialMoney;
CargoManager = new CargoManager(); CargoManager = new CargoManager(this);
} }
public void GenerateMap(string seed) public void GenerateMap(string seed)
@@ -69,12 +69,11 @@ namespace Barotrauma
GameMain.GameSession = new GameSession(new Submarine(sub.FilePath, ""), saveName, GameModePreset.list.Find(g => g.Name == "Campaign")); GameMain.GameSession = new GameSession(new Submarine(sub.FilePath, ""), saveName, GameModePreset.list.Find(g => g.Name == "Campaign"));
var campaign = ((MultiplayerCampaign)GameMain.GameSession.GameMode); var campaign = ((MultiplayerCampaign)GameMain.GameSession.GameMode);
campaign.GenerateMap(mapSeed); campaign.GenerateMap(mapSeed);
campaign.map.OnLocationSelected += (loc, connection) => { campaign.LastUpdateID++; }; campaign.SetDelegates();
setupBox.Close(); setupBox.Close();
GameMain.NetLobbyScreen.ToggleCampaignMode(true); GameMain.NetLobbyScreen.ToggleCampaignMode(true);
SaveUtil.SaveGame(GameMain.GameSession.SavePath); SaveUtil.SaveGame(GameMain.GameSession.SavePath);
campaign.LastSaveID++; campaign.LastSaveID++;
}; };
@@ -105,9 +104,17 @@ namespace Barotrauma
return true; return true;
}; };
} }
#endif #endif
private void SetDelegates()
{
if (GameMain.Server != null)
{
CargoManager.OnItemsChanged += () => { LastUpdateID++; };
Map.OnLocationSelected += (loc, connection) => { LastUpdateID++; };
}
}
public override void Start() public override void Start()
{ {
base.Start(); base.Start();
@@ -186,6 +193,7 @@ namespace Barotrauma
if (!success) if (!success)
{ {
#if CLIENT
var summaryScreen = GUIMessageBox.VisibleBox; var summaryScreen = GUIMessageBox.VisibleBox;
if (summaryScreen != null) if (summaryScreen != null)
{ {
@@ -200,6 +208,7 @@ namespace Barotrauma
quitButton.OnClicked += GameMain.LobbyScreen.QuitToMainMenu; quitButton.OnClicked += GameMain.LobbyScreen.QuitToMainMenu;
quitButton.OnClicked += (GUIButton button, object obj) => { GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox); return true; }; quitButton.OnClicked += (GUIButton button, object obj) => { GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox); return true; };
} }
#endif
} }
} }
else else
@@ -232,9 +241,8 @@ namespace Barotrauma
campaign.map.SetLocation(ToolBox.GetAttributeInt(element, "currentlocation", 0)); campaign.map.SetLocation(ToolBox.GetAttributeInt(element, "currentlocation", 0));
} }
campaign.map.OnLocationSelected += (loc, connection) => { campaign.LastUpdateID++; }; campaign.SetDelegates();
//campaign.savedOnStart = true;
return campaign; return campaign;
} }
@@ -258,8 +266,15 @@ namespace Barotrauma
msg.Write(map.CurrentLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.CurrentLocationIndex); msg.Write(map.CurrentLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.CurrentLocationIndex);
msg.Write(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex); msg.Write(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex);
} msg.Write(Money);
msg.Write((UInt16)CargoManager.PurchasedItems.Count);
foreach (ItemPrefab ip in CargoManager.PurchasedItems)
{
msg.Write((UInt16)MapEntityPrefab.list.IndexOf(ip));
}
}
#if CLIENT #if CLIENT
public static void ClientRead(NetBuffer msg) public static void ClientRead(NetBuffer msg)
{ {
@@ -271,6 +286,16 @@ namespace Barotrauma
UInt16 currentLocIndex = msg.ReadUInt16(); UInt16 currentLocIndex = msg.ReadUInt16();
UInt16 selectedLocIndex = msg.ReadUInt16(); UInt16 selectedLocIndex = msg.ReadUInt16();
int money = msg.ReadInt32();
UInt16 purchasedItemCount = msg.ReadUInt16();
List<ItemPrefab> purchasedItems = new List<ItemPrefab>();
for (int i = 0; i<purchasedItemCount; i++)
{
UInt16 itemPrefabIndex = msg.ReadUInt16();
purchasedItems.Add(MapEntityPrefab.list[itemPrefabIndex] as ItemPrefab);
}
MultiplayerCampaign campaign = GameMain.GameSession?.GameMode as MultiplayerCampaign; MultiplayerCampaign campaign = GameMain.GameSession?.GameMode as MultiplayerCampaign;
if (campaign == null || mapSeed != campaign.Map.Seed) if (campaign == null || mapSeed != campaign.Map.Seed)
{ {
@@ -284,7 +309,7 @@ namespace Barotrauma
GameMain.NetLobbyScreen.ToggleCampaignMode(true); GameMain.NetLobbyScreen.ToggleCampaignMode(true);
if (NetIdUtils.IdMoreRecent(campaign.lastUpdateID, updateID)) return; if (NetIdUtils.IdMoreRecent(campaign.lastUpdateID, updateID)) return;
//server has a newer save file //server has a newer save file
if (NetIdUtils.IdMoreRecent(saveID, campaign.PendingSaveID)) if (NetIdUtils.IdMoreRecent(saveID, campaign.PendingSaveID))
{ {
@@ -305,10 +330,58 @@ namespace Barotrauma
{ {
campaign.Map.SetLocation(currentLocIndex == UInt16.MaxValue ? -1 : currentLocIndex); campaign.Map.SetLocation(currentLocIndex == UInt16.MaxValue ? -1 : currentLocIndex);
campaign.Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex); campaign.Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
campaign.Money = money;
campaign.CargoManager.SetPurchasedItems(purchasedItems);
campaign.lastUpdateID = updateID; campaign.lastUpdateID = updateID;
} }
} }
#endif #endif
public void ClientWrite(NetBuffer msg)
{
System.Diagnostics.Debug.Assert(map.Locations.Count < UInt16.MaxValue);
msg.Write(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex);
msg.Write((UInt16)CargoManager.PurchasedItems.Count);
foreach (ItemPrefab ip in CargoManager.PurchasedItems)
{
msg.Write((UInt16)MapEntityPrefab.list.IndexOf(ip));
}
}
public void ServerRead(NetBuffer msg, Client sender)
{
UInt16 selectedLocIndex = msg.ReadUInt16();
UInt16 purchasedItemCount = msg.ReadUInt16();
List<ItemPrefab> purchasedItems = new List<ItemPrefab>();
for (int i = 0; i < purchasedItemCount; i++)
{
UInt16 itemPrefabIndex = msg.ReadUInt16();
purchasedItems.Add(MapEntityPrefab.list[itemPrefabIndex] as ItemPrefab);
}
if (!sender.HasPermission(ClientPermissions.ManageCampaign))
{
DebugConsole.ThrowError("Client \""+sender.name+"\" does not have a permission to manage the campaign");
return;
}
Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
List<ItemPrefab> currentItems = new List<ItemPrefab>(CargoManager.PurchasedItems);
foreach (ItemPrefab ip in currentItems)
{
CargoManager.SellItem(ip);
}
foreach (ItemPrefab ip in purchasedItems)
{
CargoManager.PurchaseItem(ip);
}
}
} }
} }
@@ -29,6 +29,7 @@ namespace Barotrauma
private LocationConnection selectedConnection; private LocationConnection selectedConnection;
public Action<Location, LocationConnection> OnLocationSelected; public Action<Location, LocationConnection> OnLocationSelected;
public Action<Location> OnLocationChanged;
public Location CurrentLocation public Location CurrentLocation
{ {
@@ -350,6 +351,8 @@ namespace Barotrauma
currentLocation = selectedLocation; currentLocation = selectedLocation;
currentLocation.Discovered = true; currentLocation.Discovered = true;
selectedLocation = null; selectedLocation = null;
OnLocationChanged?.Invoke(currentLocation);
} }
public void SetLocation(int index) public void SetLocation(int index)
@@ -368,6 +371,8 @@ namespace Barotrauma
currentLocation = locations[index]; currentLocation = locations[index];
currentLocation.Discovered = true; currentLocation.Discovered = true;
OnLocationChanged?.Invoke(currentLocation);
} }
public void SelectLocation(int index) public void SelectLocation(int index)
@@ -15,7 +15,9 @@ namespace Barotrauma.Networking
[Description("Kick")] [Description("Kick")]
Kick = 2, Kick = 2,
[Description("Ban")] [Description("Ban")]
Ban = 4 Ban = 4,
[Description("Manage campaign")]
ManageCampaign = 8
} }
class Client class Client
@@ -748,7 +748,7 @@ namespace Barotrauma.Networking
if (!sender.HasPermission(command)) if (!sender.HasPermission(command))
{ {
Log("Client \""+sender.name+"\" sent a server command \""+command+"\". Permission denied.", ServerLog.MessageType.ServerMessage); Log("Client \"" + sender.name + "\" sent a server command \"" + command + "\". Permission denied.", ServerLog.MessageType.ServerMessage);
return; return;
} }
@@ -781,6 +781,13 @@ namespace Barotrauma.Networking
EndGame(); EndGame();
} }
break; break;
case ClientPermissions.ManageCampaign:
MultiplayerCampaign campaign = GameMain.GameSession.GameMode as MultiplayerCampaign;
if (campaign != null)
{
campaign.ServerRead(inc, sender);
}
break;
} }
inc.ReadPadBits(); inc.ReadPadBits();