Fixed robot save mechanic to include nodes and their states.

This commit is contained in:
2026-06-28 14:00:11 +02:00
parent c29372ca51
commit c84fdf8a0b
10 changed files with 361 additions and 6 deletions
+28
View File
@@ -55,4 +55,32 @@ public class CraftNode : ProgramNode
{
return $"Name: {DisplayText}, Item: {(selectedItem == null ? "Empty" : selectedItem.data.Id)}, Amount: {amount}";
}
public override NodeSaveData CreateSaveData()
{
NodeSaveData saveData = base.CreateSaveData();
saveData.ItemId = selectedItem?.data.Id;
saveData.Amount = amount;
if (selectedItem != null)
{
saveData.ElapsedCraftTime = selectedItem.elapsedCraftTime;
saveData.AmountCrafted = selectedItem.amountCrafted;
}
return saveData;
}
public override void Load(NodeSaveData saveData)
{
base.Load(saveData);
amount = saveData.Amount;
if (string.IsNullOrEmpty(saveData.ItemId)) return;
if (!GameData.availableItems.ContainsKey(saveData.ItemId)) return;
selectedItem = new Item
{
data = GameData.availableItems[saveData.ItemId],
elapsedCraftTime = saveData.ElapsedCraftTime,
amountCrafted = saveData.AmountCrafted
};
}
}
+29 -2
View File
@@ -7,6 +7,7 @@ public class ExploreNode : ProgramNode
public Vector3 startPosition;
public Vector3I targetPosition;
public List<Vector3> pathPoints;
public bool hasTargetPosition;
public ExploreNode()
{
@@ -16,7 +17,7 @@ public class ExploreNode : ProgramNode
public override NodeResult Execute(Robot robot, double delta)
{
if (pathPoints == null && !TrySelectTarget())
if (pathPoints == null && !hasTargetPosition && !TrySelectTarget())
{
lastExecutionMessage = "No tiles left to explore";
return NodeResult.SUCCESS;
@@ -52,6 +53,7 @@ public class ExploreNode : ProgramNode
);
if (!GameData.map[targetPosition.Y].tiles[targetPosition.X, targetPosition.Z].wasVisited)
{
hasTargetPosition = true;
return true;
}
@@ -94,6 +96,7 @@ public class ExploreNode : ProgramNode
lastExecutionMessage = "Current exploration finished";
pathPoints = null;
hasTargetPosition = false;
return NodeResult.RUNNING;
}
@@ -119,7 +122,8 @@ public class ExploreNode : ProgramNode
{
return new ExploreNode
{
targetPosition = targetPosition
targetPosition = targetPosition,
hasTargetPosition = hasTargetPosition
};
}
@@ -127,4 +131,27 @@ public class ExploreNode : ProgramNode
{
return $"Name: {DisplayText}";
}
public override NodeSaveData CreateSaveData()
{
NodeSaveData saveData = base.CreateSaveData();
saveData.TargetX = targetPosition.X;
saveData.TargetY = targetPosition.Y;
saveData.TargetZ = targetPosition.Z;
saveData.HasTargetPosition = hasTargetPosition || pathPoints != null;
return saveData;
}
public override void Load(NodeSaveData saveData)
{
base.Load(saveData);
hasTargetPosition = saveData.HasTargetPosition;
if (!hasTargetPosition) return;
targetPosition = new Vector3I(
saveData.TargetX,
saveData.TargetY,
saveData.TargetZ
);
}
}
+15
View File
@@ -42,6 +42,21 @@ public class ForNode : ProgramNode
return $"Name: {DisplayText}, AmountExecuted: {amountExecuted}, Amount: {amount}";
}
public override NodeSaveData CreateSaveData()
{
NodeSaveData saveData = base.CreateSaveData();
saveData.Amount = amount;
saveData.AmountExecuted = amountExecuted;
return saveData;
}
public override void Load(NodeSaveData saveData)
{
base.Load(saveData);
amount = saveData.Amount;
amountExecuted = saveData.AmountExecuted;
}
public override void SetNextNode(
List<Godot.Collections.Dictionary> connections,
Dictionary<StringName, ProgramNode> availableNodes
+20
View File
@@ -60,6 +60,26 @@ public class IfNode : ProgramNode
return $"Name: {DisplayText}, Item: {(selectedItem == null ? "Empty" : selectedItem.data.Id)}, Comparator: {comparator}, Amount: {amount}";
}
public override NodeSaveData CreateSaveData()
{
NodeSaveData saveData = base.CreateSaveData();
saveData.ItemId = selectedItem?.data.Id;
saveData.Comparator = comparator;
saveData.Amount = amount;
return saveData;
}
public override void Load(NodeSaveData saveData)
{
base.Load(saveData);
amount = saveData.Amount;
comparator = saveData.Comparator;
if (string.IsNullOrEmpty(saveData.ItemId)) return;
if (!GameData.availableItems.ContainsKey(saveData.ItemId)) return;
selectedItem = new Item { data = GameData.availableItems[saveData.ItemId] };
}
public override void SetNextNode(
List<Godot.Collections.Dictionary> connections,
Dictionary<StringName, ProgramNode> availableNodes
+22
View File
@@ -98,4 +98,26 @@ public class MoveNode : ProgramNode
{
return $"Name: {DisplayText}, Position: ({targetPosition.X}|{targetPosition.Y}|{targetPosition.Z})";
}
public override NodeSaveData CreateSaveData()
{
NodeSaveData saveData = base.CreateSaveData();
saveData.TargetX = targetPosition.X;
saveData.TargetY = targetPosition.Y;
saveData.TargetZ = targetPosition.Z;
saveData.HasTargetPosition = true;
return saveData;
}
public override void Load(NodeSaveData saveData)
{
base.Load(saveData);
if (!saveData.HasTargetPosition) return;
targetPosition = new Vector3I(
saveData.TargetX,
saveData.TargetY,
saveData.TargetZ
);
}
}
+57
View File
@@ -14,6 +14,52 @@ public abstract class ProgramNode
public abstract ProgramNode Duplicate();
public abstract string Save();
public virtual NodeSaveData CreateSaveData()
{
return new NodeSaveData
{
NodeType = DisplayText,
EditorNodeId = EditorNodeId,
NextEditorNodeId = nextNode?.EditorNodeId,
NegativeEditorNodeId = NegativeNode?.EditorNodeId,
NodeContent = Save(),
LastExecutionMessage = lastExecutionMessage
};
}
public virtual void Load(NodeSaveData saveData)
{
EditorNodeId = saveData.EditorNodeId;
lastExecutionMessage = saveData.LastExecutionMessage;
}
public void RestoreConnections(
NodeSaveData saveData,
Dictionary<string, ProgramNode> availableNodes
)
{
nextNode = GetSavedConnection(saveData.NextEditorNodeId, availableNodes);
NegativeNode = GetSavedConnection(saveData.NegativeEditorNodeId, availableNodes);
}
public static ProgramNode CreateFromSaveData(NodeSaveData saveData)
{
return saveData.NodeType?.ToLower() switch
{
"start" => new StartNode(),
"move" => new MoveNode(),
"explore" => new ExploreNode(),
"harvest" => new HarvestNode(),
"craft" => new CraftNode(),
"if" => new IfNode(),
"while" => new WhileNode(),
"for" => new ForNode(),
"maintain" => new MaintainNode(),
"sacrifice" => new SacrificeNode(),
_ => null
};
}
public ProgramNode DuplicateForRuntime(string editorNodeId)
{
ProgramNode duplicate = Duplicate();
@@ -65,4 +111,15 @@ public abstract class ProgramNode
return availableNodes[nodeName];
}
private ProgramNode GetSavedConnection(
string nodeId,
Dictionary<string, ProgramNode> availableNodes
)
{
if (string.IsNullOrEmpty(nodeId)) return null;
if (!availableNodes.ContainsKey(nodeId)) return null;
return availableNodes[nodeId];
}
}
+20
View File
@@ -60,6 +60,26 @@ public class WhileNode : ProgramNode
return $"Name: {DisplayText}, Item: {(selectedItem == null ? "Empty" : selectedItem.data.Id)}, Comparator: {comparator}, Amount: {amount}";
}
public override NodeSaveData CreateSaveData()
{
NodeSaveData saveData = base.CreateSaveData();
saveData.ItemId = selectedItem?.data.Id;
saveData.Comparator = comparator;
saveData.Amount = amount;
return saveData;
}
public override void Load(NodeSaveData saveData)
{
base.Load(saveData);
amount = saveData.Amount;
comparator = saveData.Comparator;
if (string.IsNullOrEmpty(saveData.ItemId)) return;
if (!GameData.availableItems.ContainsKey(saveData.ItemId)) return;
selectedItem = new Item { data = GameData.availableItems[saveData.ItemId] };
}
public override void SetNextNode(
List<Godot.Collections.Dictionary> connections,
Dictionary<StringName, ProgramNode> availableNodes