diff --git a/Campofinale/Campofinale.csproj b/Campofinale/Campofinale.csproj
index 5cc10f4..113136d 100644
--- a/Campofinale/Campofinale.csproj
+++ b/Campofinale/Campofinale.csproj
@@ -21,15 +21,11 @@
-
-
-
-
diff --git a/Campofinale/Commands/Handlers/CommandHeal.cs b/Campofinale/Commands/Handlers/CommandHeal.cs
index 992c2b2..60c049d 100644
--- a/Campofinale/Commands/Handlers/CommandHeal.cs
+++ b/Campofinale/Commands/Handlers/CommandHeal.cs
@@ -10,21 +10,8 @@ namespace Campofinale.Commands.Handlers
[Server.Command("heal", "Revives/Heals your team characters", true)]
public static void Handle(Player sender, string cmd, string[] args, Player target)
{
- target.GetCurTeam().ForEach(chara =>
- {
- chara.curHp = chara.CalcAttributes()[AttributeType.MaxHp].val;
- ScCharSyncStatus state = new ScCharSyncStatus()
- {
- Objid=chara.guid,
- IsDead=chara.curHp < 1,
- BattleInfo = new()
- {
- Hp=chara.curHp,
- Ultimatesp=chara.ultimateSp
- }
- };
- target.Send(ScMsgId.ScCharSyncStatus, state);
- });
+ target.RestTeam();
+
target.Send(ScMsgId.ScSceneRevival, new ScSceneRevival()
{
diff --git a/Campofinale/Database/DatabaseManager.cs b/Campofinale/Database/DatabaseManager.cs
index e769373..9235701 100644
--- a/Campofinale/Database/DatabaseManager.cs
+++ b/Campofinale/Database/DatabaseManager.cs
@@ -4,6 +4,8 @@ using MongoDB.Bson;
using System.Reflection;
using static Campofinale.Game.Factory.FactoryNode;
using Campofinale.Game.Inventory;
+using Campofinale.Game.Factory;
+using Campofinale.Game.Factory.BuildingsBehaviour;
namespace Campofinale.Database
{
@@ -66,6 +68,7 @@ namespace Campofinale.Database
BsonSerializer.RegisterSerializer(typeof(Dictionary), new CustomDictionarySerializer());
RegisterSubclasses();
+ RegisterSubclasses();
Logger.Print("Connecting to MongoDB...");
try
{
diff --git a/Campofinale/Game/Factory/BlockCalculator.cs b/Campofinale/Game/Factory/BlockCalculator.cs
new file mode 100644
index 0000000..ba4b72b
--- /dev/null
+++ b/Campofinale/Game/Factory/BlockCalculator.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using static Campofinale.Resource.ResourceManager;
+
+namespace Campofinale.Game.Factory
+{
+ public class BlockCalculator
+ {
+ public static int CalculateTotalBlocks(List points)
+ {
+ if (points == null || points.Count < 2)
+ return 0;
+
+ HashSet> blocks = new HashSet>();
+
+ for (int i = 0; i < points.Count - 1; i++)
+ {
+ Vector3f p1 = points[i];
+ Vector3f p2 = points[i + 1];
+
+ AddBlocksForLineSegment3D(p1, p2, blocks);
+ }
+
+ return blocks.Count;
+ }
+
+ private static void AddBlocksForLineSegment3D(Vector3f p1, Vector3f p2, HashSet> blocks)
+ {
+ int x0 = (int)Math.Floor(p1.x);
+ int y0 = (int)Math.Floor(p1.y);
+ int z0 = (int)Math.Floor(p1.z);
+ int x1 = (int)Math.Floor(p2.x);
+ int y1 = (int)Math.Floor(p2.y);
+ int z1 = (int)Math.Floor(p2.z);
+
+ int dx = Math.Abs(x1 - x0);
+ int dy = Math.Abs(y1 - y0);
+ int dz = Math.Abs(z1 - z0);
+ int sx = x0 < x1 ? 1 : -1;
+ int sy = y0 < y1 ? 1 : -1;
+ int sz = z0 < z1 ? 1 : -1;
+
+ if (dx >= dy && dx >= dz)
+ {
+ int err1 = 2 * dy - dx;
+ int err2 = 2 * dz - dx;
+ for (int i = 0; i < dx; i++)
+ {
+ blocks.Add(Tuple.Create(x0, y0, z0));
+ if (err1 > 0)
+ {
+ y0 += sy;
+ err1 -= 2 * dx;
+ }
+ if (err2 > 0)
+ {
+ z0 += sz;
+ err2 -= 2 * dx;
+ }
+ err1 += 2 * dy;
+ err2 += 2 * dz;
+ x0 += sx;
+ }
+ }
+ else if (dy >= dx && dy >= dz)
+ {
+ int err1 = 2 * dx - dy;
+ int err2 = 2 * dz - dy;
+ for (int i = 0; i < dy; i++)
+ {
+ blocks.Add(Tuple.Create(x0, y0, z0));
+ if (err1 > 0)
+ {
+ x0 += sx;
+ err1 -= 2 * dy;
+ }
+ if (err2 > 0)
+ {
+ z0 += sz;
+ err2 -= 2 * dy;
+ }
+ err1 += 2 * dx;
+ err2 += 2 * dz;
+ y0 += sy;
+ }
+ }
+ else
+ {
+ int err1 = 2 * dy - dz;
+ int err2 = 2 * dx - dz;
+ for (int i = 0; i < dz; i++)
+ {
+ blocks.Add(Tuple.Create(x0, y0, z0));
+ if (err1 > 0)
+ {
+ y0 += sy;
+ err1 -= 2 * dz;
+ }
+ if (err2 > 0)
+ {
+ x0 += sx;
+ err2 -= 2 * dz;
+ }
+ err1 += 2 * dy;
+ err2 += 2 * dx;
+ z0 += sz;
+ }
+ }
+
+ blocks.Add(Tuple.Create(x1, y1, z1));
+ }
+ }
+}
diff --git a/Campofinale/Game/Factory/BuildingsBehaviour/NodeBuildingBehaviour.cs b/Campofinale/Game/Factory/BuildingsBehaviour/NodeBuildingBehaviour.cs
new file mode 100644
index 0000000..f024b38
--- /dev/null
+++ b/Campofinale/Game/Factory/BuildingsBehaviour/NodeBuildingBehaviour.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Campofinale.Game.Factory.BuildingsBehaviour
+{
+ public class NodeBuildingBehaviour
+ {
+ public virtual void Update(FactoryChapter chapter, FactoryNode node)
+ {
+
+ }
+ //Executed the first time when created a node that use the specific behaviour
+ public virtual void Init(FactoryChapter chapter, FactoryNode node)
+ {
+
+ }
+ }
+}
diff --git a/Campofinale/Game/Factory/BuildingsBehaviour/NodeBuilding_Producer.cs b/Campofinale/Game/Factory/BuildingsBehaviour/NodeBuilding_Producer.cs
new file mode 100644
index 0000000..333a907
--- /dev/null
+++ b/Campofinale/Game/Factory/BuildingsBehaviour/NodeBuilding_Producer.cs
@@ -0,0 +1,112 @@
+using Campofinale.Game.Factory.Components;
+using Campofinale.Protocol;
+using Campofinale.Resource;
+using Campofinale.Resource.Table;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Campofinale.Resource;
+using static Campofinale.Resource.ResourceManager;
+using System.Xml.Linq;
+
+namespace Campofinale.Game.Factory.BuildingsBehaviour
+{
+ public class NodeBuilding_Producer : NodeBuildingBehaviour
+ {
+ public uint inputCacheId = 0;
+ public uint outputCacheId = 0;
+ public uint producerId = 0;
+ public long timestampFinish = 0;
+ public override void Init(FactoryChapter chapter, FactoryNode node)
+ {
+ FComponentCache cache1 = (FComponentCache)new FComponentCache(chapter.nextCompV(), FCComponentPos.CacheIn1).Init();
+ FComponentCache cache2 = (FComponentCache)new FComponentCache(chapter.nextCompV(), FCComponentPos.CacheOut1).Init();
+ FComponentProducer producer = (FComponentProducer)new FComponentProducer(chapter.nextCompV()).Init();
+ node.components.Add(producer);
+ node.components.Add(new FComponentFormulaMan(chapter.nextCompV()).Init());
+ node.components.Add(cache1);
+ node.components.Add(cache2);
+ inputCacheId = cache1.compId;
+ outputCacheId = cache2.compId;
+ producerId = producer.compId;
+ node.components.Add(new FComponentPortManager(chapter.nextCompV(), 3, cache1).Init());
+ node.components.Add(new FComponentPortManager(chapter.nextCompV(), 3, cache2).Init());
+ }
+ public string GetFormulaGroupId(string templateId)
+ {
+ FactoryMachineCraftTable table = factoryMachineCraftTable.Values.ToList().Find(r => r.machineId == templateId);
+ if (table != null)
+ {
+ return table.formulaGroupId;
+ }
+ else
+ {
+ return "";
+ }
+ }
+ public override void Update(FactoryChapter chapter, FactoryNode node)
+ {
+
+ if (node.powered)
+ {
+ FComponentProducer producer = node.GetComponent(producerId);
+ FComponentCache inCache = node.GetComponent(inputCacheId);
+ FComponentCache outCache = node.GetComponent(outputCacheId);
+ FComponentFormulaMan formulaManager = node.GetComponent();
+
+ if (formulaManager == null) return;
+ formulaManager.currentGroup = GetFormulaGroupId(node.templateId);
+ FactoryMachineCraftTable craftingRecipe = null;
+ string recipe = ResourceManager.FindFactoryMachineCraftIdUsingCacheItems(inCache.items,formulaManager.currentGroup);
+ producer.formulaId = recipe;
+ ResourceManager.factoryMachineCraftTable.TryGetValue(producer.formulaId, out craftingRecipe);
+
+ if (craftingRecipe != null)
+ {
+ producer.inBlock = outCache.IsFull();
+ if (craftingRecipe.CacheHaveItems(inCache) && !outCache.IsFull())
+ {
+ producer.inProduce = true;
+
+ producer.lastFormulaId = recipe;
+ if (timestampFinish == 0)
+ {
+ timestampFinish = DateTime.UtcNow.ToUnixTimestampMilliseconds() + 1000 * craftingRecipe.progressRound;
+ }
+ producer.progress = (DateTime.UtcNow.ToUnixTimestampMilliseconds()/timestampFinish)* craftingRecipe.totalProgress;
+ if (DateTime.UtcNow.ToUnixTimestampMilliseconds() >= timestampFinish)
+ {
+ timestampFinish= DateTime.UtcNow.ToUnixTimestampMilliseconds()+1000* craftingRecipe.progressRound;
+ List toConsume = craftingRecipe.GetIngredients();
+ inCache.ConsumeItems(toConsume);
+ craftingRecipe.outcomes.ForEach(e =>
+ {
+ e.group.ForEach(i =>
+ {
+ outCache.AddItem(i.id, i.count);
+ });
+
+ });
+ }
+ }
+ else
+ {
+ producer.inProduce = false;
+ producer.progress = 0;
+ timestampFinish = 0;
+ }
+ }
+ else
+ {
+ producer.inBlock = false;
+ producer.inProduce = false;
+ producer.progress = 0;
+ timestampFinish = 0;
+ }
+ }
+
+ }
+ }
+}
diff --git a/Campofinale/Game/Factory/BuildingsBehaviour/NodeBuilding_ProducerFurnace.cs b/Campofinale/Game/Factory/BuildingsBehaviour/NodeBuilding_ProducerFurnace.cs
new file mode 100644
index 0000000..a9bf040
--- /dev/null
+++ b/Campofinale/Game/Factory/BuildingsBehaviour/NodeBuilding_ProducerFurnace.cs
@@ -0,0 +1,120 @@
+using Campofinale.Game.Factory.Components;
+using Campofinale.Protocol;
+using Campofinale.Resource;
+using Campofinale.Resource.Table;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Campofinale.Resource;
+using static Campofinale.Resource.ResourceManager;
+using System.Xml.Linq;
+
+namespace Campofinale.Game.Factory.BuildingsBehaviour
+{
+ public class NodeBuilding_ProducerFurnace : NodeBuildingBehaviour
+ {
+ public uint inputCacheId = 0;
+ public uint outputCacheId = 0;
+ public uint inputCacheIdFluid = 0;
+ public uint outputCacheIdFluid = 0;
+ public uint producerId = 0;
+ public long timestampFinish = 0;
+ public override void Init(FactoryChapter chapter, FactoryNode node)
+ {
+ FComponentCache cache1 = (FComponentCache)new FComponentCache(chapter.nextCompV(), FCComponentPos.CacheIn1).Init();
+ FComponentCache cache2 = (FComponentCache)new FComponentCache(chapter.nextCompV(), FCComponentPos.CacheOut1).Init();
+ FComponentCache cache3 = (FComponentCache)new FComponentCache(chapter.nextCompV(), FCComponentPos.CacheFluidIn1).Init();
+ FComponentCache cache4 = (FComponentCache)new FComponentCache(chapter.nextCompV(), FCComponentPos.CacheFluidOut1).Init();
+ FComponentProducer producer = (FComponentProducer)new FComponentProducer(chapter.nextCompV()).Init();
+ node.components.Add(producer);
+ node.components.Add(new FComponentFormulaMan(chapter.nextCompV()).Init());
+ node.components.Add(cache1);
+ node.components.Add(cache2);
+ node.components.Add(cache3);
+ node.components.Add(cache4);
+ inputCacheId = cache1.compId;
+ outputCacheId = cache2.compId;
+ inputCacheIdFluid = cache3.compId;
+ outputCacheIdFluid = cache4.compId;
+ producerId = producer.compId;
+ node.components.Add(new FComponentPortManager(chapter.nextCompV(), 4, cache1).Init());
+ node.components.Add(new FComponentPortManager(chapter.nextCompV(), 4, cache2).Init());
+ }
+ public string GetFormulaGroupId(string templateId)
+ {
+ FactoryMachineCraftTable table = factoryMachineCraftTable.Values.ToList().Find(r => r.machineId == templateId);
+ if (table != null)
+ {
+ return table.formulaGroupId;
+ }
+ else
+ {
+ return "";
+ }
+ }
+ public override void Update(FactoryChapter chapter, FactoryNode node)
+ {
+
+ if (node.powered)
+ {
+ FComponentProducer producer = node.GetComponent(producerId);
+ FComponentCache inCache = node.GetComponent(inputCacheId);
+ FComponentCache outCache = node.GetComponent(outputCacheId);
+ FComponentFormulaMan formulaManager = node.GetComponent();
+
+ if (formulaManager == null) return;
+ formulaManager.currentGroup = GetFormulaGroupId(node.templateId);
+ FactoryMachineCraftTable craftingRecipe = null;
+ string recipe = ResourceManager.FindFactoryMachineCraftIdUsingCacheItems(inCache.items,formulaManager.currentGroup);
+ producer.formulaId = recipe;
+ ResourceManager.factoryMachineCraftTable.TryGetValue(producer.formulaId, out craftingRecipe);
+
+ if (craftingRecipe != null)
+ {
+ producer.inBlock = outCache.IsFull();
+ if (craftingRecipe.CacheHaveItems(inCache) && !outCache.IsFull())
+ {
+ producer.inProduce = true;
+
+ producer.lastFormulaId = recipe;
+ if (timestampFinish == 0)
+ {
+ timestampFinish = DateTime.UtcNow.ToUnixTimestampMilliseconds() + 1000 * craftingRecipe.progressRound;
+ }
+ producer.progress = (DateTime.UtcNow.ToUnixTimestampMilliseconds() / timestampFinish) * craftingRecipe.totalProgress;
+ if (DateTime.UtcNow.ToUnixTimestampMilliseconds() >= timestampFinish)
+ {
+ timestampFinish = DateTime.UtcNow.ToUnixTimestampMilliseconds() + 1000 * craftingRecipe.progressRound;
+ List toConsume = craftingRecipe.GetIngredients();
+ inCache.ConsumeItems(toConsume);
+ craftingRecipe.outcomes.ForEach(e =>
+ {
+ e.group.ForEach(i =>
+ {
+ outCache.AddItem(i.id, i.count);
+ });
+
+ });
+ }
+ }
+ else
+ {
+ producer.inProduce = false;
+ producer.progress = 0;
+ timestampFinish = 0;
+ }
+ }
+ else
+ {
+ producer.inBlock = false;
+ producer.inProduce = false;
+ producer.progress = 0;
+ timestampFinish = 0;
+ }
+ }
+
+ }
+ }
+}
diff --git a/Campofinale/Game/Factory/Components/FComponentBattle.cs b/Campofinale/Game/Factory/Components/FComponentBattle.cs
new file mode 100644
index 0000000..f48cd53
--- /dev/null
+++ b/Campofinale/Game/Factory/Components/FComponentBattle.cs
@@ -0,0 +1,23 @@
+using Campofinale.Resource;
+using static Campofinale.Game.Factory.FactoryNode;
+
+namespace Campofinale.Game.Factory.Components
+{
+ public class FComponentBattle : FComponent
+ {
+ public int EnergyCurrent=100;
+ public FComponentBattle(uint id) : base(id, FCComponentType.Battle, FCComponentPos.Battle1)
+ {
+ }
+
+ public override void SetComponentInfo(ScdFacCom proto)
+ {
+ proto.Battle = new()
+ {
+ EnergyCurrent=100,
+ EnergyMax=100,
+ InOverloading=false
+ };
+ }
+ }
+}
diff --git a/Campofinale/Game/Factory/Components/FComponentBoxConveyor.cs b/Campofinale/Game/Factory/Components/FComponentBoxConveyor.cs
new file mode 100644
index 0000000..c63d964
--- /dev/null
+++ b/Campofinale/Game/Factory/Components/FComponentBoxConveyor.cs
@@ -0,0 +1,37 @@
+using Campofinale.Resource;
+using static Campofinale.Game.Factory.FactoryNode;
+using static Campofinale.Resource.ResourceManager;
+
+namespace Campofinale.Game.Factory.Components
+{
+ public class FComponentBoxConveyor : FComponent
+ {
+ public long lastPopTms = 0;
+ public List items = new();
+ public FComponentBoxConveyor(uint id) : base(id, FCComponentType.BoxConveyor,FCComponentPos.BoxConveyor)
+ {
+ lastPopTms=DateTime.UtcNow.ToUnixTimestampMilliseconds();
+ }
+
+ public override void SetComponentInfo(ScdFacCom proto)
+ {
+ if (items == null)
+ {
+ items = new List();
+ }
+
+ proto.BoxConveyor = new()
+ {
+ LastPopTms = lastPopTms,
+
+ };
+
+ items.ForEach(item =>
+ {
+ if(item!=null)
+ proto.BoxConveyor.Items.Add(item.ToFactoryItemProto());
+ });
+
+ }
+ }
+}
diff --git a/Campofinale/Game/Factory/Components/FComponentCache.cs b/Campofinale/Game/Factory/Components/FComponentCache.cs
new file mode 100644
index 0000000..e76407d
--- /dev/null
+++ b/Campofinale/Game/Factory/Components/FComponentCache.cs
@@ -0,0 +1,100 @@
+using Campofinale.Resource;
+using static Campofinale.Game.Factory.FactoryNode;
+using static Campofinale.Resource.ResourceManager;
+
+namespace Campofinale.Game.Factory.Components
+{
+ public class FComponentCache : FComponent
+ {
+
+ public List items = new();
+ public FComponentCache(uint id,FCComponentPos pos) : base(id, FCComponentType.Cache,pos)
+ {
+ }
+ public int GetItemCount(string id)
+ {
+ int count = 0;
+ ItemCount item = items.Find(i=>i.id == id);
+ if (item != null)
+ {
+ count += item.count;
+ }
+ return count;
+ }
+ public override void SetComponentInfo(ScdFacCom proto)
+ {
+ if(items.Count < 1)
+ {
+ //Add 1 empty item as default
+ items.Add(new ItemCount());
+ }
+ proto.Cache = new()
+ {
+ Items =
+ {
+ },
+ Size=items.Count,
+
+ };
+ items.ForEach(item =>
+ {
+ proto.Cache.Items.Add(item.ToFactoryItemProto());
+ });
+ }
+
+ public void ConsumeItems(List toConsume)
+ {
+ foreach (var consume in toConsume)
+ {
+ ItemCount item = items.Find(i => i.id == consume.id);
+ if (item != null)
+ {
+ item.count-=consume.count;
+ if(item.count < 1)
+ {
+ item.count = 0;
+ item.id = "";
+ }
+ }
+ }
+ }
+
+ public bool IsFull()
+ {
+ int maxItems = items.Count * 50;
+ int count = 0;
+ foreach (var item in items)
+ {
+ count += item.count;
+ };
+ return count>=maxItems;
+ }
+
+ public void AddItem(string id, int count)
+ {
+ int remaining = count;
+ foreach (var item in items)
+ {
+ int space = 50-item.count;
+ if (item.id==id)
+ {
+ if (space >= remaining)
+ {
+ item.count +=remaining;
+ remaining = 0;
+ }
+ else
+ {
+ item.count += space;
+ remaining -= space;
+ }
+ }
+ else if(item.id.Length < 1)
+ {
+ item.id = id;
+ item.count = remaining;
+ }
+ }
+ }
+ }
+}
diff --git a/Campofinale/Game/Factory/Components/FComponentFormulaMan.cs b/Campofinale/Game/Factory/Components/FComponentFormulaMan.cs
new file mode 100644
index 0000000..993892c
--- /dev/null
+++ b/Campofinale/Game/Factory/Components/FComponentFormulaMan.cs
@@ -0,0 +1,32 @@
+using Campofinale.Resource;
+
+
+namespace Campofinale.Game.Factory.Components
+{
+ public class FComponentFormulaMan : FComponent
+ {
+ public string currentGroup = "group_grinder_normal";
+ public string currentMode = "normal";
+ public List formulaIds = new();
+ public FComponentFormulaMan(uint id) : base(id, FCComponentType.FormulaMan)
+ {
+ }
+ public List GetFormulaIds()
+ {
+ List ids = ResourceManager.factoryMachineCraftTable.Where(i => i.Value.formulaGroupId == currentGroup).Select(i => i.Value.id).ToList();
+ return ids;
+ }
+ public override void SetComponentInfo(ScdFacCom proto)
+ {
+ formulaIds = GetFormulaIds();
+ proto.FormulaMan = new()
+ {
+ CurrentGroup = currentGroup,
+ CurrentMode = currentMode,
+ FormulaIds = {
+ formulaIds
+ }
+ };
+ }
+ }
+}
diff --git a/Campofinale/Game/Factory/Components/FComponentPortManager.cs b/Campofinale/Game/Factory/Components/FComponentPortManager.cs
index 43e473d..fa83d87 100644
--- a/Campofinale/Game/Factory/Components/FComponentPortManager.cs
+++ b/Campofinale/Game/Factory/Components/FComponentPortManager.cs
@@ -35,9 +35,45 @@ namespace Campofinale.Game.Factory.Components
});
}
}
-
+ public FComponentPortManager(uint id, int size) : base(id, FCComponentType.PortManager)
+ {
+ for (int i = 0; i < size; i++)
+ {
+ ports.Add(new FPort()
+ {
+ index = i,
+ ownerComId = 0,
+ touchComId = 0
+ });
+ }
+ }
+ public FComponentPortManager(uint id, int size, FComponentCache cache) : base(id, FCComponentType.PortManager)
+ {
+ if( cache.customPos == FCComponentPos.CacheIn1 ||
+ cache.customPos == FCComponentPos.CacheIn2 ||
+ cache.customPos == FCComponentPos.CacheIn3 ||
+ cache.customPos == FCComponentPos.CacheIn4)
+ {
+ customPos = FCComponentPos.PortInManager;
+ }
+ else
+ {
+ customPos = FCComponentPos.PortOutManager;
+ }
+
+ for (int i = 0; i < size; i++)
+ {
+ ports.Add(new FPort()
+ {
+ index = i,
+ ownerComId = cache.compId,
+ touchComId = 0
+ });
+ }
+ }
public override void SetComponentInfo(ScdFacCom proto)
{
+
proto.PortManager = new();
foreach(FPort port in ports)
{
diff --git a/Campofinale/Game/Factory/Components/FComponentProducer.cs b/Campofinale/Game/Factory/Components/FComponentProducer.cs
new file mode 100644
index 0000000..4452420
--- /dev/null
+++ b/Campofinale/Game/Factory/Components/FComponentProducer.cs
@@ -0,0 +1,29 @@
+using Campofinale.Resource;
+using static Campofinale.Game.Factory.FactoryNode;
+
+namespace Campofinale.Game.Factory.Components
+{
+ public class FComponentProducer : FComponent
+ {
+ public string formulaId = "";
+ public string lastFormulaId = "";
+ public bool inProduce, inBlock;
+ public long progress;
+ public FComponentProducer(uint id) : base(id, FCComponentType.Producer)
+ {
+
+ }
+
+ public override void SetComponentInfo(ScdFacCom proto)
+ {
+ proto.Producer = new()
+ {
+ FormulaId=formulaId,
+ InBlock=inBlock,
+ CurrentProgress=progress,
+ InProduce=inProduce,
+ LastFormulaId=lastFormulaId
+ };
+ }
+ }
+}
diff --git a/Campofinale/Game/Factory/FComponent.cs b/Campofinale/Game/Factory/FComponent.cs
new file mode 100644
index 0000000..89058d3
--- /dev/null
+++ b/Campofinale/Game/Factory/FComponent.cs
@@ -0,0 +1,111 @@
+using Campofinale.Game.Factory.Components;
+using Campofinale.Resource;
+using MongoDB.Bson.Serialization.Attributes;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Campofinale.Game.Factory
+{
+ [BsonDiscriminator(Required = true)]
+ [BsonKnownTypes(typeof(FComponentSelector))]
+
+ public class FComponent
+ {
+ public class FCompInventory
+ {
+ public ScdFacComInventory ToProto()
+ {
+ return new ScdFacComInventory()
+ {
+
+ };
+ }
+ }
+ public uint compId;
+ public FCComponentType type;
+ public FCompInventory inventory;
+ public FCComponentPos customPos = FCComponentPos.Invalid;
+ public FComponent(uint id, FCComponentType t, FCComponentPos custom= FCComponentPos.Invalid)
+ {
+ this.compId = id;
+ this.type = t;
+ this.customPos = custom;
+ }
+ public FCComponentPos GetComPos()
+ {
+ if(customPos == FCComponentPos.Invalid)
+ {
+ switch (type)
+ {
+ case FCComponentType.PowerPole:
+ return FCComponentPos.PowerPole;
+ case FCComponentType.TravelPole:
+ return FCComponentPos.TravelPole;
+ case FCComponentType.Battle:
+ return FCComponentPos.Battle1;
+ case FCComponentType.Producer:
+ return FCComponentPos.Producer;
+ case FCComponentType.FormulaMan:
+ return FCComponentPos.FormulaMan;
+ case FCComponentType.BusLoader:
+ return FCComponentPos.BusLoader;
+ case FCComponentType.StablePower:
+ return FCComponentPos.StablePower;
+ case FCComponentType.Selector:
+ return FCComponentPos.Selector;
+ case FCComponentType.PowerSave:
+ return FCComponentPos.PowerSave;
+ default:
+ return FCComponentPos.Invalid;
+ }
+ }
+
+ return customPos;
+ }
+ public ScdFacCom ToProto()
+ {
+ ScdFacCom proto = new ScdFacCom()
+ {
+ ComponentType = (int)type,
+ ComponentId = compId,
+
+ };
+ SetComponentInfo(proto);
+ return proto;
+ }
+
+ public virtual void SetComponentInfo(ScdFacCom proto)
+ {
+ if (inventory != null)
+ {
+ proto.Inventory = inventory.ToProto();
+ }
+ else if (type == FCComponentType.PowerPole)
+ {
+ proto.PowerPole = new()
+ {
+
+ };
+ }
+ }
+
+ public virtual FComponent Init()
+ {
+ switch (type)
+ {
+ case FCComponentType.Inventory:
+ inventory = new();
+ break;
+ default:
+ break;
+ }
+ return this;
+ }
+
+
+ }
+}
diff --git a/Campofinale/Game/Factory/FactoryChapter.cs b/Campofinale/Game/Factory/FactoryChapter.cs
new file mode 100644
index 0000000..7a461d3
--- /dev/null
+++ b/Campofinale/Game/Factory/FactoryChapter.cs
@@ -0,0 +1,722 @@
+using Campofinale.Game.Factory.Components;
+using Campofinale.Game.Inventory;
+using Campofinale.Packets.Sc;
+using Campofinale.Protocol;
+using Campofinale.Resource;
+using Campofinale.Resource.Table;
+using Newtonsoft.Json;
+using System.Xml.Linq;
+using static Campofinale.Resource.ResourceManager;
+
+namespace Campofinale.Game.Factory
+{
+ public class FactoryChapter
+ {
+ public string chapterId;
+ public ulong ownerId;
+ public List nodes = new();
+ public uint v = 1;
+ public uint compV = 0;
+ public int bandwidth = 200;
+ public FactoryBlackboard blackboard = new();
+ public class FactoryBlackboard
+ {
+ public uint inventoryNodeId=1;
+ public FacBbPower power = new();
+
+ public class FacBbPower
+ {
+ public long powerGen;
+ public long powerSaveMax;
+ public long powerSaveCurrent;
+ public long powerCost;
+ public bool isStopByPower;
+ }
+ public ScdFactorySyncBlackboard ToProto()
+ {
+ return new ScdFactorySyncBlackboard()
+ {
+ InventoryNodeId = inventoryNodeId,
+ Power = new()
+ {
+ IsStopByPower=power.isStopByPower,
+ PowerCost=power.powerCost,
+ PowerGen=power.powerGen,
+ PowerSaveCurrent=power.powerSaveCurrent,
+ PowerSaveMax=power.powerSaveMax,
+ }
+ };
+ }
+
+ public ScdFactoryHsBb ToProtoHsBb()
+ {
+ return new ScdFactoryHsBb()
+ {
+ Power = new()
+ {
+ IsStopByPower = power.isStopByPower,
+ PowerSaveCurrent = power.powerSaveCurrent,
+ PowerSaveMax = power.powerSaveMax,
+
+ },
+
+ };
+ }
+ }
+ public ScFactorySyncChapter ToProto()
+ {
+ blackboard = new();
+ ScFactorySyncChapter chapter = new()
+ {
+ ChapterId = chapterId,
+ Tms = DateTime.UtcNow.ToUnixTimestampMilliseconds(),
+ Blackboard = new(),
+ Statistic = new()
+ {
+ LastDay = new()
+ {
+
+ },
+ Other = new()
+ {
+ InPowerBuilding = nodes.FindAll(n=>n.lastPowered==true).Count,
+
+ }
+ },
+ PinBoard = new()
+ {
+ Cards =
+ {
+
+ },
+
+ },
+ };
+ blackboard.power.powerSaveCurrent = bandwidth;
+ domainDataTable[chapterId].levelGroup.ForEach(levelGroup =>
+ {
+ int grade = GetOwner().sceneManager.GetScene(GetSceneNumIdFromLevelData(levelGroup)).grade;
+ LevelGradeInfo sceneGrade = ResourceManager.levelGradeTable[levelGroup].grades.Find(g => g.grade == grade);
+ if (sceneGrade != null)
+ {
+ blackboard.power.powerGen += sceneGrade.bandwidth;
+ blackboard.power.powerSaveMax += sceneGrade.bandwidth;
+
+ var scene = new ScdFactorySyncScene()
+ {
+ SceneId = GetSceneNumIdFromLevelData(levelGroup),
+
+ Bandwidth = new()
+ {
+ Current = 0,
+ Max = sceneGrade.bandwidth,
+ TravelPoleMax = sceneGrade.travelPoleLimit,
+
+ BattleCurrent = 0,
+ BattleMax = sceneGrade.battleBuildingLimit,
+ },
+ Settlements =
+ {
+
+ },
+
+ Panels =
+ {
+
+ }
+ };
+ int index = 0;
+ LevelScene scen = GetLevelData(GetSceneNumIdFromLevelData(levelGroup));
+ foreach (var reg in scen.levelData.factoryRegions)
+ {
+ foreach (var area in reg.areas)
+ {
+ var lvData = area.levelData.Find(l => l.level == grade);
+ if (lvData == null)
+ {
+ lvData = area.levelData.Last();
+ }
+ if (lvData.levelBounds.Count > 0)
+ {
+ var bounds = lvData.levelBounds[0];
+ scene.Panels.Add(new ScdFactorySyncScenePanel()
+ {
+ Index = index,
+ Level = lvData.level,
+ MainMesh =
+ {
+ new ScdRectInt()
+ {
+ X=(int)bounds.start.x,
+ Z=(int)bounds.start.z,
+ Y=(int)bounds.start.y,
+ W=(int)bounds.size.x,
+ H=(int)bounds.size.y,
+ L=(int)bounds.size.z,
+ }
+ }
+ });
+ index++;
+ }
+
+ }
+ }
+ chapter.Scenes.Add(scene);
+ }
+
+ });
+ try
+ {
+ nodes.ForEach(node =>
+ {
+ chapter.Nodes.Add(node.ToProto());
+ });
+ }
+ catch(Exception e)
+ {
+
+ }
+ chapter.Blackboard = blackboard.ToProto();
+ chapter.Maps.AddRange(GetMaps());
+ return chapter;
+ }
+ public List GetMaps()
+ {
+ List maps = new();
+ string levelId = domainDataTable[chapterId].levelGroup[0];
+ string mapId = GetLevelData(GetSceneNumIdFromLevelData(levelId)).mapIdStr;
+ maps.Add(new ScdFactorySyncMap()
+ {
+ MapId = ResourceManager.strIdNumTable.chapter_map_id.dic[mapId],
+
+ Wires =
+ {
+ GetWires()
+ },
+
+ });
+ return maps;
+ }
+
+ public List GetWires()
+ {
+ List wires = new();
+ HashSet<(ulong, ulong)> addedConnections = new();
+ ulong i = 0;
+
+ foreach (FactoryNode node in nodes)
+ {
+ foreach (var conn in node.connectedComps)
+ {
+ ulong compA = conn.Key;
+ ulong compB = conn.Value;
+
+ var key = (compA, compB);
+
+ if (!addedConnections.Contains(key))
+ {
+ wires.Add(new ScdFactorySyncMapWire()
+ {
+ Index = i,
+ FromComId = compA,
+ ToComId = compB,
+
+ });
+
+ addedConnections.Add(key);
+ i++;
+ }
+ }
+ }
+
+ return wires;
+ }
+
+
+ public void Update()
+ {
+ try
+ {
+ UpdatePowerGrid(nodes);
+ foreach (FactoryNode node in nodes)
+ {
+ try
+ {
+ node.Update(this);
+ }
+ catch (Exception e)
+ {
+ Logger.PrintError($"Error occured while updating nodeId {node.nodeId}: {e.Message}");
+ }
+
+ }
+ }
+ catch (Exception e)
+ {
+
+ }
+
+ }
+ public List GetNodesInRange(Vector3f pos, float range)
+ {
+ return nodes.FindAll(n => n.position.Distance(pos) <= range);
+ }
+
+ public void ExecOp(CsFactoryOp op, ulong seq)
+ {
+
+ switch (op.OpType)
+ {
+ case FactoryOpType.Place:
+ CreateNode(op, seq);
+ break;
+ case FactoryOpType.MoveNode:
+ MoveNode(op, seq);
+ break;
+ case FactoryOpType.Dismantle:
+ DismantleNode(op, seq);
+ break;
+ case FactoryOpType.AddConnection:
+ AddConnection(op, seq);
+ break;
+ case FactoryOpType.MoveItemBagToCache:
+ MoveItemBagToCache(op, seq);
+ break;
+ case FactoryOpType.MoveItemCacheToBag:
+ MoveItemCacheToBag(op, seq);
+ break;
+ case FactoryOpType.ChangeProducerMode:
+ ChangeProducerMode(op, seq);
+ break;
+ case FactoryOpType.EnableNode:
+ EnableNode(op, seq);
+ break;
+ case FactoryOpType.PlaceConveyor:
+ PlaceConveyor(op, seq);
+ break;
+ case FactoryOpType.DismantleBoxConveyor:
+ DismantleBoxConveyor(op, seq);
+ break;
+ case FactoryOpType.UseHealTowerPoint:
+ //TODO
+ break;
+ case FactoryOpType.SetTravelPoleDefaultNext:
+ FactoryNode travelNode = GetNodeByCompId(op.SetTravelPoleDefaultNext.ComponentId);
+ travelNode.GetComponent().defaultNext = op.SetTravelPoleDefaultNext.DefaultNext;
+ GetOwner().Send(new PacketScFactoryModifyChapterNodes(GetOwner(), chapterId, travelNode));
+ GetOwner().Send(new PacketScFactoryOpRet(GetOwner(), 0, op), seq);
+ break;
+ default:
+ break;
+ }
+
+ }
+ public void DismantleBoxConveyor(CsFactoryOp op, ulong seq)
+ {
+ var dismantle = op.DismantleBoxConveyor;
+
+ FactoryNode nodeRem = nodes.Find(n => n.nodeId == dismantle.NodeId);
+ if (nodeRem != null)
+ {
+ RemoveConnectionsToNode(nodeRem, nodes);
+ nodes.Remove(nodeRem);
+ GetOwner().Send(new PacketScFactoryModifyChapterNodes(GetOwner(), chapterId, nodeRem.nodeId));
+ GetOwner().Send(new PacketScFactoryOpRet(GetOwner(), nodeRem.nodeId, op), seq);
+ }
+ else
+ {
+ ScFactoryOpRet ret = new()
+ {
+ RetCode = FactoryOpRetCode.Fail,
+
+ };
+ GetOwner().Send(ScMsgId.ScFactoryOpRet, ret, seq);
+ }
+ }
+ public void EnableNode(CsFactoryOp op, ulong seq)
+ {
+ var enableNode = op.EnableNode;
+ FactoryNode node = nodes.Find(n => n.nodeId == enableNode.NodeId);
+ if(node!= null)
+ {
+ node.deactive = !enableNode.Enable;
+ GetOwner().Send(new PacketScFactoryModifyChapterNodes(GetOwner(), chapterId, node));
+ }
+ GetOwner().Send(new PacketScFactoryOpRet(GetOwner(), 0, op), seq);
+ }
+ public void ChangeProducerMode(CsFactoryOp op, ulong seq)
+ {
+ var changeMode = op.ChangeProducerMode;
+ FactoryNode node = nodes.Find(n=>n.nodeId == changeMode.NodeId);
+ if(node != null)
+ {
+ FComponentFormulaMan formula = node.GetComponent();
+ if (formula != null)
+ {
+ formula.currentMode = changeMode.ToMode; //test, not sure
+ }
+
+ }
+ GetOwner().Send(new PacketScFactoryOpRet(GetOwner(), 0, op), seq);
+
+ }
+ public void MoveItemCacheToBag(CsFactoryOp op, ulong seq)
+ {
+ var move = op.MoveItemCacheToBag;
+ FComponentCache cacheComp = GetCompById(move.ComponentId);
+ if (cacheComp != null)
+ {
+ ItemCount cacheItem = cacheComp.items[move.CacheGridIndex];
+ Item gridItem = null;
+ GetOwner().inventoryManager.items.bag.TryGetValue(move.GridIndex, out gridItem);
+ if (gridItem == null)
+ {
+ GetOwner().inventoryManager.items.bag.Add(move.GridIndex, new Item(ownerId,cacheItem.id,cacheItem.count));
+ cacheItem.id = "";
+ cacheItem.count = 0;
+
+ }
+ else
+ {
+ if(gridItem.id == cacheItem.id)
+ {
+ int availableSpace = 50 - gridItem.amount;
+ if(cacheItem.count > availableSpace)
+ {
+ gridItem.amount += availableSpace;
+ cacheItem.count-= availableSpace;
+ }
+ else
+ {
+ gridItem.amount += cacheItem.count;
+ cacheItem.id = "";
+ cacheItem.count = 0;
+ }
+ }
+ else
+ {
+ //TODO Swap
+ }
+
+ }
+ }
+ GetOwner().inventoryManager.items.UpdateBagInventoryPacket();
+ GetOwner().Send(new PacketScFactoryOpRet(GetOwner(), 0, op), seq);
+ }
+ public void MoveItemBagToCache(CsFactoryOp op, ulong seq)
+ {
+ var move = op.MoveItemBagToCache;
+ FComponentCache cacheComp = GetCompById(move.ComponentId);
+ if (cacheComp != null)
+ {
+ Item gridItem = null;
+ GetOwner().inventoryManager.items.bag.TryGetValue(move.GridIndex, out gridItem);
+ if (gridItem != null)
+ {
+ if(cacheComp.items[move.CacheGridIndex].id == "" || cacheComp.items[move.CacheGridIndex].id == gridItem.id)
+ {
+ int canAdd = 50 - cacheComp.items[move.CacheGridIndex].count;
+
+ if (canAdd >= gridItem.amount)
+ {
+ cacheComp.items[move.CacheGridIndex].id = gridItem.id;
+ cacheComp.items[move.CacheGridIndex].count += gridItem.amount;
+ GetOwner().inventoryManager.items.bag.Remove(move.GridIndex);
+ GetOwner().inventoryManager.items.UpdateBagInventoryPacket();
+ }
+ else
+ {
+ cacheComp.items[move.CacheGridIndex].id = gridItem.id;
+ cacheComp.items[move.CacheGridIndex].count += canAdd;
+ gridItem.amount-=canAdd;
+ GetOwner().inventoryManager.items.UpdateBagInventoryPacket();
+ }
+ }
+ }
+
+ }
+ GetOwner().Send(new PacketScFactoryOpRet(GetOwner(), 0, op), seq);
+ }
+
+ public void MoveNode(CsFactoryOp op, ulong seq)
+ {
+ var move = op.MoveNode;
+ FactoryNode node = nodes.Find(n => n.nodeId == move.NodeId);
+ if (node != null)
+ {
+ node.direction = new Vector3f(move.Direction);
+ node.position = new Vector3f(move.Position);
+ node.worldPosition = new Vector3f(move.InteractiveParam.Position);
+ GetOwner().Send(new PacketScFactoryModifyChapterNodes(GetOwner(), chapterId, node));
+ GetOwner().Send(new PacketScFactoryOpRet(GetOwner(), node.nodeId, op), seq);
+ node.SendEntity(GetOwner(), chapterId);
+ }
+ else
+ {
+ ScFactoryOpRet ret = new()
+ {
+ RetCode = FactoryOpRetCode.Fail,
+ };
+ GetOwner().Send(ScMsgId.ScFactoryOpRet, ret, seq);
+ }
+ }
+ public void DismantleNode(CsFactoryOp op, ulong seq)
+ {
+ var dismantle = op.Dismantle;
+
+ FactoryNode nodeRem = nodes.Find(n => n.nodeId == dismantle.NodeId);
+ if (nodeRem != null)
+ {
+ RemoveConnectionsToNode(nodeRem, nodes);
+ nodes.Remove(nodeRem);
+ GetOwner().Send(ScMsgId.ScFactoryModifyChapterMap, new ScFactoryModifyChapterMap()
+ {
+ ChapterId = chapterId,
+ MapId = nodeRem.mapId,
+ Tms = DateTime.UtcNow.ToUnixTimestampMilliseconds(),
+ Wires =
+ {
+ GetWires()
+ }
+ });
+ GetOwner().Send(new PacketScFactoryModifyChapterNodes(GetOwner(), chapterId, nodeRem.nodeId));
+ GetOwner().Send(new PacketScFactoryOpRet(GetOwner(), nodeRem.nodeId, op), seq);
+ }
+ else
+ {
+ ScFactoryOpRet ret = new()
+ {
+ RetCode = FactoryOpRetCode.Fail,
+
+ };
+ GetOwner().Send(ScMsgId.ScFactoryOpRet, ret, seq);
+ }
+ }
+ public void RemoveConnectionsToNode(FactoryNode nodeRem, List allNodes)
+ {
+ // Ottieni tutti i compId del nodo da rimuovere
+ HashSet remCompIds = nodeRem.components.Select(c => (ulong)c.compId).ToHashSet();
+
+ foreach (var node in allNodes)
+ {
+ node.connectedComps.RemoveAll(conn =>
+ remCompIds.Contains(conn.Key) || remCompIds.Contains(conn.Value));
+ }
+ }
+
+
+ public uint nextCompV()
+ {
+ compV++;
+ return compV;
+ }
+ public FComponent GetCompById(ulong compId)
+ {
+ foreach (FactoryNode node in nodes)
+ {
+ if (node.components.Find(c => c.compId == compId) != null)
+ {
+ return node.components.Find(c => c.compId == compId);
+ }
+ }
+ return null;
+ }
+ public FComponent GetCompById(ulong compId) where FComponent : class
+ {
+ foreach (FactoryNode node in nodes)
+ {
+ if (node.components.Find(c => c.compId == compId) != null)
+ {
+ return node.components.Find(c => c.compId == compId && c is FComponent) as FComponent;
+ }
+ }
+ return null;
+ }
+ public FactoryNode GetNodeByCompId(ulong compId)
+ {
+ foreach (FactoryNode node in nodes)
+ {
+ if (node.components.Find(c => c.compId == compId) != null)
+ {
+ return node;
+ }
+ }
+ return null;
+ }
+ private void AddConnection(CsFactoryOp op, ulong seq)
+ {
+ FComponent nodeFrom = GetCompById(op.AddConnection.FromComId);
+ FComponent nodeTo = GetCompById(op.AddConnection.ToComId);
+
+ if (nodeFrom != null && nodeTo != null)
+ {
+ GetNodeByCompId(nodeFrom.compId).connectedComps.Add(new(nodeFrom.compId, nodeTo.compId));
+ GetNodeByCompId(nodeTo.compId).connectedComps.Add(new(nodeTo.compId, nodeFrom.compId));
+ GetOwner().Send(ScMsgId.ScFactoryModifyChapterMap, new ScFactoryModifyChapterMap()
+ {
+ ChapterId = chapterId,
+ MapId = GetNodeByCompId(nodeFrom.compId).mapId,
+ Tms = DateTime.UtcNow.ToUnixTimestampMilliseconds(),
+ Wires =
+ {
+ GetWires()
+ }
+ });
+ var wire = GetWires().Find(w =>
+ (w.FromComId == op.AddConnection.FromComId && w.ToComId == op.AddConnection.ToComId) ||
+ (w.FromComId == op.AddConnection.ToComId && w.ToComId == op.AddConnection.FromComId));
+
+ if (wire != null)
+ {
+ GetOwner().Send(new PacketScFactoryOpRet(GetOwner(), (uint)wire.Index, op), seq);
+ }
+ else
+ {
+ // Facoltativo: log di errore
+ Console.WriteLine($"[WARN] Connessione non trovata tra {op.AddConnection.FromComId} e {op.AddConnection.ToComId}");
+ }
+
+ }
+
+ }
+ void ResetAllPower(List allNodes)
+ {
+ foreach (var node in allNodes)
+ node.powered = false;
+ }
+ void UpdatePowerGrid(List allNodes)
+ {
+ ResetAllPower(allNodes);
+
+ HashSet visited = new();
+
+ foreach (var node in allNodes)
+ {
+ if (node.templateId.Contains("hub") || node.templateId == "power_diffuser_1")
+ {
+ //if(node.forcePowerOn)
+ if (node.templateId == "power_diffuser_1")
+ {
+ //Check inside factory region
+
+ }
+ else
+ {
+ PropagatePowerFrom(node, visited);
+ }
+
+ }
+ }
+ }
+ void PropagatePowerFrom(FactoryNode node, HashSet visited)
+ {
+ if (visited.Contains(node.nodeId))
+ return;
+
+ visited.Add(node.nodeId);
+ node.powered = true;
+ if (node.templateId == "power_diffuser_1")
+ {
+ //get builds in area test
+ List nodes = GetNodesInRange(node.position, 15);
+ foreach (FactoryNode propagateNode in nodes)
+ {
+ if (propagateNode.GetComponent() == null)
+ {
+ propagateNode.powered = true;
+ }
+ }
+ }
+ if (node.GetComponent() != null)
+ foreach (var connectedCompId in node.connectedComps)
+ {
+ FactoryNode connectedNode = GetNodeByCompId(connectedCompId.Value);
+ if (connectedNode != null)
+ {
+ PropagatePowerFrom(connectedNode, visited);
+ }
+ }
+ }
+ public void PlaceConveyor(CsFactoryOp op, ulong seq)
+ {
+ var placeConveyor = op.PlaceConveyor;
+ v++;
+ uint nodeId = v;
+ List points = new();
+ foreach(var point in placeConveyor.Points)
+ {
+ points.Add(new Vector3f(point));
+ }
+ FactoryNode node = new()
+ {
+ nodeId = nodeId,
+ templateId = placeConveyor.TemplateId,
+ mapId = placeConveyor.MapId,
+ sceneNumId = GetOwner().sceneManager.GetCurScene().sceneNumId,
+ nodeType = FCNodeType.BoxConveyor,
+ position = new Vector3f(placeConveyor.Points[0]),
+ direction = new(),
+ directionIn = new Vector3f(placeConveyor.DirectionIn),
+ directionOut = new Vector3f(placeConveyor.DirectionOut),
+ worldPosition = null,
+ points = points,
+ guid = GetOwner().random.NextRand(),
+ };
+
+ node.InitComponents(this);
+ GetOwner().Send(new PacketScFactoryModifyChapterNodes(GetOwner(), chapterId, node));
+ nodes.Add(node);
+
+ GetOwner().Send(new PacketScFactoryOpRet(GetOwner(), nodeId, op), seq);
+ }
+ private void CreateNode(CsFactoryOp op, ulong seq)
+ {
+ v++;
+ uint nodeId = v;
+ CsdFactoryOpPlace place = op.Place;
+ FactoryBuildingTable table = ResourceManager.factoryBuildingTable[place.TemplateId];
+ FactoryNode node = new()
+ {
+ nodeId = nodeId,
+ templateId = place.TemplateId,
+ mapId = place.MapId,
+ sceneNumId = GetOwner().sceneManager.GetCurScene().sceneNumId,
+ nodeType = table.GetNodeType(),
+ position = new Vector3f(place.Position),
+ direction = new Vector3f(place.Direction),
+ worldPosition = new Vector3f(place.InteractiveParam.Position),
+ guid = GetOwner().random.NextRand(),
+
+ };
+
+ node.InitComponents(this);
+ GetOwner().Send(new PacketScFactoryModifyChapterNodes(GetOwner(), chapterId, node));
+ nodes.Add(node);
+ node.SendEntity(GetOwner(), chapterId);
+
+ GetOwner().Send(new PacketScFactoryOpRet(GetOwner(), node.nodeId, op), seq);
+
+ }
+
+ public FactoryChapter(string chapterId, ulong ownerId)
+ {
+ this.ownerId = ownerId;
+ this.chapterId = chapterId;
+ FactoryNode node = new()
+ {
+ nodeId = v,
+ templateId = "__inventory__",
+ nodeType = FCNodeType.Inventory,
+ mapId = 0,
+ deactive = true,
+ guid = GetOwner().random.NextRand()
+ };
+ node.InitComponents(this);
+ nodes.Add(node);
+ }
+ public Player GetOwner()
+ {
+ return Server.clients.Find(c => c.roleId == ownerId);
+ }
+ }
+}
diff --git a/Campofinale/Game/Factory/FactoryManager.cs b/Campofinale/Game/Factory/FactoryManager.cs
index d62ae5d..81f4e51 100644
--- a/Campofinale/Game/Factory/FactoryManager.cs
+++ b/Campofinale/Game/Factory/FactoryManager.cs
@@ -1,15 +1,12 @@
using Campofinale.Database;
using Campofinale.Game.Entities;
using Campofinale.Game.Factory.Components;
+using Campofinale.Network;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
using Campofinale.Resource;
-using Campofinale.Resource.Table;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
-using System.Linq;
-using System.Numerics;
-using System.Xml.Linq;
using static Campofinale.Resource.ResourceManager;
namespace Campofinale.Game.Factory
@@ -19,6 +16,7 @@ namespace Campofinale.Game.Factory
public Player player;
public List chapters = new();
public ObjectId _id;
+
public class FactoryData
{
public ulong roleId;
@@ -71,829 +69,38 @@ namespace Campofinale.Game.Factory
player.Send(ScMsgId.ScFactoryOpRet, ret, seq);
}
}
+ public void SendFactoryHsSync()
+ {
+ if (!player.Initialized) return;
+ if (player.GetCurrentChapter() == "") return;
+ List nodeUpdateList = new();
+ foreach (var node in GetChapter(player.GetCurrentChapter()).nodes)
+ {
+ if (node != null)
+ {
+ if (node.position.DistanceXZ(player.position) < 150 && node.nodeBehaviour!=null)
+ {
+ nodeUpdateList.Add(node);
+ }
+ }
+ }
+ player.Send(new PacketScFactoryHsSync(player,GetChapter(player.GetCurrentChapter()), nodeUpdateList));
+ }
public void Update()
{
+ if (!player.Initialized) return;
foreach (FactoryChapter chapter in chapters)
{
chapter.Update();
}
+
}
public FactoryChapter GetChapter(string id)
{
return chapters.Find(c=>c.chapterId==id);
}
}
- public class FactoryChapter
- {
- public string chapterId;
- public ulong ownerId;
- public List nodes=new();
- public uint v = 1;
- public uint compV = 0;
- public int bandwidth = 200;
-
- public ScFactorySyncChapter ToProto()
- {
- ScFactorySyncChapter chapter = new()
- {
- ChapterId = chapterId,
- Tms = DateTime.UtcNow.ToUnixTimestampMilliseconds()/1000,
- Blackboard = new()
- {
- Power = new()
- {
- PowerGen = 0,
- PowerSaveMax = 0,
- PowerSaveCurrent = 0,
- PowerCost = 0
- },
- InventoryNodeId = 1
- },
- Statistic = new()
- {
- LastDay = new()
- {
-
- },
- Other = new()
- {
- InPowerBuilding = 1
- }
- },
- PinBoard = new()
- {
- Cards =
- {
-
- },
-
- },
- };
- chapter.Blackboard.Power.PowerSaveCurrent = bandwidth;
- domainDataTable[chapterId].levelGroup.ForEach(levelGroup =>
- {
- int grade = GetOwner().sceneManager.GetScene(GetSceneNumIdFromLevelData(levelGroup)).grade;
- LevelGradeInfo sceneGrade = ResourceManager.levelGradeTable[levelGroup].grades.Find(g=>g.grade==grade);
- if (sceneGrade != null)
- {
- chapter.Blackboard.Power.PowerGen += sceneGrade.bandwidth;
- chapter.Blackboard.Power.PowerSaveMax += sceneGrade.bandwidth;
-
- var scene = new ScdFactorySyncScene()
- {
- SceneId = GetSceneNumIdFromLevelData(levelGroup),
-
- Bandwidth = new()
- {
- Current = 0,
- Max = sceneGrade.bandwidth,
- TravelPoleMax = sceneGrade.travelPoleLimit,
-
- BattleCurrent = 0,
- BattleMax = sceneGrade.battleBuildingLimit,
- },
- Settlements =
- {
-
- },
-
- Panels =
- {
-
- }
- };
- int index = 0;
- LevelScene scen = GetLevelData(GetSceneNumIdFromLevelData(levelGroup));
- foreach (var reg in scen.levelData.factoryRegions)
- {
- foreach (var area in reg.areas)
- {
- var lvData = area.levelData.Find(l=>l.level==grade);
- if (lvData == null)
- {
- lvData = area.levelData.Last();
- }
- if (lvData.levelBounds.Count > 0)
- {
- var bounds = lvData.levelBounds[0];
- scene.Panels.Add(new ScdFactorySyncScenePanel()
- {
- Index = index,
- Level = lvData.level,
- MainMesh =
- {
- new ScdRectInt()
- {
- X=(int)bounds.start.x,
- Z=(int)bounds.start.z,
- Y=(int)bounds.start.y,
- W=(int)bounds.size.x,
- H=(int)bounds.size.y,
- L=(int)bounds.size.z,
- }
- }
- });
- index++;
- }
-
- }
- }
- chapter.Scenes.Add(scene);
- }
-
- });
- nodes.ForEach(node =>
- {
- chapter.Nodes.Add(node.ToProto());
- });
- chapter.Maps.AddRange(GetMaps());
- return chapter;
- }
- public List GetMaps()
- {
- List maps = new();
- string levelId = domainDataTable[chapterId].levelGroup[0];
- string mapId = GetLevelData(GetSceneNumIdFromLevelData(levelId)).mapIdStr;
- maps.Add(new ScdFactorySyncMap()
- {
- MapId = ResourceManager.strIdNumTable.chapter_map_id.dic[mapId],
- Wires =
- {
- GetWires()
- }
- });
- return maps;
- }
-
- public List GetWires()
- {
- List wires = new();
- HashSet<(ulong, ulong)> addedConnections = new(); // evita doppioni esatti
- ulong i = 0;
-
- foreach (FactoryNode node in nodes)
- {
- foreach (var conn in node.connectedComps)
- {
- ulong compA = conn.Key;
- ulong compB = conn.Value;
-
- var key = (compA, compB);
-
- if (!addedConnections.Contains(key))
- {
- wires.Add(new ScdFactorySyncMapWire()
- {
- Index = i,
- FromComId = compA,
- ToComId = compB
- });
-
- addedConnections.Add(key);
- i++;
- }
- }
- }
-
- return wires;
- }
-
-
- public void Update()
- {
- try
- {
- UpdatePowerGrid(nodes);
- foreach (FactoryNode node in nodes)
- {
- node.Update(this);
- }
- }
- catch (Exception e)
- {
-
- }
-
- }
- public List GetNodesInRange(Vector3f pos,float range)
- {
- return nodes.FindAll(n => n.position.Distance(pos) <= range);
- }
-
- public void ExecOp(CsFactoryOp op, ulong seq)
- {
-
- switch (op.OpType)
- {
- case FactoryOpType.Place:
- CreateNode(op, seq);
- break;
- case FactoryOpType.MoveNode:
- MoveNode(op, seq);
- break;
- case FactoryOpType.Dismantle:
- DismantleNode(op, seq);
- break;
- case FactoryOpType.AddConnection:
- AddConnection(op, seq);
- break;
- case FactoryOpType.SetTravelPoleDefaultNext:
- FactoryNode travelNode = GetNodeByCompId(op.SetTravelPoleDefaultNext.ComponentId);
- travelNode.GetComponent().defaultNext = op.SetTravelPoleDefaultNext.DefaultNext;
- GetOwner().Send(new PacketScFactoryModifyChapterNodes(GetOwner(), chapterId, travelNode));
- GetOwner().Send(new PacketScFactoryOpRet(GetOwner(), 0, op), seq);
- break;
- default:
- break;
- }
-
- }
- public void MoveNode(CsFactoryOp op, ulong seq)
- {
- var move = op.MoveNode;
- FactoryNode node = nodes.Find(n => n.nodeId == move.NodeId);
- if (node != null)
- {
- node.direction = new Vector3f(move.Direction);
- node.position = new Vector3f(move.Position);
- node.worldPosition = new Vector3f(move.InteractiveParam.Position);
- GetOwner().Send(new PacketScFactoryModifyChapterNodes(GetOwner(), chapterId, node));
- GetOwner().Send(new PacketScFactoryOpRet(GetOwner(), node.nodeId, op), seq);
- node.SendEntity(GetOwner(), chapterId);
- }
- else
- {
- ScFactoryOpRet ret = new()
- {
- RetCode = FactoryOpRetCode.Fail,
- };
- GetOwner().Send(ScMsgId.ScFactoryOpRet, ret, seq);
- }
- }
- public void DismantleNode(CsFactoryOp op, ulong seq)
- {
- var dismantle = op.Dismantle;
-
- FactoryNode nodeRem = nodes.Find(n => n.nodeId == dismantle.NodeId);
- if (nodeRem != null)
- {
- RemoveConnectionsToNode(nodeRem, nodes);
- nodes.Remove(nodeRem);
- GetOwner().Send(ScMsgId.ScFactoryModifyChapterMap, new ScFactoryModifyChapterMap()
- {
- ChapterId = chapterId,
- MapId = nodeRem.mapId,
- Tms = DateTime.UtcNow.ToUnixTimestampMilliseconds() / 1000,
- Wires =
- {
- GetWires()
- }
- });
- GetOwner().Send(new PacketScFactoryModifyChapterNodes(GetOwner(), chapterId, nodeRem.nodeId));
- GetOwner().Send(new PacketScFactoryOpRet(GetOwner(), nodeRem.nodeId, op), seq);
- }
- else
- {
- ScFactoryOpRet ret = new()
- {
- RetCode = FactoryOpRetCode.Fail,
-
- };
- GetOwner().Send(ScMsgId.ScFactoryOpRet, ret, seq);
- }
- }
- public void RemoveConnectionsToNode(FactoryNode nodeRem, List allNodes)
- {
- // Ottieni tutti i compId del nodo da rimuovere
- HashSet remCompIds = nodeRem.components.Select(c => (ulong)c.compId).ToHashSet();
-
- foreach (var node in allNodes)
- {
- node.connectedComps.RemoveAll(conn =>
- remCompIds.Contains(conn.Key) || remCompIds.Contains(conn.Value));
- }
- }
-
-
- public uint nextCompV()
- {
- compV++;
- return compV;
- }
- public FactoryNode.FComponent GetCompById(ulong compId)
- {
- foreach(FactoryNode node in nodes)
- {
- if (node.components.Find(c => c.compId == compId) != null)
- {
- return node.components.Find(c => c.compId == compId);
- }
- }
- return null;
- }
- public FactoryNode GetNodeByCompId(ulong compId)
- {
- foreach (FactoryNode node in nodes)
- {
- if (node.components.Find(c => c.compId == compId) != null)
- {
- return node;
- }
- }
- return null;
- }
- private void AddConnection(CsFactoryOp op,ulong seq)
- {
- FactoryNode.FComponent nodeFrom = GetCompById(op.AddConnection.FromComId);
- FactoryNode.FComponent nodeTo = GetCompById(op.AddConnection.ToComId);
-
- if(nodeFrom!=null && nodeTo != null)
- {
- GetNodeByCompId(nodeFrom.compId).connectedComps.Add(new(nodeFrom.compId, nodeTo.compId));
- GetNodeByCompId(nodeTo.compId).connectedComps.Add(new(nodeTo.compId, nodeFrom.compId));
- GetOwner().Send(ScMsgId.ScFactoryModifyChapterMap, new ScFactoryModifyChapterMap()
- {
- ChapterId = chapterId,
- MapId = GetNodeByCompId(nodeFrom.compId).mapId,
- Tms = DateTime.UtcNow.ToUnixTimestampMilliseconds()/1000,
- Wires =
- {
- GetWires()
- }
- });
- var wire = GetWires().Find(w =>
- (w.FromComId == op.AddConnection.FromComId && w.ToComId == op.AddConnection.ToComId) ||
- (w.FromComId == op.AddConnection.ToComId && w.ToComId == op.AddConnection.FromComId));
-
- if (wire != null)
- {
- GetOwner().Send(new PacketScFactoryOpRet(GetOwner(), (uint)wire.Index, op), seq);
- }
- else
- {
- // Facoltativo: log di errore
- Console.WriteLine($"[WARN] Connessione non trovata tra {op.AddConnection.FromComId} e {op.AddConnection.ToComId}");
- }
-
- }
-
- }
- void ResetAllPower(List allNodes)
- {
- foreach (var node in allNodes)
- node.powered = false;
- }
- void UpdatePowerGrid(List allNodes)
- {
- ResetAllPower(allNodes);
-
- HashSet visited = new();
-
- foreach (var node in allNodes)
- {
- if (node.templateId.Contains("hub") || node.templateId == "power_diffuser_1")
- {
- //if(node.forcePowerOn)
- if(node.templateId== "power_diffuser_1")
- {
- //Check inside factory region
-
- }
- else
- {
- PropagatePowerFrom(node, visited);
- }
-
- }
- }
- }
- void PropagatePowerFrom(FactoryNode node, HashSet visited)
- {
- if (visited.Contains(node.nodeId))
- return;
-
- visited.Add(node.nodeId);
- node.powered = true;
- if(node.templateId == "power_diffuser_1")
- {
- //get builds in area test
- List nodes=GetNodesInRange(node.position, 15);
- foreach(FactoryNode propagateNode in nodes)
- {
- if (propagateNode.GetComponent() == null)
- {
- propagateNode.powered = true;
- }
- }
- }
- if (node.GetComponent() != null)
- foreach (var connectedCompId in node.connectedComps)
- {
- FactoryNode connectedNode = GetNodeByCompId(connectedCompId.Value);
- if (connectedNode != null)
- {
- PropagatePowerFrom(connectedNode, visited);
- }
- }
- }
- private void CreateNode(CsFactoryOp op, ulong seq)
- {
- v++;
- uint nodeId = v;
- CsdFactoryOpPlace place = op.Place;
- FactoryBuildingTable table = ResourceManager.factoryBuildingTable[place.TemplateId];
- FactoryNode node = new()
- {
- nodeId = nodeId,
- templateId = place.TemplateId,
- mapId = place.MapId,
- sceneNumId = GetOwner().sceneManager.GetCurScene().sceneNumId,
- nodeType = table.GetNodeType(),
- position = new Vector3f(place.Position),
- direction = new Vector3f(place.Direction),
- worldPosition = new Vector3f(place.InteractiveParam.Position),
- guid = GetOwner().random.NextRand(),
-
- };
-
- node.InitComponents(this);
- GetOwner().Send(new PacketScFactoryModifyChapterNodes(GetOwner(), chapterId, node));
- nodes.Add(node);
- node.SendEntity(GetOwner(), chapterId);
-
- GetOwner().Send(new PacketScFactoryOpRet(GetOwner(), node.nodeId,op),seq);
-
- }
-
- public FactoryChapter(string chapterId,ulong ownerId)
- {
- this.ownerId = ownerId;
- this.chapterId = chapterId;
- FactoryNode node = new()
- {
- nodeId = v,
- templateId= "__inventory__",
- nodeType=FCNodeType.Inventory,
- mapId=0,
- deactive=true,
- guid = GetOwner().random.NextRand()
- };
- node.InitComponents(this);
- nodes.Add(node);
- }
- public Player GetOwner()
- {
- return Server.clients.Find(c => c.roleId == ownerId);
- }
- }
- public class FactoryNode
- {
- public uint nodeId;
- public FCNodeType nodeType;
- public string templateId;
- public Vector3f position=new();
- public Vector3f direction = new();
- public Vector3f worldPosition = new();
- public string instKey="";
- public bool deactive = false;
- public int mapId;
- public int sceneNumId;
- public bool forcePowerOn = false;
- public List components = new();
- [BsonIgnore]
- public bool powered = false;
- [BsonIgnore]
- public bool lastPowered = false;
- public List connectedComps = new();
- public ulong guid;
-
- public class ConnectedComp
- {
- public ulong Key;
- public ulong Value;
- public ConnectedComp(ulong key, ulong value)
- {
- this.Key = key;
- this.Value = value;
- }
- }
- public void Update(FactoryChapter chapter)
- {
- LevelScene scen = GetLevelData(sceneNumId);
- if (lastPowered != powered)
- {
- lastPowered = powered;
- chapter.GetOwner().Send(new PacketScFactoryModifyChapterNodes(chapter.GetOwner(), chapter.chapterId, this));
- }
-
- }
- public bool InPower()
- {
- if (forcePowerOn)
- {
- return true;
- }
- return powered;
- }
- public FComponent GetComponent() where FComponent : class
- {
- return components.Find(c => c is FComponent) as FComponent;
- }
- public FMesh GetMesh()
- {
- FMesh mesh = new FMesh();
-
- if (ResourceManager.factoryBuildingTable.TryGetValue(templateId, out FactoryBuildingTable table))
- {
- float width = table.range.width - 1;
- float height = table.range.height - 1;
- float depth = table.range.depth-1;
-
- Vector3f p1_final = new Vector3f();
- Vector3f p2_final = new Vector3f();
-
- switch (direction.y)
- {
- case 0f:
- case 360f:
- default:
- p1_final = position + new Vector3f(table.range.x, table.range.y, table.range.z);
- p2_final = p1_final + new Vector3f(width, height, depth);
- break;
-
- case 90f:
- // Rotazione 90°: Larghezza e profondità si scambiano.
- // Il mesh parte da 'position' ma si estende su assi diversi.
- p1_final = position + new Vector3f(table.range.x, table.range.y, table.range.z - width);
- p2_final = p1_final + new Vector3f(depth, height, width);
- break;
-
- case 180f:
- // Rotazione 180°: Larghezza e profondità mantengono i loro valori
- // ma il mesh si estende in direzioni negative.
- p1_final = position + new Vector3f(table.range.x - width, table.range.y, table.range.z - depth);
- p2_final = p1_final + new Vector3f(width, height, depth);
- break;
-
- case 270f:
- // Rotazione 270°: Larghezza e profondità si scambiano.
- // Il mesh si estende in direzioni diverse rispetto alla rotazione di 90°.
- p1_final = position + new Vector3f(table.range.x - depth, table.range.y, table.range.z);
- p2_final = p1_final + new Vector3f(depth, height, width);
- break;
- }
-
- mesh.points.Add(p1_final);
- mesh.points.Add(p2_final);
- }
-
- return mesh;
- }
-
-
- public ScdFacNode ToProto()
- {
- ScdFacNode node = new ScdFacNode()
- {
- InstKey = instKey,
- NodeId=nodeId,
- TemplateId=templateId,
- StableId= GetStableId(),
- IsDeactive= deactive,
-
- Power = new()
- {
- InPower= InPower(),
- NeedInPower=true,
- },
-
- NodeType=(int)nodeType,
- Transform = new()
- {
- Position = position.ToProtoScd(),
- Direction=direction.ToProtoScd(),
- MapId=mapId,
-
-
- }
- };
- if(templateId!="__inventory__")
- {
- node.Transform.Mesh = GetMesh().ToProto();
- node.Transform.Position = position.ToProtoScd();
- node.Transform.WorldPosition = worldPosition.ToProto();
- node.Transform.WorldRotation = direction.ToProto();
- node.InteractiveObject = new()
- {
- ObjectId=guid,
- };
- node.Flag = 0;
- node.InstKey = "";
- }
- foreach(FComponent comp in components)
- {
- node.Components.Add(comp.ToProto());
- node.ComponentPos.Add((int)comp.GetComPos(), comp.compId);
- }
-
- return node;
- }
- public uint GetStableId()
- {
- return 10000+nodeId;
- }
- public FCComponentType GetMainCompType()
- {
- string nodeTypeName = nodeType.ToString();
- if (Enum.TryParse(nodeTypeName, out FCComponentType fromName))
- {
- return fromName;
- }
- return FCComponentType.Invalid;
- }
- public void InitComponents(FactoryChapter chapter)
- {
- switch (nodeType)
- {
- case FCNodeType.PowerPole:
- components.Add(new FComponentPowerPole(chapter.nextCompV()).Init());
- break;
- case FCNodeType.PowerDiffuser:
- components.Add(new FComponentPowerPole(chapter.nextCompV()).Init());
- break;
- case FCNodeType.TravelPole:
- components.Add(new FComponentTravelPole(chapter.nextCompV()).Init());
- break;
- case FCNodeType.Hub:
- components.Add(new FComponentSelector(chapter.nextCompV()).Init());
- components.Add(new FComponentPowerPole(chapter.nextCompV()).Init());
- components.Add(new FComponentPowerSave(chapter.nextCompV()).Init());
- components.Add(new FComponentStablePower(chapter.nextCompV()).Init());
- components.Add(new FComponentBusLoader(chapter.nextCompV()).Init());
- components.Add(new FComponentPortManager(chapter.nextCompV(),GetComponent().compId).Init());
- forcePowerOn = true;
- break;
- case FCNodeType.SubHub:
- components.Add(new FComponentSubHub(chapter.nextCompV()).Init());
- components.Add(new FComponentSelector(chapter.nextCompV()).Init());
- components.Add(new FComponentPowerPole(chapter.nextCompV()).Init());
- components.Add(new FComponentPowerSave(chapter.nextCompV()).Init());
- components.Add(new FComponentStablePower(chapter.nextCompV()).Init());
- components.Add(new FComponentBusLoader(chapter.nextCompV()).Init());
- components.Add(new FComponentPortManager(chapter.nextCompV(), GetComponent().compId).Init());
- forcePowerOn = true;
- break;
- default:
- components.Add(new FComponent(chapter.nextCompV(), GetMainCompType()).Init());
- break;
- }
-
- }
-
- public void SendEntity(Player player, string chapterId)
- {
- Entity exist = player.sceneManager.GetCurScene().entities.Find(e => e.guid == guid);
- if (exist != null)
- {
- exist.Position = worldPosition;
- exist.Rotation = direction;
- ScMoveObjectMove move = new()
- {
- ServerNotify = true,
- MoveInfo =
- {
- new MoveObjectMoveInfo()
- {
- Objid = guid,
- SceneNumId=sceneNumId,
- MotionInfo = new()
- {
- Position=exist.Position.ToProto(),
- Rotation=exist.Rotation.ToProto(),
- Speed=new Vector()
- {
-
- },
- State=MotionState.MotionNone
- }
- }
- }
- };
- player.Send(ScMsgId.ScMoveObjectMove, move);
- }
- else
- {
- EntityInteractive e = new(interactiveFacWrapperTable[templateId].interactiveTemplateId, player.roleId, worldPosition, direction, sceneNumId, guid);
- e.InitDefaultProperties();
- e.SetPropValue(nodeId, "factory_inst_id");
-
- player.sceneManager.GetCurScene().entities.Add(e);
- player.sceneManager.GetCurScene().SpawnEntity(e);
- }
-
- }
-
- [BsonDiscriminator(Required = true)]
- [BsonKnownTypes(typeof(FComponentSelector))]
-
- public class FComponent
- {
- public class FCompInventory
- {
- public ScdFacComInventory ToProto()
- {
- return new ScdFacComInventory()
- {
-
- };
- }
- }
- public uint compId;
- public FCComponentType type;
- public FCompInventory inventory;
-
- public FComponent(uint id, FCComponentType t)
- {
- this.compId = id;
- this.type = t;
- }
- public FCComponentPos GetComPos()
- {
-
- string compTypeName = type.ToString();
- if (Enum.TryParse(compTypeName, out FCComponentPos fromName))
- {
- return fromName;
- }
- switch (type)
- {
- case FCComponentType.PowerPole:
- return FCComponentPos.PowerPole;
- }
- return FCComponentPos.Invalid;
- }
- public ScdFacCom ToProto()
- {
- ScdFacCom proto = new ScdFacCom()
- {
- ComponentType = (int)type,
- ComponentId = compId,
-
- };
- SetComponentInfo(proto);
- return proto;
- }
-
- public virtual void SetComponentInfo(ScdFacCom proto)
- {
- if (inventory != null)
- {
- proto.Inventory = inventory.ToProto();
- }
- else if (type == FCComponentType.PowerPole)
- {
- proto.PowerPole = new()
- {
-
- };
- }
- }
-
- public virtual FComponent Init()
- {
- switch (type)
- {
- case FCComponentType.Inventory:
- inventory = new();
- break;
- default:
- break;
- }
- return this;
- }
- }
- public class FMesh
- {
- public FCMeshType type;
- public List points=new();
- public ScdFacMesh ToProto()
- {
- ScdFacMesh m = new ScdFacMesh()
- {
- MeshType = (int)type
- };
- foreach (Vector3f p in points)
- {
- m.Points.Add(new ScdVec3Int()
- {
- X = (int)p.x,
- Y = (int)p.y,
- Z = (int)p.z
- });
- }
- return m;
- }
- }
- }
+
+
}
diff --git a/Campofinale/Game/Factory/FactoryNode.cs b/Campofinale/Game/Factory/FactoryNode.cs
new file mode 100644
index 0000000..d469806
--- /dev/null
+++ b/Campofinale/Game/Factory/FactoryNode.cs
@@ -0,0 +1,598 @@
+using Campofinale.Game.Entities;
+using Campofinale.Game.Factory.Components;
+using Campofinale.Packets.Sc;
+using Campofinale.Protocol;
+using Campofinale.Resource.Table;
+using Campofinale.Resource;
+using MongoDB.Bson.Serialization.Attributes;
+using static Campofinale.Resource.ResourceManager;
+using Campofinale.Game.Factory.BuildingsBehaviour;
+using static Campofinale.Resource.ResourceManager.FactoryBuildingTable;
+using Newtonsoft.Json;
+using System.Drawing;
+using Campofinale.Game.Inventory;
+using System.Numerics;
+
+namespace Campofinale.Game.Factory
+{
+ public class FactoryNode
+ {
+ public uint nodeId;
+ public FCNodeType nodeType;
+ public string templateId;
+ public Vector3f position = new();
+ public Vector3f direction = new();
+ public Vector3f worldPosition = new();
+
+ public Vector3f directionIn;
+ public Vector3f directionOut;
+ public string instKey = "";
+ public bool deactive = false;
+ public int mapId;
+ public int sceneNumId;
+ public bool forcePowerOn = false;
+ public List components = new();
+ //Conveyor only
+ public List points;
+ public bool powered = false;
+ public bool lastPowered = false;
+ public List connectedComps = new();
+ public ulong guid;
+ public NodeBuildingBehaviour nodeBehaviour;
+ public class ConnectedComp
+ {
+ public ulong Key;
+ public ulong Value;
+ public ConnectedComp(ulong key, ulong value)
+ {
+ this.Key = key;
+ this.Value = value;
+ }
+ }
+ public void Update(FactoryChapter chapter)
+ {
+ LevelScene scen = GetLevelData(sceneNumId);
+ if (lastPowered != powered)
+ {
+ lastPowered = powered;
+ chapter.GetOwner().Send(new PacketScFactoryModifyChapterNodes(chapter.GetOwner(), chapter.chapterId, this));
+ }
+ if (nodeBehaviour != null && !deactive)
+ {
+ nodeBehaviour.Update(chapter,this);
+ }
+ foreach (var comp in components.FindAll(c => c is FComponentPortManager))
+ {
+ var portmanager = (FComponentPortManager)comp;
+ if (portmanager.customPos != FCComponentPos.PortOutManager)
+ {
+ UpdatePortManager(chapter, portmanager);
+ }
+ }
+ foreach (var comp in components.FindAll(c => c is FComponentPortManager))
+ {
+ var portmanager = (FComponentPortManager)comp;
+ if (portmanager.customPos == FCComponentPos.PortOutManager)
+ {
+ UpdatePortManager(chapter, portmanager);
+ }
+ }
+
+ }
+ public FactoryBuildingTable GetBuildingTable()
+ {
+ ResourceManager.factoryBuildingTable.TryGetValue(templateId, out FactoryBuildingTable table);
+ if (table == null)
+ {
+ table = new FactoryBuildingTable();
+ }
+ return table;
+ }
+ public void UpdatePortManager(FactoryChapter chapter,FComponentPortManager manager)
+ {
+ if (ResourceManager.factoryBuildingTable.TryGetValue(templateId, out FactoryBuildingTable table))
+ {
+ List ports = new();
+ if (manager.customPos == FCComponentPos.PortOutManager)
+ {
+ ports = GetTransformedPorts(table.outputPorts);
+ List conveyors = chapter.nodes.FindAll(n => n.points != null);
+ foreach (var port in ports)
+ {
+ Vector3f front = port.GetFront();
+ FactoryNode node = conveyors.Find(c =>
+ c.nodeType == FCNodeType.BoxConveyor &&
+ c.points.Any(p => p.x == front.x && p.y == front.y && p.z == front.z));
+ var compPort = manager.ports.Find(p => p.index == port.index);
+ if (compPort != null)
+ {
+ if (node != null)
+ {
+ compPort.touchComId = node.GetComponent().compId;
+ }
+ else
+ {
+ compPort.touchComId = 0;
+ }
+ }
+
+ }
+ //Output items
+ foreach (var port in manager.ports)
+ {
+ FComponentBoxConveyor output = chapter.GetCompById(port.touchComId);
+ FComponentCache outputCache = chapter.GetCompById(port.ownerComId);
+ FactoryNode conveyorNode = chapter.GetNodeByCompId(port.touchComId);
+ if (outputCache != null && output != null && conveyorNode != null)
+ {
+ bool did = false;
+ outputCache.items.ForEach(i =>
+ {
+ if (!did && i.count > 0)
+ {
+ ItemCount add = new ItemCount()
+ {
+ id = i.id,
+ count = 1
+ };
+
+ if (conveyorNode.AddConveyorItem(chapter,add))
+ {
+ did = true;
+ outputCache.ConsumeItems(new List() { add });
+ }
+
+ }
+ });
+ }
+ }
+
+ }
+ else
+ {
+ ports = GetTransformedPorts(table.inputPorts);
+ List conveyors = chapter.nodes.FindAll(n => n.points != null);
+ foreach (var port in ports)
+ {
+ Vector3f back = port.GetBack();
+ FactoryNode node = conveyors.Find(c =>
+ c.nodeType == FCNodeType.BoxConveyor &&
+ c.points.Any(p => p.x == back.x && p.y == back.y && p.z == back.z));
+ var compPort = manager.ports.Find(p => p.index == port.index);
+
+ if (compPort != null)
+ {
+ if (node != null)
+ {
+ compPort.touchComId = node.GetComponent().compId;
+ }
+ else
+ {
+ compPort.touchComId = 0;
+ }
+ }
+
+ }
+
+ //Input items
+ foreach (var port in manager.ports)
+ {
+ FComponentBoxConveyor input = chapter.GetCompById(port.touchComId);
+ FComponentCache inputCache = chapter.GetCompById(port.ownerComId);
+ FactoryNode conveyorNode = chapter.GetNodeByCompId(port.touchComId);
+ if (inputCache != null && input != null && conveyorNode != null)
+ {
+ bool did = false;
+ ItemCount toRemove = null;
+ foreach (var item in input.items)
+ {
+ if (!did && item.count > 0 && item.IsItemAtConveyorEnd(BlockCalculator.CalculateTotalBlocks(conveyorNode.points)))
+ {
+
+ if (!inputCache.IsFull())
+ {
+ did = true;
+ toRemove = item;
+ inputCache.AddItem(item.id, item.count);
+ break;
+ }
+
+ }
+ }
+ if(toRemove!=null)
+ conveyorNode.RemoveConveyorItem(chapter,toRemove);
+
+ }
+ }
+ }
+ }
+
+ }
+
+ private void RemoveConveyorItem(FactoryChapter chapter,ItemCount toRemove)
+ {
+ FComponentBoxConveyor conveyorComp = GetComponent();
+ conveyorComp.items.Remove(toRemove);
+ chapter.GetOwner().Send(new PacketScFactoryHsSync(chapter.GetOwner(), chapter, new List() { this}));
+ }
+
+ private bool AddConveyorItem(FactoryChapter chapter,ItemCount i)
+ {
+ float length=BlockCalculator.CalculateTotalBlocks(points);
+ FComponentBoxConveyor conveyorComp = GetComponent();
+ if (conveyorComp != null)
+ {
+ if(conveyorComp.items.Count < (int)length)
+ {
+ long timestamp = i.tms - conveyorComp.lastPopTms;
+ if(timestamp >= 2000)
+ {
+ conveyorComp.items.Add(i);
+ i.tms = DateTime.UtcNow.ToUnixTimestampMilliseconds();
+ conveyorComp.lastPopTms = i.tms;
+ chapter.GetOwner().Send(new PacketScFactoryHsSync(chapter.GetOwner(), chapter, new List() { this }));
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+
+
+ }
+ }
+ return false;
+ }
+
+ public bool InPower()
+ {
+ if (forcePowerOn)
+ {
+ return true;
+ }
+ return lastPowered;
+ }
+ public FComponent GetComponent() where FComponent : class
+ {
+ return components.Find(c => c is FComponent) as FComponent;
+ }
+ public FComponent GetComponent(uint compid) where FComponent : class
+ {
+ return components.Find(c => c is FComponent && c.compId==compid) as FComponent;
+ }
+ public List GetTransformedPorts(List originalPorts)
+ {
+ List transformedPorts = new List();
+
+ if (originalPorts == null || originalPorts.Count == 0)
+ return transformedPorts;
+
+ FMesh mesh = GetMesh();
+ if (mesh.points.Count < 2)
+ return transformedPorts;
+
+ Vector3f objectPosition = mesh.points[0];
+ float objectRotationY = direction.y % 360f;
+
+ FactoryBuildingTable table;
+ if (!ResourceManager.factoryBuildingTable.TryGetValue(templateId, out table))
+ return transformedPorts;
+
+ float width = table.range.width - 1;
+ float depth = table.range.depth - 1;
+
+ foreach (FacPort originalPort in originalPorts)
+ {
+ FacPort transformedPort = new FacPort
+ {
+ index = originalPort.index,
+ isOutput = originalPort.isOutput,
+ isPipe = originalPort.isPipe,
+ trans = new FacPort.FacPortTrans()
+ };
+
+ Vector3f originalPos = originalPort.trans.position;
+ Vector3f transformedPos = objectPosition;
+
+ switch ((int)objectRotationY)
+ {
+ case 0:
+ transformedPos += originalPos;
+ break;
+
+ case 90:
+ transformedPos += new Vector3f(originalPos.z, originalPos.y, width - originalPos.x);
+ break;
+
+ case 180:
+ transformedPos += new Vector3f(width - originalPos.x, originalPos.y, depth - originalPos.z);
+ break;
+
+ case 270:
+ transformedPos += new Vector3f(depth - originalPos.z, originalPos.y, originalPos.x);
+ break;
+ }
+
+ transformedPort.trans.position = transformedPos;
+
+ transformedPort.trans.rotation = new Vector3f(
+ originalPort.trans.rotation.x,
+ (originalPort.trans.rotation.y + objectRotationY) % 360f,
+ originalPort.trans.rotation.z
+ );
+
+ transformedPorts.Add(transformedPort);
+ }
+
+ return transformedPorts;
+ }
+
+ public FMesh GetMesh()
+ {
+ FMesh mesh = new FMesh();
+ if(points != null)
+ {
+ points.ForEach(p =>
+ {
+ mesh.points.Add(p);
+ });
+ mesh.type = FCMeshType.Line;
+ return mesh;
+ }
+ if (ResourceManager.factoryBuildingTable.TryGetValue(templateId, out FactoryBuildingTable table))
+ {
+ float width = table.range.width - 1;
+ float height = table.range.height - 1;
+ float depth = table.range.depth - 1;
+
+ Vector3f p1_final = new Vector3f();
+ Vector3f p2_final = new Vector3f();
+
+ switch (direction.y)
+ {
+ case 0f:
+ case 360f:
+ default:
+ p1_final = position + new Vector3f(table.range.x, table.range.y, table.range.z);
+ p2_final = p1_final + new Vector3f(width, height, depth);
+ break;
+
+ case 90f:
+ p1_final = position + new Vector3f(table.range.x, table.range.y, table.range.z - width);
+ p2_final = p1_final + new Vector3f(depth, height, width);
+ break;
+
+ case 180f:
+ p1_final = position + new Vector3f(table.range.x - width, table.range.y, table.range.z - depth);
+ p2_final = p1_final + new Vector3f(width, height, depth);
+ break;
+
+ case 270f:
+ p1_final = position + new Vector3f(table.range.x - depth, table.range.y, table.range.z);
+ p2_final = p1_final + new Vector3f(depth, height, width);
+ break;
+ }
+
+ mesh.points.Add(p1_final);
+ mesh.points.Add(p2_final);
+ }
+
+ return mesh;
+ }
+
+
+ public ScdFacNode ToProto()
+ {
+ ScdFacNode node = new ScdFacNode()
+ {
+ InstKey = instKey,
+ NodeId = nodeId,
+ TemplateId = templateId,
+ StableId = GetStableId(),
+ IsDeactive = deactive,
+
+ Power = new()
+ {
+ InPower = InPower(),
+ NeedInPower = true,
+ PowerCost= GetBuildingTable().bandwidth,
+ PowerCostShow= GetBuildingTable().bandwidth,
+ },
+
+ NodeType = (int)nodeType,
+ Transform = new()
+ {
+ Position = position.ToProtoScd(),
+ Direction = direction.ToProtoScd(),
+ MapId = mapId,
+
+ }
+ };
+
+ if (templateId != "__inventory__")
+ {
+ if(nodeType != FCNodeType.BoxConveyor)
+ {
+ node.Transform.Mesh = GetMesh().ToProto();
+ node.Transform.Position = position.ToProtoScd();
+ node.Transform.WorldPosition = worldPosition.ToProto();
+ node.Transform.WorldRotation = direction.ToProto();
+ node.InteractiveObject = new()
+ {
+ ObjectId = guid,
+ };
+ node.Flag = 0;
+ node.InstKey = "";
+ }
+ else
+ {
+ node.Transform.Mesh = GetMesh().ToProto();
+ node.Transform.Position = position.ToProtoScd();
+ node.Transform.WorldPosition = null;
+ node.Transform.WorldRotation = null;
+ node.InteractiveObject =null;
+ node.Transform.BcPortIn = new()
+ {
+ Direction = directionIn.ToProtoScd(),
+ Position = points[0].ToProtoScd()
+ };
+ node.Transform.BcPortOut = new()
+ {
+ Direction = directionOut.ToProtoScd(),
+ Position = points[points.Count-1].ToProtoScd()
+ };
+ node.Flag = 0;
+ node.InstKey = "";
+ }
+
+ }
+
+ foreach (FComponent comp in components)
+ {
+ node.Components.Add(comp.ToProto());
+ node.ComponentPos.Add((int)comp.GetComPos(), comp.compId);
+ }
+
+ return node;
+ }
+ public uint GetStableId()
+ {
+ return 10000 + nodeId;
+ }
+ public FCComponentType GetMainCompType()
+ {
+ string nodeTypeName = nodeType.ToString();
+ if (Enum.TryParse(nodeTypeName, out FCComponentType fromName))
+ {
+ return fromName;
+ }
+ return FCComponentType.Invalid;
+ }
+ public void InitComponents(FactoryChapter chapter)
+ {
+ switch (nodeType)
+ {
+ case FCNodeType.PowerPole:
+ components.Add(new FComponentPowerPole(chapter.nextCompV()).Init());
+ break;
+ case FCNodeType.PowerDiffuser:
+ components.Add(new FComponentPowerPole(chapter.nextCompV()).Init());
+ break;
+ case FCNodeType.Battle:
+ components.Add(new FComponentBattle(chapter.nextCompV()).Init());
+ break;
+ case FCNodeType.Producer:
+ if (templateId == "grinder_1")
+ {
+ nodeBehaviour = new NodeBuilding_Producer();
+ }else if (templateId == "furnance_1")
+ {
+ nodeBehaviour = new NodeBuilding_ProducerFurnace();
+ }
+ if(nodeBehaviour!=null)
+ nodeBehaviour.Init(chapter, this);
+ break;
+ case FCNodeType.BoxConveyor:
+ components.Add(new FComponentBoxConveyor(chapter.nextCompV()).Init());
+ break;
+ case FCNodeType.TravelPole:
+ components.Add(new FComponentTravelPole(chapter.nextCompV()).Init());
+ break;
+ case FCNodeType.Hub:
+ components.Add(new FComponentSelector(chapter.nextCompV()).Init());
+ components.Add(new FComponentPowerPole(chapter.nextCompV()).Init());
+ components.Add(new FComponentPowerSave(chapter.nextCompV()).Init());
+ components.Add(new FComponentStablePower(chapter.nextCompV()).Init());
+ components.Add(new FComponentBusLoader(chapter.nextCompV()).Init());
+ components.Add(new FComponentPortManager(chapter.nextCompV(), GetComponent().compId).Init());
+ forcePowerOn = true;
+ break;
+ case FCNodeType.SubHub:
+ components.Add(new FComponentSubHub(chapter.nextCompV()).Init());
+ components.Add(new FComponentSelector(chapter.nextCompV()).Init());
+ components.Add(new FComponentPowerPole(chapter.nextCompV()).Init());
+ components.Add(new FComponentPowerSave(chapter.nextCompV()).Init());
+ components.Add(new FComponentStablePower(chapter.nextCompV()).Init());
+ components.Add(new FComponentBusLoader(chapter.nextCompV()).Init());
+ components.Add(new FComponentPortManager(chapter.nextCompV(), GetComponent().compId).Init());
+ forcePowerOn = true;
+ break;
+ default:
+ components.Add(new FComponent(chapter.nextCompV(), GetMainCompType()).Init());
+ break;
+ }
+
+ }
+
+ public void SendEntity(Player player, string chapterId)
+ {
+ Entity exist = player.sceneManager.GetCurScene().entities.Find(e => e.guid == guid);
+ if (exist != null)
+ {
+ exist.Position = worldPosition;
+ exist.Rotation = direction;
+ ScMoveObjectMove move = new()
+ {
+ ServerNotify = true,
+ MoveInfo =
+ {
+ new MoveObjectMoveInfo()
+ {
+ Objid = guid,
+ SceneNumId=sceneNumId,
+ MotionInfo = new()
+ {
+ Position=exist.Position.ToProto(),
+ Rotation=exist.Rotation.ToProto(),
+ Speed=new Vector()
+ {
+
+ },
+ State=MotionState.MotionNone
+ }
+ }
+ }
+ };
+ player.Send(ScMsgId.ScMoveObjectMove, move);
+ }
+ else
+ {
+ if (interactiveFacWrapperTable.ContainsKey(templateId))
+ {
+ EntityInteractive e = new(interactiveFacWrapperTable[templateId].interactiveTemplateId, player.roleId, worldPosition, direction, sceneNumId, guid);
+ e.InitDefaultProperties();
+ e.SetPropValue(nodeId, "factory_inst_id");
+
+ player.sceneManager.GetCurScene().entities.Add(e);
+ player.sceneManager.GetCurScene().SpawnEntity(e);
+ }
+
+ }
+
+ }
+
+
+ public class FMesh
+ {
+ public FCMeshType type;
+ public List points = new();
+ public ScdFacMesh ToProto()
+ {
+ ScdFacMesh m = new ScdFacMesh()
+ {
+ MeshType = (int)type
+ };
+ foreach (Vector3f p in points)
+ {
+ m.Points.Add(new ScdVec3Int()
+ {
+ X = (int)p.x,
+ Y = (int)p.y,
+ Z = (int)p.z
+ });
+ }
+ return m;
+ }
+ }
+ }
+}
diff --git a/Campofinale/Game/Inventory/Item.cs b/Campofinale/Game/Inventory/Item.cs
index a35230a..13afaa9 100644
--- a/Campofinale/Game/Inventory/Item.cs
+++ b/Campofinale/Game/Inventory/Item.cs
@@ -11,7 +11,6 @@ using static Campofinale.Resource.ResourceManager;
using Google.Protobuf.Collections;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
-using CsvHelper.Configuration.Attributes;
namespace Campofinale.Game.Inventory
{
@@ -141,14 +140,15 @@ namespace Campofinale.Game.Inventory
Inst = new()
{
InstId = guid,
-
+
Equip = new()
{
-
+
EquipCharId = GetOwner().chars.Find(c => c.IsEquipped(guid)) != null ? GetOwner().chars.Find(c => c.IsEquipped(guid)).guid : 0,
Equipid = guid,
Templateid = ResourceManager.GetItemTemplateId(id),
+
},
IsLock = locked
}
@@ -241,6 +241,7 @@ namespace Campofinale.Game.Inventory
};
GetOwner().Send(ScMsgId.ScWeaponAddExp, levelUp);
+
GetOwner().Send(new PacketScSyncWallet(GetOwner()));
}
}
@@ -258,6 +259,10 @@ namespace Campofinale.Game.Inventory
return false;
case ItemValuableDepotType.MissionItem:
return true;
+ case ItemValuableDepotType.Factory:
+ return false;
+ case ItemValuableDepotType.CommercialItem:
+ return false;
default:
return false;
}
diff --git a/Campofinale/Game/SceneManager.cs b/Campofinale/Game/SceneManager.cs
index c000be1..b185c34 100644
--- a/Campofinale/Game/SceneManager.cs
+++ b/Campofinale/Game/SceneManager.cs
@@ -27,8 +27,18 @@ namespace Campofinale.Game
}
public void Update()
{
- if (GetCurScene()!=null)
- GetCurScene().UpdateShowEntities();
+ if (GetCurScene() != null)
+ {
+ try
+ {
+ GetCurScene().UpdateShowEntities();
+ }
+ catch(Exception e)
+ {
+
+ }
+ }
+
}
public Entity GetEntity(ulong guid)
{
@@ -267,7 +277,7 @@ namespace Campofinale.Game
public List activeScripts = new();
public List scripts = new();
- public int grade = 0;
+ public int grade = 1;
public int GetCollection(string id)
{
@@ -311,6 +321,10 @@ namespace Campofinale.Game
}
public void Load()
{
+ if (grade == 0)
+ {
+ grade = 1;
+ }
Unload();
LevelScene lv_scene = ResourceManager.GetLevelData(sceneNumId);
diff --git a/Campofinale/Packets/Cs/HandleCsCharPotentialUnlock.cs b/Campofinale/Packets/Cs/HandleCsCharPotentialUnlock.cs
index 6ca8531..121ea0e 100644
--- a/Campofinale/Packets/Cs/HandleCsCharPotentialUnlock.cs
+++ b/Campofinale/Packets/Cs/HandleCsCharPotentialUnlock.cs
@@ -15,6 +15,7 @@ namespace Campofinale.Packets.Cs
Character character = session.chars.Find(c => c.guid == req.CharObjId);
if (character != null)
{
+
character.potential=req.Level;
//TODO consume Item ID
diff --git a/Campofinale/Packets/Cs/HandleCsFactoryHsFb.cs b/Campofinale/Packets/Cs/HandleCsFactoryHsFb.cs
index 853efe5..51a565d 100644
--- a/Campofinale/Packets/Cs/HandleCsFactoryHsFb.cs
+++ b/Campofinale/Packets/Cs/HandleCsFactoryHsFb.cs
@@ -1,4 +1,5 @@
-using Campofinale.Network;
+using Campofinale.Game.Factory;
+using Campofinale.Network;
using Campofinale.Protocol;
namespace Campofinale.Packets.Cs
@@ -10,14 +11,33 @@ namespace Campofinale.Packets.Cs
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsFactoryHsFb req = packet.DecodeBody();
- long curtimestamp = DateTime.UtcNow.ToUnixTimestampMilliseconds();
+
+ List comps = new();
- ScFactoryHs hs = new()
+ foreach (var id in req.NodeIdList)
{
-
-
+ FactoryNode node=session.factoryManager.GetChapter(req.ChapterId).nodes.Find(n=>n.nodeId == id);
+ if (node != null)
+ {
+ node.components.ForEach(c =>
+ {
+ comps.Add(c.ToProto());
+ });
+ }
+ }
+
+ long curtimestamp = DateTime.UtcNow.ToUnixTimestampMilliseconds();
+ ScFactoryHsSync hs = new()
+ {
+ Tms = curtimestamp,
+ CcList =
+ {
+ comps,
+ },
+ Blackboard = session.factoryManager.GetChapter(req.ChapterId).ToProto().Blackboard,
+ ChapterId=req.ChapterId,
};
- session.Send(ScMsgId.ScFactoryHs, hs);
+ session.Send(ScMsgId.ScFactoryHsSync, hs,packet.csHead.UpSeqid);
}
diff --git a/Campofinale/Packets/Cs/HandleCsGachaTenPullReq.cs b/Campofinale/Packets/Cs/HandleCsGachaTenPullReq.cs
index 407d1b5..41e7f26 100644
--- a/Campofinale/Packets/Cs/HandleCsGachaTenPullReq.cs
+++ b/Campofinale/Packets/Cs/HandleCsGachaTenPullReq.cs
@@ -19,107 +19,6 @@ namespace Campofinale.Packets.Cs
CsGachaTenPullReq req = packet.DecodeBody();
session.gachaManager.upSeqId = packet.csHead.UpSeqid;
session.gachaManager.DoGacha(req.GachaPoolId, 10);
- /* Random rng = new Random();
- List chars = new List();
- const double prob6Star = 0.008; // 0.8%
- const double prob5Star = 0.08; // 8%
- const double fiftyfifty = 0.50; // 50%
- GachaCharPoolTable table = ResourceManager.gachaCharPoolTable[req.GachaPoolId];
- GachaCharPoolContentTable content = ResourceManager.gachaCharPoolContentTable[req.GachaPoolId];
- int sixstarcount = 0;
- int fivestarcount = 0;
- List fiveStars = content.list.FindAll(c => c.starLevel == 5);
- List sixStars = content.list.FindAll(c => c.starLevel == 6);
- int fiveStarGuaranteedIndex = new Random().Next(9);
- for (int i=0; i < 10; i++)
- {
- double roll = rng.NextDouble();
- double fifty = rng.NextDouble();
-
- if (roll < prob6Star)
- {
- sixstarcount++;
-
- if (table.upCharIds.Count > 0)
- {
- if (fifty >= fiftyfifty)
- {
- chars.Add(ResourceManager.characterTable[table.upCharIds[0]].charId);
- }
- else
- {
- chars.Add(sixStars[new Random().Next(sixStars.Count - 1)].charId);
- }
-
- }
- else
- {
- chars.Add(sixStars[new Random().Next(sixStars.Count - 1)].charId);
- }
- }
- else if (roll < prob6Star + prob5Star || fiveStarGuaranteedIndex == i)
- {
- fivestarcount++;
- if(table.upCharIds.Count > 1)
- {
- if(fifty >= fiftyfifty)
- {
- chars.Add(ResourceManager.characterTable[table.upCharIds[1]].charId);
- }
- else
- {
- chars.Add(fiveStars[new Random().Next(fiveStars.Count - 1)].charId);
- }
-
- }
- else
- {
- chars.Add(fiveStars[new Random().Next(fiveStars.Count-1)].charId);
- }
-
- }
- else
- {
- chars.Add(ResourceManager.characterTable.Values.ToList().FindAll(c=>c.rarity == 4)[new Random().Next(ResourceManager.characterTable.Values.ToList().FindAll(c => c.rarity == 4).Count - 1)].charId);
- }
-
- }
- ScGachaSyncPullResult result = new ScGachaSyncPullResult()
- {
- GachaPoolId=req.GachaPoolId,
- GachaType=req.GachaType,
-
- OriResultIds =
- {
- },
- Star5GotCount= fivestarcount,
- Star6GotCount= sixstarcount,
- FinalResults =
- {
-
- },
- UpGotCount= fivestarcount+ sixstarcount,
-
- };
- foreach(string ch in chars)
- {
- bool exist = session.chars.Find(c => c.id == ch) != null;
- result.OriResultIds.Add(ch);
- result.FinalResults.Add(new ScdGachaFinalResult()
- {
- IsNew= !exist,
- ItemId=ch,
-
- });
- }
-
-
- //session.Send(Packet.EncodePacket((int)CsMessageId.CsGachaTenPullReq, req));
-
- session.Send(ScMessageId.ScGachaSyncPullResult, result); */
- // session.Send(CsMessageId.CsGachaEnd, new Empty());
- // session.Send(ScMessageId.ScGachaBegin, new Empty());
-
}
}
diff --git a/Campofinale/Packets/Cs/HandleCsItemBagSetItemLock.cs b/Campofinale/Packets/Cs/HandleCsItemBagSetItemLock.cs
new file mode 100644
index 0000000..8c33136
--- /dev/null
+++ b/Campofinale/Packets/Cs/HandleCsItemBagSetItemLock.cs
@@ -0,0 +1,34 @@
+using Campofinale.Game.Char;
+using Campofinale.Game.Inventory;
+using Campofinale.Network;
+using Campofinale.Protocol;
+
+namespace Campofinale.Packets.Cs
+{
+ public class HandleCsItemBagSetItemLock
+ {
+ [Server.Handler(CsMsgId.CsItemBagSetItemLock)]
+ public static void Handle(Player session, CsMsgId cmdId, Packet packet)
+ {
+ CsItemBagSetItemLock req = packet.DecodeBody();
+
+ foreach (var info in req.LockInfoList)
+ {
+ Item item = session.inventoryManager.items.items.Find(i=>i.guid==info.InstId);
+ if (item != null)
+ {
+ item.locked = info.IsLock;
+ }
+ }
+ ScItemBagSetItemLock rsp = new()
+ {
+ LockInfoList =
+ {
+ req.LockInfoList,
+ }
+ };
+ session.Send(ScMsgId.ScItemBagSetItemLock, rsp);
+ }
+
+ }
+}
diff --git a/Campofinale/Packets/Cs/HandleCsLogin.cs b/Campofinale/Packets/Cs/HandleCsLogin.cs
index 412ee09..db853ec 100644
--- a/Campofinale/Packets/Cs/HandleCsLogin.cs
+++ b/Campofinale/Packets/Cs/HandleCsLogin.cs
@@ -89,7 +89,8 @@ namespace Campofinale.Packets.Cs
IsFirstLogin = false,
IsReconnect=false,
LastRecvUpSeqid = packet.csHead.UpSeqid,
-
+ ServerTimeZone=2,
+ ServerTime=DateTime.UtcNow.ToUnixTimestampMilliseconds(),
};
byte[] encKey = GenerateRandomBytes(32);
string serverPublicKeyPem = req.ClientPublicKey.ToStringUtf8();
diff --git a/Campofinale/Packets/Cs/HandleCsMoveObjectMove.cs b/Campofinale/Packets/Cs/HandleCsMoveObjectMove.cs
index dafe2a2..276a787 100644
--- a/Campofinale/Packets/Cs/HandleCsMoveObjectMove.cs
+++ b/Campofinale/Packets/Cs/HandleCsMoveObjectMove.cs
@@ -12,6 +12,7 @@ namespace Campofinale.Packets.Cs
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsMoveObjectMove req = packet.DecodeBody();
+ if (session.sceneLoadState != Player.SceneLoadState.OK) return;
foreach (var moveInfo in req.MoveInfo)
{
diff --git a/Campofinale/Packets/Cs/HandleCsPing.cs b/Campofinale/Packets/Cs/HandleCsPing.cs
index f3cccf3..7fa8e39 100644
--- a/Campofinale/Packets/Cs/HandleCsPing.cs
+++ b/Campofinale/Packets/Cs/HandleCsPing.cs
@@ -17,25 +17,7 @@ namespace Campofinale.Packets.Cs
ClientTs = req.ClientTs,
ServerTs = (ulong)curtimestamp,
}));
- /*ScFactoryHsSync s = new()
- {
- Blackboard = new()
- {
- InventoryNodeId = 0,
- Power = new()
- {
-
- }
- },
- CcList =
- {
-
- },
- Tms = curtimestamp / 1000,
- ChapterId = session.GetCurrentChapter()
- };
-
- session.Send(ScMessageId.ScFactoryHsSync,s);*/
+ session.factoryManager.SendFactoryHsSync();
//Logger.Print("Server: " + curtimestamp + " client: " + req.ClientTs);
}
diff --git a/Campofinale/Packets/Cs/HandleCsSceneRepatriate.cs b/Campofinale/Packets/Cs/HandleCsSceneRepatriate.cs
index 75b40ad..d6e2917 100644
--- a/Campofinale/Packets/Cs/HandleCsSceneRepatriate.cs
+++ b/Campofinale/Packets/Cs/HandleCsSceneRepatriate.cs
@@ -1,5 +1,7 @@
using Campofinale.Network;
+using Campofinale.Packets.Sc;
using Campofinale.Protocol;
+using Campofinale.Resource;
namespace Campofinale.Packets.Cs
{
@@ -30,6 +32,7 @@ namespace Campofinale.Packets.Cs
}
// Not correctly fixed, need to find the issue - SuikoAkari
// No idea how pass_through_data is used, it's not part of the packet sent by the official server
+ session.Send(new PacketScSelfSceneInfo(session, SelfInfoReasonType.SlrReviveRest));
session.Send(ScMsgId.ScSceneRepatriate, new ScSceneRepatriate()
{
SceneNumId = session.savedSaveZone.sceneNumId,
diff --git a/Campofinale/Packets/Cs/HandleCsSceneRest.cs b/Campofinale/Packets/Cs/HandleCsSceneRest.cs
new file mode 100644
index 0000000..00649a8
--- /dev/null
+++ b/Campofinale/Packets/Cs/HandleCsSceneRest.cs
@@ -0,0 +1,28 @@
+using Campofinale.Network;
+using Campofinale.Packets.Sc;
+using Campofinale.Protocol;
+using Campofinale.Resource;
+
+namespace Campofinale.Packets.Cs
+{
+ public class HandleCsSceneRest
+ {
+
+ [Server.Handler(CsMsgId.CsSceneRest)]
+ public static void Handle(Player session, CsMsgId cmdId, Packet packet)
+ {
+ CsSceneRest req = packet.DecodeBody();
+ if (session.sceneLoadState == Player.SceneLoadState.Loading) return;
+ ScSceneRevival revival = new()
+ {
+
+ };
+ session.RestTeam();
+ session.sceneManager.LoadCurrentTeamEntities();
+ session.Send(ScMsgId.ScSceneRevival, revival, packet.csHead.UpSeqid);
+ session.Send(new PacketScSelfSceneInfo(session, SelfInfoReasonType.SlrReviveRest));
+
+ }
+
+ }
+}
diff --git a/Campofinale/Packets/Cs/HandleCsSceneTeleport.cs b/Campofinale/Packets/Cs/HandleCsSceneTeleport.cs
index b4c77b6..6a85ee1 100644
--- a/Campofinale/Packets/Cs/HandleCsSceneTeleport.cs
+++ b/Campofinale/Packets/Cs/HandleCsSceneTeleport.cs
@@ -1,6 +1,7 @@
using Campofinale.Network;
using Campofinale.Protocol;
using Campofinale.Utils;
+using static Campofinale.Resource.ResourceManager;
namespace Campofinale.Packets.Cs
{
@@ -15,7 +16,7 @@ namespace Campofinale.Packets.Cs
if (session.curSceneNumId != req.SceneNumId)
{
session.EnterScene(req.SceneNumId, new Resource.ResourceManager.Vector3f(req.Position), new Resource.ResourceManager.Vector3f(req.Rotation));
- /* ScSceneTeleport t = new()
+ ScSceneTeleport t = new()
{
TeleportReason = req.TeleportReason,
PassThroughData = req.PassThroughData,
@@ -23,7 +24,7 @@ namespace Campofinale.Packets.Cs
Rotation = req.Rotation,
SceneNumId = req.SceneNumId,
};
- session.Send(ScMsgId.ScSceneTeleport, t);*/
+ session.Send(ScMsgId.ScSceneTeleport, t);
}
else
{
@@ -41,6 +42,9 @@ namespace Campofinale.Packets.Cs
TpUuid= (ulong)id
};
session.curSceneNumId = t.SceneNumId;
+ session.position = new Vector3f(req.Position);
+ session.rotation = new Vector3f(req.Rotation);
+ session.sceneLoadState = Player.SceneLoadState.Loading;
session.Send(ScMsgId.ScSceneTeleport, t);
}
diff --git a/Campofinale/Packets/Cs/HandleCsSceneTeleportFinish.cs b/Campofinale/Packets/Cs/HandleCsSceneTeleportFinish.cs
new file mode 100644
index 0000000..110a647
--- /dev/null
+++ b/Campofinale/Packets/Cs/HandleCsSceneTeleportFinish.cs
@@ -0,0 +1,19 @@
+using Campofinale.Network;
+using Campofinale.Protocol;
+using Campofinale.Utils;
+using static Campofinale.Resource.ResourceManager;
+
+namespace Campofinale.Packets.Cs
+{
+ public class HandleCsSceneTeleportFinish
+ {
+
+ [Server.Handler(CsMsgId.CsSceneTeleportFinish)]
+ public static void Handle(Player session, CsMsgId cmdId, Packet packet)
+ {
+ CsSceneTeleportFinish req = packet.DecodeBody();
+ session.sceneLoadState=Player.SceneLoadState.OK;
+ }
+
+ }
+}
diff --git a/Campofinale/Packets/Sc/PacketScFactoryHsSync.cs b/Campofinale/Packets/Sc/PacketScFactoryHsSync.cs
new file mode 100644
index 0000000..3d4286d
--- /dev/null
+++ b/Campofinale/Packets/Sc/PacketScFactoryHsSync.cs
@@ -0,0 +1,31 @@
+using Campofinale.Game.Factory;
+using Campofinale.Network;
+using Campofinale.Protocol;
+using System.Numerics;
+
+namespace Campofinale.Packets.Sc
+{
+ public class PacketScFactoryHsSync : Packet
+ {
+
+ public PacketScFactoryHsSync(Player client, FactoryChapter chapter, List nodes) {
+
+ long curtimestamp = DateTime.UtcNow.ToUnixTimestampMilliseconds();
+ ScFactoryHsSync hs = new()
+ {
+ Tms = curtimestamp,
+ Blackboard = chapter.blackboard.ToProto(),
+ ChapterId = chapter.chapterId,
+ };
+ nodes.ForEach(node =>
+ {
+ node.components.ForEach(c =>
+ {
+ hs.CcList.Add(c.ToProto());
+ });
+ });
+ SetData(ScMsgId.ScFactoryHsSync, hs);
+ }
+
+ }
+}
diff --git a/Campofinale/Packets/Sc/PacketScFactoryModifyChapterNodes.cs b/Campofinale/Packets/Sc/PacketScFactoryModifyChapterNodes.cs
index d34a9d9..85a3409 100644
--- a/Campofinale/Packets/Sc/PacketScFactoryModifyChapterNodes.cs
+++ b/Campofinale/Packets/Sc/PacketScFactoryModifyChapterNodes.cs
@@ -11,7 +11,7 @@ namespace Campofinale.Packets.Sc
ScFactoryModifyChapterNodes edit = new()
{
ChapterId = chapterId,
- Tms = DateTime.UtcNow.ToUnixTimestampMilliseconds()/1000,
+ Tms = DateTime.UtcNow.ToUnixTimestampMilliseconds(),
Nodes =
{
node.ToProto()
@@ -24,7 +24,7 @@ namespace Campofinale.Packets.Sc
ScFactoryModifyChapterNodes edit = new()
{
ChapterId = chapterId,
- Tms = DateTime.UtcNow.ToUnixTimestampMilliseconds() / 1000,
+ Tms = DateTime.UtcNow.ToUnixTimestampMilliseconds(),
RemoveNodes =
{
nodeId
diff --git a/Campofinale/Packets/Sc/PacketScFactoryOpRet.cs b/Campofinale/Packets/Sc/PacketScFactoryOpRet.cs
index 0dcb19c..d406b6f 100644
--- a/Campofinale/Packets/Sc/PacketScFactoryOpRet.cs
+++ b/Campofinale/Packets/Sc/PacketScFactoryOpRet.cs
@@ -42,6 +42,20 @@ namespace Campofinale.Packets.Sc
};
}
+ if (op.OpType == FactoryOpType.DismantleBoxConveyor)
+ {
+ proto.DismantleBoxConveyor = new()
+ {
+
+ };
+ }
+ if (op.OpType == FactoryOpType.ChangeProducerMode)
+ {
+ proto.ChangeProducerMode = new()
+ {
+
+ };
+ }
if (op.OpType == FactoryOpType.SetTravelPoleDefaultNext)
{
proto.SetTravelPoleDefaultNext = new()
@@ -49,9 +63,50 @@ namespace Campofinale.Packets.Sc
};
}
+ if (op.OpType == FactoryOpType.EnableNode)
+ {
+ proto.EnableNode = new()
+ {
+
+ };
+ }
+
+ if (op.OpType == FactoryOpType.MoveItemBagToCache)
+ {
+ proto.MoveItemBagToCache = new()
+ {
+
+ };
+ }
+ if(op.OpType == FactoryOpType.MoveItemCacheToBag)
+ {
+ proto.MoveItemCacheToBag = new();
+ }
proto.Index=op.Index;
SetData(ScMsgId.ScFactoryOpRet, proto);
}
+ public PacketScFactoryOpRet(Player client, List val, CsFactoryOp op)
+ {
+ ScFactoryOpRet proto = new ScFactoryOpRet()
+ {
+ RetCode = FactoryOpRetCode.Ok,
+ OpType = op.OpType,
+
+ };
+
+ if (op.OpType == FactoryOpType.PlaceConveyor)
+ {
+ proto.PlaceConveyor = new()
+ {
+ NodeId =
+ {
+ val
+ }
+ };
+ }
+ proto.Index = op.Index;
+ SetData(ScMsgId.ScFactoryOpRet, proto);
+ }
}
}
diff --git a/Campofinale/Packets/Sc/PacketScSelfSceneInfo.cs b/Campofinale/Packets/Sc/PacketScSelfSceneInfo.cs
index fbb5069..f54189c 100644
--- a/Campofinale/Packets/Sc/PacketScSelfSceneInfo.cs
+++ b/Campofinale/Packets/Sc/PacketScSelfSceneInfo.cs
@@ -22,7 +22,7 @@ namespace Campofinale.Packets.Sc
TeamType = CharBagTeamType.Main
},
- SceneGrade = 4,
+ SceneGrade = session.sceneManager.GetCurScene().grade,
Detail = new()
{
diff --git a/Campofinale/Player.cs b/Campofinale/Player.cs
index ebce970..e85cf9b 100644
--- a/Campofinale/Player.cs
+++ b/Campofinale/Player.cs
@@ -312,24 +312,6 @@ namespace Campofinale
teams.Add(new Team());
teams.Add(new Team());
bitsetManager.Load(new Dictionary>());
- /*mails.Add(new Mail()
- {
- expireTime=DateTime.UtcNow.AddDays(30).Ticks,
- sendTime=DateTime.UtcNow.Ticks,
- claimed=false,
- guid=random.Next(),
- owner=roleId,
- isRead=false,
- content=new Mail_Content()
- {
- content= "Welcome to Campofinale, Join our Discord for help: https://discord.gg/5uJGJJEFHa",
- senderName="SuikoAkari",
- title="Welcome",
- templateId="",
- }
-
- });*/
-
spaceshipManager.Load();
}
@@ -348,8 +330,6 @@ namespace Campofinale
}
else
{
- //sceneManager.UnloadCurrent(false);
- //sceneManager.LoadCurrent();
sceneLoadState = SceneLoadState.Loading;
Send(new PacketScEnterSceneNotify(this, curSceneNumId));
}
@@ -370,7 +350,6 @@ namespace Campofinale
}
public SceneLoadState sceneLoadState=0;
- // public bool LoadFinish = true;
public void EnterScene(int sceneNumId, Vector3f pos, Vector3f rot, PassThroughData passThroughData = null)
{
// if (!LoadFinish) return;
@@ -573,15 +552,10 @@ namespace Campofinale
{
}
-
-
-
-
Disconnect();
}
public void Kick(CODE code, string optionalMsg="")
{
-
Send(ScMsgId.ScNtfErrorCode, new ScNtfErrorCode()
{
Details = optionalMsg,
@@ -606,8 +580,6 @@ namespace Campofinale
Logger.Print($"{nickname} Disconnected");
socket.Disconnect(false);
}
-
-
}
public void Save()
{
@@ -759,5 +731,24 @@ namespace Campofinale
}
}
+
+ public void RestTeam()
+ {
+ GetCurTeam().ForEach(chara =>
+ {
+ chara.curHp = chara.CalcAttributes()[AttributeType.MaxHp].val;
+ ScCharSyncStatus state = new ScCharSyncStatus()
+ {
+ Objid = chara.guid,
+ IsDead = chara.curHp < 1,
+ BattleInfo = new()
+ {
+ Hp = chara.curHp,
+ Ultimatesp = chara.ultimateSp
+ }
+ };
+ Send(ScMsgId.ScCharSyncStatus, state);
+ });
+ }
}
}
diff --git a/Campofinale/Program.cs b/Campofinale/Program.cs
index 78e50ad..00b5597 100644
--- a/Campofinale/Program.cs
+++ b/Campofinale/Program.cs
@@ -13,7 +13,7 @@ class Program
static void Main(string[] args)
{
StartServer(args);
- //FakeClientTester();
+ //FakeClientTester();
}
public static byte[] ConcatenateByteArrays(byte[] array1, byte[] array2)
{
@@ -22,7 +22,7 @@ class Program
private static void FakeClientTester()
{
//
- string serverIp = "beyond-cn.hypergryph.com";
+ string serverIp = "beyond-ric.gryphline.com";
int serverPort = 30000;
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
@@ -32,7 +32,8 @@ class Program
socket.Connect(new IPEndPoint(ipAddress, serverPort));
- socket.Send(Packet.EncodePacket((int)CsMsgId.CsLogin,new CsLogin() { ClientVersion="0.5.5",Uid= "", Token= "", Env=EnvType.Prod,PlatformId=ClientPlatformType.Windows,Area=AreaType.Oversea,ClientResVersion="", LoginToken= "" }.ToByteArray()));
+ socket.Send(Packet.EncodePacket((int)CsMsgId.CsLogin,new CsLogin() { ClientVersion="0.5.5",Uid= "", Token= "", Env=EnvType.Prod,PlatformId=ClientPlatformType.Windows,Area=AreaType.Oversea,ClientResVersion="", LoginToken= "" }.ToByteArray()));
+ //socket.Send(Packet.EncodePacket((int)CsMsgId.CsFriendListSync, new CsFriendListSync() { }.ToByteArray()));
while (true)
{
byte[] buffer = new byte[3];
diff --git a/Campofinale/Resource/ResourceManager.cs b/Campofinale/Resource/ResourceManager.cs
index 37d0b90..44ae964 100644
--- a/Campofinale/Resource/ResourceManager.cs
+++ b/Campofinale/Resource/ResourceManager.cs
@@ -69,6 +69,7 @@ namespace Campofinale.Resource
public static DialogIdTable dialogIdTable = new();//
public static Dictionary levelShortIdTable = new();
public static Dictionary factoryBuildingTable = new();
+ public static Dictionary factoryMachineCraftTable = new();
public static Dictionary facSTTNodeTable = new();
public static Dictionary facSTTLayerTable = new();
public static Dictionary itemTypeTable = new(); //
@@ -339,12 +340,63 @@ namespace Campofinale.Resource
{
return strIdNumTable.item_id.dic[item_id];
}
+
+ public static string FindFactoryMachineCraftIdUsingCacheItems(List items, string group)
+ {
+ // Estrae solo gli ID degli items in input e li ordina
+ var inputItemIds = items.Select(item => item.id).OrderBy(id => id).ToList();
+
+ foreach (var recipe in factoryMachineCraftTable.Values.ToList().FindAll(r=>r.formulaGroupId==group))
+ {
+ // Raccoglie tutti gli ID degli ingredienti della ricetta
+ var recipeItemIds = new List();
+ foreach (var ingr in recipe.ingredients)
+ {
+ recipeItemIds.AddRange(ingr.group.Select(item => item.id));
+ }
+
+ // Ordina gli ID degli ingredienti della ricetta
+ var sortedRecipeItemIds = recipeItemIds.OrderBy(id => id).ToList();
+
+ // Confronta le due liste di ID (ignorando le quantità)
+ if (inputItemIds.SequenceEqual(sortedRecipeItemIds))
+ {
+ return recipe.id; // Trovata corrispondenza
+ }
+ }
+
+ return ""; // Nessuna corrispondenza trovata
+ }
+
public class InteractiveData
{
public string id;
public Dictionary propertyKeyToIdMap = new();
public List saveProperties = new();
}
+ public class ItemCount
+ {
+ public int count;
+ public string id = "";
+ public long tms = DateTime.UtcNow.ToUnixTimestampMilliseconds();
+
+ public ScdFactorySyncItem ToFactoryItemProto()
+ {
+ return new ScdFactorySyncItem()
+ {
+ Count = count,
+ Id = id,
+ Tms = tms
+ };
+ }
+ public bool IsItemAtConveyorEnd(float conveyorSize)
+ {
+ long spawnTms = tms;
+ long endTms = spawnTms + (long)(2000 * conveyorSize);
+ long cur = DateTime.UtcNow.ToUnixTimestampMilliseconds();
+ return cur > endTms;
+ }
+ }
public class FactoryBuildingTable
{
public int bandwidth;
@@ -354,15 +406,107 @@ namespace Campofinale.Resource
public int powerConsume;
public FacBuildingType type;
public FBuildingRange range;
+ public List outputPorts = new();
+ public List inputPorts = new();
+ public class FacPort
+ {
+ public int index;
+ public int isOutput;
+ public bool isPipe;
+ public FacPortTrans trans = new();
+ public Vector3f GetBack()
+ {
+ float angleY = trans.rotation.y % 360f;
+
+ Vector3f offset;
+
+ switch ((int)angleY)
+ {
+ default:
+ case 360:
+ case 0:
+ offset = new Vector3f(0, 0, -1);
+ break;
+ case 90:
+ offset = new Vector3f(-1, 0, 0);
+ break;
+ case 180:
+ offset = new Vector3f(0, 0, 1);
+ break;
+ case 270:
+ offset = new Vector3f(1, 0, 0);
+ break;
+ }
+
+ return trans.position + offset;
+ }
+ public Vector3f GetFront()
+ {
+ float angleY = trans.rotation.y % 360f;
+
+ Vector3f offset=new();
+
+ switch ((int)angleY)
+ {
+ default:
+ case 360:
+ case 0:
+ offset = new Vector3f(0, 0, 1);
+ break;
+ case 90:
+ offset = new Vector3f(1, 0, 0);
+ break;
+ case 180:
+ offset = new Vector3f(0, 0, -1);
+ break;
+ case 270:
+ offset = new Vector3f(-1, 0, 0);
+ break;
+ }
+
+ return trans.position + offset;
+ }
+
+ public class FacPortTrans
+ {
+ public Vector3f position=new();
+ public Vector3f rotation = new();
+ }
+ }
public FCNodeType GetNodeType()
{
- string nodeTypeName = type.ToString();
- if (Enum.TryParse(nodeTypeName, out FCNodeType fromName))
+ switch (type)
{
- return fromName;
+ case FacBuildingType.Battle:
+ return FCNodeType.Battle;
+ case FacBuildingType.Hub:
+ return FCNodeType.Hub;
+ case FacBuildingType.SubHub:
+ return FCNodeType.SubHub;
+ case FacBuildingType.MachineCrafter:
+ return FCNodeType.Producer;
+ case FacBuildingType.PowerPort:
+ return FCNodeType.PowerPort;
+ case FacBuildingType.PowerPole:
+ return FCNodeType.PowerPole;
+ case FacBuildingType.PowerDiffuser:
+ return FCNodeType.PowerDiffuser;
+ case FacBuildingType.TravelPole:
+ return FCNodeType.TravelPole;
+ case FacBuildingType.Medic:
+ return FCNodeType.HealTower;
+ case FacBuildingType.Unloader:
+ return FCNodeType.BusUnloader;
+ case FacBuildingType.Loader:
+ return FCNodeType.BusLoader;
+ case FacBuildingType.Miner:
+ return FCNodeType.Collector;
+ case FacBuildingType.Storager:
+ return FCNodeType.DepositBox;
+ default:
+ return FCNodeType.Invalid;
}
- return FCNodeType.Invalid;
}
public struct FBuildingRange
{
@@ -978,7 +1122,20 @@ namespace Campofinale.Resource
public float x;
public float y;
public float z;
-
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Vector3f v)
+ {
+ return x == v.x && y == v.y && z == v.z;
+ }
+ return false;
+ }
+
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(x, y, z);
+ }
public Vector3f()
{
diff --git a/Campofinale/Resource/Table/FactoryMachineCraftTable.cs b/Campofinale/Resource/Table/FactoryMachineCraftTable.cs
new file mode 100644
index 0000000..880d691
--- /dev/null
+++ b/Campofinale/Resource/Table/FactoryMachineCraftTable.cs
@@ -0,0 +1,53 @@
+using Campofinale.Game.Factory.Components;
+using static Campofinale.Resource.ResourceManager;
+
+namespace Campofinale.Resource.Table
+{
+ [TableCfgType("TableCfg/FactoryMachineCraftTable.json", LoadPriority.LOW)]
+ public class FactoryMachineCraftTable
+ {
+ public string id;
+ public string machineId;
+ public int progressRound;
+ public long totalProgress;
+ public int signal;
+ public string formulaGroupId;
+ public List ingredients = new();
+ public List outcomes = new();
+
+ public bool CacheHaveItems(FComponentCache inCache)
+ {
+ bool enough = true;
+ ingredients.ForEach(i =>
+ {
+ i.group.ForEach(item =>
+ {
+ if(inCache.GetItemCount(item.id) < item.count)
+ {
+ enough = false;
+
+ }
+ });
+ });
+ return enough;
+ }
+
+ internal List GetIngredients()
+ {
+ List items = new();
+ ingredients.ForEach(i =>
+ {
+ i.group.ForEach(item =>
+ {
+ items.Add(item);
+ });
+ });
+ return items;
+ }
+
+ public class FactoryMachineCraftIngredient
+ {
+ public List group = new();
+ }
+ }
+}
diff --git a/Campofinale/Server.cs b/Campofinale/Server.cs
index 4f2b587..2963a4b 100644
--- a/Campofinale/Server.cs
+++ b/Campofinale/Server.cs
@@ -59,7 +59,7 @@ namespace Campofinale
public delegate void HandlerDelegate(Player sender, string command, string[] args, Player target);
}
public static List clients = new List();
- public static string ServerVersion = "1.1.6";
+ public static string ServerVersion = "1.1.7";
public static bool Initialized = false;
public static bool showLogs = true;
public static bool showWarningLogs = true;
@@ -67,7 +67,7 @@ namespace Campofinale
public static Dispatch? dispatch;
public static ConfigFile? config;
public static List csMessageToHide = new() { CsMsgId.CsMoveObjectMove, CsMsgId.CsBattleOp,CsMsgId.CsPing };
- public static List scMessageToHide = new() { ScMsgId.ScMoveObjectMove, ScMsgId.ScPing,ScMsgId.ScObjectEnterView };
+ public static List scMessageToHide = new() { ScMsgId.ScMoveObjectMove, ScMsgId.ScPing,ScMsgId.ScObjectEnterView,ScMsgId.ScFactoryHsSync };
public void Start(ConfigFile config)
{
{
@@ -152,7 +152,7 @@ namespace Campofinale
try
{
clients.ForEach(client => { if (client != null) client.Update(); });
- Thread.Sleep(1000);
+ Thread.Sleep(250);
}
catch (Exception ex)
{
diff --git a/Dotfuscator1.xml b/Dotfuscator1.xml
deleted file mode 100644
index 44bfed3..0000000
--- a/Dotfuscator1.xml
+++ /dev/null
@@ -1,229 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file