Skip to content
Closed
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: 1 addition & 0 deletions C7/C7Game.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -310,4 +310,5 @@ current = true
[connection signal="BuildCity" from="CanvasLayer/PopupOverlay" to="." method="OnBuildCity"]
[connection signal="HidePopup" from="CanvasLayer/PopupOverlay" to="CanvasLayer/PopupOverlay" method="OnHidePopup"]
[connection signal="Quit" from="CanvasLayer/PopupOverlay" to="." method="OnQuitTheGame"]
[connection signal="SaveGame" from="CanvasLayer/PopupOverlay" to="." method="OnSaveGame"]
[connection signal="UnitDisbanded" from="CanvasLayer/PopupOverlay" to="." method="OnUnitDisbanded"]
39 changes: 26 additions & 13 deletions C7/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ public void processEngineMessages(GameData gameData)
case MsgStartTurn mST:
OnPlayerStartTurn();
break;

case MsgFinishedSave mFS:
PopupOverlay popupOverlay = GetNode<PopupOverlay>(PopupOverlay.NodePath);
popupOverlay.CloseCurrentPopup();
break;
}
}
}
Expand Down Expand Up @@ -358,29 +363,25 @@ public override void _UnhandledInput(InputEvent @event)
if(eventMouseButton.ButtonIndex == (int)ButtonList.Left)
{
GetTree().SetInputAsHandled();
if(eventMouseButton.IsPressed())
{
if(eventMouseButton.IsPressed()) {
if (inUnitGoToMode) {
setGoToMode(false);
using (var gameDataAccess = new UIGameDataAccess()) {
var tile = mapView.tileOnScreenAt(gameDataAccess.gameData.map, eventMouseButton.Position);
using (UIGameDataAccess gameDataAccess = new UIGameDataAccess()) {
Tile tile = mapView.tileOnScreenAt(gameDataAccess.gameData.map, eventMouseButton.Position);
if (tile != null) {
new MsgSetUnitPath(CurrentlySelectedUnit.guid, tile).send();
}
}
}
else
{
} else {
// Select unit on tile at mouse location
using (var gameDataAccess = new UIGameDataAccess()) {
var tile = mapView.tileOnScreenAt(gameDataAccess.gameData.map, eventMouseButton.Position);
using (UIGameDataAccess gameDataAccess = new UIGameDataAccess()) {
Tile tile = mapView.tileOnScreenAt(gameDataAccess.gameData.map, eventMouseButton.Position);
if (tile != null) {
MapUnit to_select = tile.unitsOnTile.Find(u => u.movementPoints.canMove);
if (to_select != null && to_select.owner == controller)
setSelectedUnit(to_select);
MapUnit toSelect = tile.unitsOnTile.Find(u => u.movementPoints.canMove);
if (toSelect != null && toSelect.owner == controller)
setSelectedUnit(toSelect);
}
}

OldPosition = eventMouseButton.Position;
IsMovingCamera = true;
}
Expand Down Expand Up @@ -458,6 +459,10 @@ public override void _UnhandledInput(InputEvent @event)
log.Debug("There is a " + CurrentlySelectedUnit.unitType.name + " selected; not ending turn");
}
}
else if (eventKeyDown.Scancode == (int)KeyList.S && eventKeyDown.Control)
{
OnSaveGame();
}
else if (eventKeyDown.Scancode == (int)Godot.KeyList.Space)
{
log.Verbose("Space pressed");
Expand Down Expand Up @@ -684,4 +689,12 @@ private void OnBuildCity(string name)
{
new MsgBuildCity(CurrentlySelectedUnit.guid, name).send();
}

private void OnSaveGame()
{
GD.Print("Saving Game...");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be convenient to print out the save file location here too, since we don't yet give the player the option to choose it. I ran this branch to test it and it was not obvious to me that the save file would overwrite c7-static-map-save.json.

string saveGamePath = Global.LoadGamePath;
new MsgSaveGame(saveGamePath).send();
}

}
2 changes: 1 addition & 1 deletion C7/GlobalSingleton.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ public void ResetLoadGamePath()
{
LoadGamePath = DefaultGamePath;
}
}
}
70 changes: 35 additions & 35 deletions C7/UIElements/Popups/GameMenu.cs
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
using Godot;

public class GameMenu : Popup
{

public GameMenu() {
alignment = BoxContainer.AlignMode.Center;
margins = new Margins(top: 100);
}

public override void _Ready()
{
base._Ready();

AddTexture(370, 300);
AddBackground(370, 300);

AddHeader("Main Menu", 10);

AddButton("Map", 60, "map");
AddButton("Load Game (Ctrl-L)", 85, "load");
AddButton("New Game (Ctrl-Shift-Q)", 110, "newGame");
AddButton("Preferences (Ctrl-P)", 135, "preferences");
AddButton("Retire (Ctrl-Q)", 160, "retire");
AddButton("Save Game (Ctrl-S)", 185, "save");
AddButton("Quit Game (ESC)", 210, "quit");
}

private void quit()
{
GetParent().EmitSignal("Quit");
}

private void map()
{
GetParent().EmitSignal("HidePopup");
}
public class GameMenu : Popup {

public GameMenu() {
alignment = BoxContainer.AlignMode.Center;
margins = new Margins(top: 100);
}

public override void _Ready() {
base._Ready();

AddTexture(370, 300);
AddBackground(370, 300);

AddHeader("Main Menu", 10);

AddButton("Map", 60, "map");
AddButton("Load Game (Ctrl-L)", 85, "load");
AddButton("New Game (Ctrl-Shift-Q)", 110, "newGame");
AddButton("Preferences (Ctrl-P)", 135, "preferences");
AddButton("Retire (Ctrl-Q)", 160, "retire");
AddButton("Save Game (Ctrl-S)", 185, "save");
AddButton("Quit Game (ESC)", 210, "quit");
}

private void map() {
GetParent().EmitSignal("HidePopup");
}

private void save() {
GetParent().EmitSignal("SaveGame");
}

private void quit() {
GetParent().EmitSignal("Quit");
}

}
7 changes: 7 additions & 0 deletions C7/UIElements/Popups/PopupOverlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class PopupOverlay : HBoxContainer

[Signal] public delegate void UnitDisbanded();
[Signal] public delegate void Quit();
[Signal] public delegate void SaveGame();
[Signal] public delegate void BuildCity(string name);
[Signal] public delegate void HidePopup();

Expand All @@ -29,6 +30,12 @@ public override void _Ready()
base._Ready();
}

public void CloseCurrentPopup() {
GD.Print("Closing popup");
RemoveChild(currentChild);
Hide();
}

private void OnHidePopup()
{
log.Debug("Hiding popup");
Expand Down
2 changes: 1 addition & 1 deletion C7/UIElements/RightClickMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ public void ResetItems(Tile tile, Dictionary<string, bool> uiUpdatedUnitStates =

public void SelectUnit(string guid) {
using (var gameDataAccess = new UIGameDataAccess()) {
MapUnit toSelect = gameDataAccess.gameData.mapUnits.Find(u => u.guid == guid);
MapUnit toSelect = gameDataAccess.gameData.GetUnit(guid);
if (toSelect != null && toSelect.owner == game.controller) {
game.setSelectedUnit(toSelect);
new MsgSetFortification(toSelect.guid, false).send();
Expand Down
2 changes: 1 addition & 1 deletion C7/Util.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public static string Civ3MediaPath(string mediaPath)
{
//First, check if the file exists via a scenario's mod path
//For now this is only checked relative to Civ3, not relative to C7.
if (modPath != "") {
if (!string.IsNullOrEmpty(modPath)) {
string[] paths = modPath.Split(";");
foreach (string path in paths) {
string[] tryPaths = new string[] {
Expand Down
2 changes: 1 addition & 1 deletion C7Engine/EngineStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static class EngineStorage

private static Thread engineThread = null;
internal static AutoResetEvent uiEvent = new AutoResetEvent(false); // Used to block engineThread while waiting for the UI, f.e. while
// an animation plays.
// an animation plays.

internal static ConcurrentQueue<MessageToEngine> pendingMessages = new ConcurrentQueue<MessageToEngine>();
internal static AutoResetEvent actionAddedToQueue = new AutoResetEvent(false);
Expand Down
27 changes: 22 additions & 5 deletions C7Engine/EntryPoints/CreateGame.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System.Linq;

namespace C7Engine
{
using System;
Expand All @@ -8,20 +10,35 @@ public class CreateGame
/**
* For now, I'm making the methods that the C7 client can call be static.
* We may want a different solution in the end, but this lets us start prototyping
* quickly. By keeping all the client-callable APIs in the EntryPoints folder,
* quickly. By keeping all the client-callable APIs in the EntryPoints folder,
* hopefully it won't be too much of a goose hunt to refactor it later if we decide to do so.
**/
public static Player createGame(string loadFilePath, string defaultBicPath)
{
EngineStorage.createThread();
EngineStorage.gameDataMutex.WaitOne();

C7SaveFormat save = SaveManager.LoadSave(loadFilePath, defaultBicPath);
C7SaveFormat save = SaveManager.Load(loadFilePath, defaultBicPath);

Player humanPlayer = null;
if (save.GameData.players.Count == 0) {
Console.WriteLine("creating dummy data...");
humanPlayer = save.GameData.CreateDummyGameData();
} else {
Console.WriteLine("loading player from save data...");
humanPlayer = save.GameData.players.Find(p => p.isHuman);
}

EngineStorage.gameData = save.GameData;
// Consider if we have any need to keep a reference to the save object handy...probably not

var humanPlayer = save.GameData.CreateDummyGameData();
EngineStorage.uiControllerID = humanPlayer.guid;
if (humanPlayer != null)
EngineStorage.uiControllerID = humanPlayer.guid;
else {
//This occurs when a game is saved in Observer Mode
//We still need this to be set for things like making sure the game doesn't autoplay forever in Observer Mode,
//and for now can assume the first player is the human
EngineStorage.uiControllerID = save.GameData.players.First().guid;
}
TurnHandling.OnBeginTurn(); // Call for the first turn
TurnHandling.AdvanceTurn();

Expand Down
22 changes: 16 additions & 6 deletions C7Engine/EntryPoints/MessageToEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ public override void process()
}
}

public class MsgSaveGame : MessageToEngine {
private string path;

public MsgSaveGame(string path) {
this.path = path;
}

public override void process() {
SaveManager.Save(path);
}
}

public class MsgSetFortification : MessageToEngine
{
private string unitGUID;
Expand All @@ -41,12 +53,10 @@ public override void process()

// Simply do nothing if we weren't given a valid GUID. TODO: Maybe this is an error we need to handle? In an MP game, we should reject
// invalid actions at the server level but at the client level an invalid action received from the server indicates a desync.
if (unit != null) {
if (fortifyElseWake)
unit.fortify();
else
unit.wake();
}
if (fortifyElseWake)
unit?.fortify();
else
unit?.wake();
}
}

Expand Down
2 changes: 2 additions & 0 deletions C7Engine/EntryPoints/MessageToUI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,6 @@ public MsgStartEffectAnimation(Tile tile, AnimatedEffect effect, AutoResetEvent

public class MsgStartTurn : MessageToUI {}

public class MsgFinishedSave : MessageToUI {}

}
41 changes: 18 additions & 23 deletions C7Engine/SaveManager.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
namespace C7Engine
{
namespace C7Engine {
using System.IO;
using C7GameData;

Expand All @@ -12,33 +11,24 @@ enum SaveFileFormat {

// The engine performs all save file creating, reading, and updating
// via the SaveManager
public static class SaveManager
{
private static SaveFileFormat getFileFormat(string path)
{
var ext = Path.GetExtension(path);
if (ext.Equals(".SAV", System.StringComparison.CurrentCultureIgnoreCase))
{
public static class SaveManager {
private static SaveFileFormat getFileFormat(string path) {
string ext = Path.GetExtension(path);
if (ext.Equals(".SAV", System.StringComparison.CurrentCultureIgnoreCase)) {
return SaveFileFormat.Sav;
}
else if (ext.Equals(".BIQ", System.StringComparison.CurrentCultureIgnoreCase))
{
} else if (ext.Equals(".BIQ", System.StringComparison.CurrentCultureIgnoreCase)) {
return SaveFileFormat.Biq;
}
else if (ext.Equals(".JSON", System.StringComparison.CurrentCultureIgnoreCase)
|| ext.Equals(".ZIP", System.StringComparison.CurrentCultureIgnoreCase))
{
} else if (ext.Equals(".JSON", System.StringComparison.CurrentCultureIgnoreCase)
|| ext.Equals(".ZIP", System.StringComparison.CurrentCultureIgnoreCase)) {
return SaveFileFormat.C7;
}
return SaveFileFormat.Invalid;
}

// Load and initialize a save
public static C7SaveFormat LoadSave(string path, string bicPath)
{
C7SaveFormat save = null;
switch (getFileFormat(path))
{
public static C7SaveFormat Load(string path, string bicPath) {
C7SaveFormat save;
switch (getFileFormat(path)) {
case SaveFileFormat.Sav:
save = ImportCiv3.ImportSav(path, bicPath);
break;
Expand All @@ -51,12 +41,17 @@ public static C7SaveFormat LoadSave(string path, string bicPath)
default:
throw new FileLoadException("invalid save format");
}
if (save.PostLoadProcess())
{
if (save.PostLoadProcess()) {
return save;
}
throw new FileLoadException("could not process save file");
}

public static void Save(string path) {
C7SaveFormat save = new C7SaveFormat(EngineStorage.gameData);
C7SaveFormat.Save(save, path);
new MsgFinishedSave().send();
}

}
}
4 changes: 3 additions & 1 deletion C7GameData/AIData/TileKnowledge.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace C7GameData
{
public class TileKnowledge
{
HashSet<Tile> knownTiles = new HashSet<Tile>();
//Public solely so System.Text.Json will serialize it.
public HashSet<Tile> knownTiles = new HashSet<Tile>();
HashSet<Tile> visibleTiles = new HashSet<Tile>();

public void AddTilesToKnown(Tile unitLocation) {
Expand Down
Loading