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..b5e01bf --- /dev/null +++ b/Campofinale/Game/Factory/BlockCalculator.cs @@ -0,0 +1,119 @@ +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); + + // Algoritmo di Bresenham 3D + 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; + + // Decision variables + 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 // dz è la dimensione dominante + { + 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; + } + } + + // Aggiungi l'ultimo punto + 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..9397b80 --- /dev/null +++ b/Campofinale/Game/Factory/BuildingsBehaviour/NodeBuilding_Producer.cs @@ -0,0 +1,102 @@ +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; + +namespace Campofinale.Game.Factory.BuildingsBehaviour +{ + public class NodeBuilding_Producer : NodeBuildingBehaviour + { + public uint inputCacheId = 0; + public uint outputCacheId = 0; + public uint producerId = 0; + public int currentProgress = 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 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); + FactoryMachineCraftTable craftingRecipe = null; + string recipe = ResourceManager.FindFactoryMachineCraftIdUsingCacheItems(inCache.items); + 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; + producer.progress += craftingRecipe.totalProgress/craftingRecipe.progressRound; + currentProgress++; + if (currentProgress >= craftingRecipe.progressRound) + { + currentProgress = 0; + List toConsume = craftingRecipe.GetIngredients(); + inCache.ConsumeItems(toConsume); + craftingRecipe.outcomes.ForEach(e => + { + e.group.ForEach(i => + { + outCache.AddItem(i.id, i.count); + }); + + }); + } + } + else + { + producer.inBlock = false; + producer.inProduce = false; + producer.progress = 0; + } + } + else + { + producer.inBlock = false; + producer.inProduce = false; + producer.progress = 0; + } + } + /* ScFactoryModifyChapterComponents update = new() + { + ChapterId = chapter.chapterId, + Tms = DateTime.UtcNow.ToUnixTimestampMilliseconds()/1000, + + }; + + foreach (var comp in node.components) + { + update.Components.Add(comp.ToProto()); + } + chapter.GetOwner().Send(ScMsgId.ScFactoryModifyChapterComponents, update);*/ + } + } +} diff --git a/Campofinale/Game/Factory/Components/FComponentBattle.cs b/Campofinale/Game/Factory/Components/FComponentBattle.cs index 82d44e8..f48cd53 100644 --- a/Campofinale/Game/Factory/Components/FComponentBattle.cs +++ b/Campofinale/Game/Factory/Components/FComponentBattle.cs @@ -6,7 +6,7 @@ namespace Campofinale.Game.Factory.Components public class FComponentBattle : FComponent { public int EnergyCurrent=100; - public FComponentBattle(uint id) : base(id, FCComponentType.Battle) + public FComponentBattle(uint id) : base(id, FCComponentType.Battle, FCComponentPos.Battle1) { } diff --git a/Campofinale/Game/Factory/Components/FComponentBoxConveyor.cs b/Campofinale/Game/Factory/Components/FComponentBoxConveyor.cs new file mode 100644 index 0000000..cd64c4b --- /dev/null +++ b/Campofinale/Game/Factory/Components/FComponentBoxConveyor.cs @@ -0,0 +1,33 @@ +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) + { + } + + public override void SetComponentInfo(ScdFacCom proto) + { + if (items == null) + { + items = new List(); + } + proto.BoxConveyor = new() + { + LastPopTms = lastPopTms, + + }; + items.ForEach(item => + { + proto.BoxConveyor.Items.Add(item.ToFactoryItemProto()); + }); + + } + } +} diff --git a/Campofinale/Game/Factory/Components/FComponentCache.cs b/Campofinale/Game/Factory/Components/FComponentCache.cs index a88b7ca..3b347f1 100644 --- a/Campofinale/Game/Factory/Components/FComponentCache.cs +++ b/Campofinale/Game/Factory/Components/FComponentCache.cs @@ -1,21 +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 FComponentCache(uint id) : base(id, FCComponentType.Cache) + + 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 * 100; + 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 = 100-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 index e4ecbbc..17868d9 100644 --- a/Campofinale/Game/Factory/Components/FComponentFormulaMan.cs +++ b/Campofinale/Game/Factory/Components/FComponentFormulaMan.cs @@ -5,6 +5,8 @@ namespace Campofinale.Game.Factory.Components { public class FComponentFormulaMan : FComponent { + public string currentGroup = "group_grinder_normal"; + public string currentMode = "normal"; public FComponentFormulaMan(uint id) : base(id, FCComponentType.FormulaMan) { } @@ -13,7 +15,21 @@ namespace Campofinale.Game.Factory.Components { proto.FormulaMan = new() { - + CurrentGroup = currentGroup, + CurrentMode = currentMode, + FormulaIds = { + "grinder_iron_powder_1", + "grinder_quartz_powder_1", + "grinder_originium_powder_1", + "grinder_carbon_powder_1", + "grinder_crystal_powder_1", + "grinder_plant_moss_powder_1_1", + "grinder_plant_moss_powder_2_1", + "grinder_plant_moss_powder_3_1", + "grinder_plant_bbflower_powder_1_1", + "grinder_plant_grass_powder_1_1", + "grinder_plant_grass_powder_2_1" + } }; } } diff --git a/Campofinale/Game/Factory/Components/FComponentPortManager.cs b/Campofinale/Game/Factory/Components/FComponentPortManager.cs index 615605b..fa83d87 100644 --- a/Campofinale/Game/Factory/Components/FComponentPortManager.cs +++ b/Campofinale/Game/Factory/Components/FComponentPortManager.cs @@ -47,8 +47,33 @@ namespace Campofinale.Game.Factory.Components }); } } + 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 index d8ac236..4452420 100644 --- a/Campofinale/Game/Factory/Components/FComponentProducer.cs +++ b/Campofinale/Game/Factory/Components/FComponentProducer.cs @@ -5,15 +5,24 @@ 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..4f5ffca --- /dev/null +++ b/Campofinale/Game/Factory/FComponent.cs @@ -0,0 +1,108 @@ +using Campofinale.Game.Factory.Components; +using Campofinale.Resource; +using MongoDB.Bson.Serialization.Attributes; +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..e25563b --- /dev/null +++ b/Campofinale/Game/Factory/FactoryChapter.cs @@ -0,0 +1,635 @@ +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 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); + } + + }); + try + { + nodes.ForEach(node => + { + chapter.Nodes.Add(node.ToProto()); + }); + } + catch(Exception e) + { + + } + + 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.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.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 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 = 100 - 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() / 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 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() / 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); + } + } + } + public void PlaceConveyor(CsFactoryOp op, ulong seq) + { + var placeConveyor = op.PlaceConveyor; + Logger.Print($"'PlaceConveyor': {JsonConvert.SerializeObject(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 d9fe989..e902f83 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,854 +69,52 @@ namespace Campofinale.Game.Factory player.Send(ScMsgId.ScFactoryOpRet, ret, seq); } } + public void SendFactoryHsSync() + { + if (!player.Initialized) return; + long curtimestamp = DateTime.UtcNow.ToUnixTimestampMilliseconds(); + + ScFactoryHsSync hs = new() + { + Tms = curtimestamp, + CcList = + { + }, + Blackboard = GetChapter(player.GetCurrentChapter()).ToProto().Blackboard, + ChapterId = player.GetCurrentChapter(), + }; + foreach (var node in GetChapter(player.GetCurrentChapter()).nodes) + { + + if (node != null) + { + if (node.position.DistanceXZ(player.position) < 150) + { + node.components.ForEach(c => + { + hs.CcList.Add(c.ToProto()); + }); + } + + } + } + player.Send(ScMsgId.ScFactoryHsSync, hs); + } 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.Battle: - components.Add(new FComponentBattle(chapter.nextCompV()).Init()); - break; - case FCNodeType.Producer: - - components.Add(new FComponentPortManager(chapter.nextCompV(), 3).Init()); - components.Add(new FComponentPortManager(chapter.nextCompV(), 3).Init()); - components.Add(new FComponentProducer(chapter.nextCompV()).Init()); - components.Add(new FComponentFormulaMan(chapter.nextCompV()).Init()); - components.Add(new FComponentCache(chapter.nextCompV()).Init()); - components.Add(new FComponentCache(chapter.nextCompV()).Init()); - components.Add(new FComponentCache(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); - } - - } - - } - - [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; - case FCComponentType.TravelPole: - return FCComponentPos.TravelPole; - case FCComponentType.Battle: - return FCComponentPos.Battle1; - case FCComponentType.Producer: - return FCComponentPos.Producer; - case FCComponentType.FormulaMan: - return FCComponentPos.FormulaMan; - } - 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..349232a --- /dev/null +++ b/Campofinale/Game/Factory/FactoryNode.cs @@ -0,0 +1,522 @@ +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; + +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) + { + nodeBehaviour.Update(chapter,this); + } + foreach(var comp in components.FindAll(c=> c is FComponentPortManager)) + { + UpdatePortManager(chapter, (FComponentPortManager)comp); + } + } + 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(i)) + { + 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; + } + } + + } + } + + } + + } + + private bool AddConveyorItem(ItemCount i) + { + int length=BlockCalculator.CalculateTotalBlocks(points); + FComponentBoxConveyor conveyorComp = GetComponent(); + if (conveyorComp != null) + { + if(conveyorComp.items.Count < length) + { + conveyorComp.items.Add(i); + int size = BlockCalculator.CalculateTotalBlocks(points) - 1; + conveyorComp.lastPopTms = i.tms; + return true; + } + } + 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; + + // Ottieni la posizione e rotazione base dall'oggetto + FMesh mesh = GetMesh(); + if (mesh.points.Count < 2) + return transformedPorts; + + Vector3f objectPosition = mesh.points[0]; + float objectRotationY = direction.y % 360f; + + // Ottieni le dimensioni originali + 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; + + // Rotazione della porta + 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, + }, + + 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: + nodeBehaviour=new NodeBuilding_Producer(); + 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/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/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/Sc/PacketScFactoryOpRet.cs b/Campofinale/Packets/Sc/PacketScFactoryOpRet.cs index 0dcb19c..edec84a 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,46 @@ namespace Campofinale.Packets.Sc }; } + if (op.OpType == FactoryOpType.EnableNode) + { + proto.EnableNode = new() + { + + }; + } + + if (op.OpType == FactoryOpType.MoveItemBagToCache) + { + proto.MoveItemBagToCache = 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/Resource/ResourceManager.cs b/Campofinale/Resource/ResourceManager.cs index 37d0b90..ce0a66f 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,55 @@ namespace Campofinale.Resource { return strIdNumTable.item_id.dic[item_id]; } + + public static string FindFactoryMachineCraftIdUsingCacheItems(List items) + { + // 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()) + { + // 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, + }; + } + } public class FactoryBuildingTable { public int bandwidth; @@ -354,15 +398,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 +1114,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..5cf914c --- /dev/null +++ b/Campofinale/Resource/Table/FactoryMachineCraftTable.cs @@ -0,0 +1,52 @@ +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 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..06b5c39 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-dev"; public static bool Initialized = false; public static bool showLogs = true; public static bool showWarningLogs = true;