mirror of
https://git.muiegratis.online/suikoakari/Campofinale
synced 2025-12-13 01:54:38 +01:00
many stuff
This commit is contained in:
@@ -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<int, Item>), new CustomDictionarySerializer<int, Item>());
|
||||
|
||||
RegisterSubclasses<FComponent>();
|
||||
RegisterSubclasses<NodeBuildingBehaviour>();
|
||||
Logger.Print("Connecting to MongoDB...");
|
||||
try
|
||||
{
|
||||
|
||||
119
Campofinale/Game/Factory/BlockCalculator.cs
Normal file
119
Campofinale/Game/Factory/BlockCalculator.cs
Normal file
@@ -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<Vector3f> points)
|
||||
{
|
||||
if (points == null || points.Count < 2)
|
||||
return 0;
|
||||
|
||||
HashSet<Tuple<int, int, int>> blocks = new HashSet<Tuple<int, int, int>>();
|
||||
|
||||
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<Tuple<int, int, int>> 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<FComponentProducer>(producerId);
|
||||
FComponentCache inCache = node.GetComponent<FComponentCache>(inputCacheId);
|
||||
FComponentCache outCache = node.GetComponent<FComponentCache>(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<ItemCount> 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);*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
33
Campofinale/Game/Factory/Components/FComponentBoxConveyor.cs
Normal file
33
Campofinale/Game/Factory/Components/FComponentBoxConveyor.cs
Normal file
@@ -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<ItemCount> items = new();
|
||||
public FComponentBoxConveyor(uint id) : base(id, FCComponentType.BoxConveyor,FCComponentPos.BoxConveyor)
|
||||
{
|
||||
}
|
||||
|
||||
public override void SetComponentInfo(ScdFacCom proto)
|
||||
{
|
||||
if (items == null)
|
||||
{
|
||||
items = new List<ItemCount>();
|
||||
}
|
||||
proto.BoxConveyor = new()
|
||||
{
|
||||
LastPopTms = lastPopTms,
|
||||
|
||||
};
|
||||
items.ForEach(item =>
|
||||
{
|
||||
proto.BoxConveyor.Items.Add(item.ToFactoryItemProto());
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<ItemCount> 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<ItemCount> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
108
Campofinale/Game/Factory/FComponent.cs
Normal file
108
Campofinale/Game/Factory/FComponent.cs
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
635
Campofinale/Game/Factory/FactoryChapter.cs
Normal file
635
Campofinale/Game/Factory/FactoryChapter.cs
Normal file
@@ -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<FactoryNode> 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<ScdFactorySyncMap> GetMaps()
|
||||
{
|
||||
List<ScdFactorySyncMap> 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<ScdFactorySyncMapWire> GetWires()
|
||||
{
|
||||
List<ScdFactorySyncMapWire> 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<FactoryNode> 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<FComponentTravelPole>().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<FComponentFormulaMan>();
|
||||
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<FComponentCache>(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<FactoryNode> allNodes)
|
||||
{
|
||||
// Ottieni tutti i compId del nodo da rimuovere
|
||||
HashSet<ulong> 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<FComponent>(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<FactoryNode> allNodes)
|
||||
{
|
||||
foreach (var node in allNodes)
|
||||
node.powered = false;
|
||||
}
|
||||
void UpdatePowerGrid(List<FactoryNode> allNodes)
|
||||
{
|
||||
ResetAllPower(allNodes);
|
||||
|
||||
HashSet<uint> 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<uint> 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<FactoryNode> nodes = GetNodesInRange(node.position, 15);
|
||||
foreach (FactoryNode propagateNode in nodes)
|
||||
{
|
||||
if (propagateNode.GetComponent<FComponentPowerPole>() == null)
|
||||
{
|
||||
propagateNode.powered = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node.GetComponent<FComponentPowerPole>() != 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<Vector3f> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<FactoryChapter> 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<FactoryNode> 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<ScdFactorySyncMap> GetMaps()
|
||||
{
|
||||
List<ScdFactorySyncMap> 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<ScdFactorySyncMapWire> GetWires()
|
||||
{
|
||||
List<ScdFactorySyncMapWire> 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<FactoryNode> 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<FComponentTravelPole>().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<FactoryNode> allNodes)
|
||||
{
|
||||
// Ottieni tutti i compId del nodo da rimuovere
|
||||
HashSet<ulong> 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<FactoryNode> allNodes)
|
||||
{
|
||||
foreach (var node in allNodes)
|
||||
node.powered = false;
|
||||
}
|
||||
void UpdatePowerGrid(List<FactoryNode> allNodes)
|
||||
{
|
||||
ResetAllPower(allNodes);
|
||||
|
||||
HashSet<uint> 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<uint> 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<FactoryNode> nodes=GetNodesInRange(node.position, 15);
|
||||
foreach(FactoryNode propagateNode in nodes)
|
||||
{
|
||||
if (propagateNode.GetComponent<FComponentPowerPole>() == null)
|
||||
{
|
||||
propagateNode.powered = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node.GetComponent<FComponentPowerPole>() != 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<FComponent> components = new();
|
||||
[BsonIgnore]
|
||||
public bool powered = false;
|
||||
[BsonIgnore]
|
||||
public bool lastPowered = false;
|
||||
public List<ConnectedComp> 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<FComponent>() 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<FComponentBusLoader>().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<FComponentBusLoader>().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<Vector3f> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
522
Campofinale/Game/Factory/FactoryNode.cs
Normal file
522
Campofinale/Game/Factory/FactoryNode.cs
Normal file
@@ -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<FComponent> components = new();
|
||||
//Conveyor only
|
||||
public List<Vector3f> points;
|
||||
public bool powered = false;
|
||||
public bool lastPowered = false;
|
||||
public List<ConnectedComp> 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<FacPort> ports = new();
|
||||
if (manager.customPos == FCComponentPos.PortOutManager)
|
||||
{
|
||||
ports = GetTransformedPorts(table.outputPorts);
|
||||
List<FactoryNode> 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<FComponentBoxConveyor>().compId;
|
||||
}
|
||||
else
|
||||
{
|
||||
compPort.touchComId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//Output items
|
||||
foreach (var port in manager.ports)
|
||||
{
|
||||
FComponentBoxConveyor output = chapter.GetCompById<FComponentBoxConveyor>(port.touchComId);
|
||||
FComponentCache outputCache = chapter.GetCompById<FComponentCache>(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<ItemCount>() { add });
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ports = GetTransformedPorts(table.inputPorts);
|
||||
List<FactoryNode> 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<FComponentBoxConveyor>().compId;
|
||||
}
|
||||
else
|
||||
{
|
||||
compPort.touchComId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private bool AddConveyorItem(ItemCount i)
|
||||
{
|
||||
int length=BlockCalculator.CalculateTotalBlocks(points);
|
||||
FComponentBoxConveyor conveyorComp = GetComponent<FComponentBoxConveyor>();
|
||||
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<FComponent>() where FComponent : class
|
||||
{
|
||||
return components.Find(c => c is FComponent) as FComponent;
|
||||
}
|
||||
public FComponent GetComponent<FComponent>(uint compid) where FComponent : class
|
||||
{
|
||||
return components.Find(c => c is FComponent && c.compId==compid) as FComponent;
|
||||
}
|
||||
public List<FacPort> GetTransformedPorts(List<FacPort> originalPorts)
|
||||
{
|
||||
List<FacPort> transformedPorts = new List<FacPort>();
|
||||
|
||||
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<FComponentBusLoader>().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<FComponentBusLoader>().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<Vector3f> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<CsFactoryHsFb>();
|
||||
long curtimestamp = DateTime.UtcNow.ToUnixTimestampMilliseconds();
|
||||
|
||||
List<ScdFacCom> 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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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<uint> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ namespace Campofinale.Resource
|
||||
public static DialogIdTable dialogIdTable = new();//
|
||||
public static Dictionary<string, LevelShortIdTable> levelShortIdTable = new();
|
||||
public static Dictionary<string, FactoryBuildingTable> factoryBuildingTable = new();
|
||||
public static Dictionary<string, FactoryMachineCraftTable> factoryMachineCraftTable = new();
|
||||
public static Dictionary<string, FacSTTNodeTable> facSTTNodeTable = new();
|
||||
public static Dictionary<string, FacSTTLayerTable> facSTTLayerTable = new();
|
||||
public static Dictionary<int, ItemTypeTable> itemTypeTable = new(); //
|
||||
@@ -339,12 +340,55 @@ namespace Campofinale.Resource
|
||||
{
|
||||
return strIdNumTable.item_id.dic[item_id];
|
||||
}
|
||||
|
||||
public static string FindFactoryMachineCraftIdUsingCacheItems(List<ItemCount> 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<string>();
|
||||
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<string, int> propertyKeyToIdMap = new();
|
||||
public List<ParamKeyValue> 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<FacPort> outputPorts = new();
|
||||
public List<FacPort> 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()
|
||||
{
|
||||
|
||||
52
Campofinale/Resource/Table/FactoryMachineCraftTable.cs
Normal file
52
Campofinale/Resource/Table/FactoryMachineCraftTable.cs
Normal file
@@ -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<FactoryMachineCraftIngredient> ingredients = new();
|
||||
public List<FactoryMachineCraftIngredient> 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<ItemCount> GetIngredients()
|
||||
{
|
||||
List<ItemCount> items = new();
|
||||
ingredients.ForEach(i =>
|
||||
{
|
||||
i.group.ForEach(item =>
|
||||
{
|
||||
items.Add(item);
|
||||
});
|
||||
});
|
||||
return items;
|
||||
}
|
||||
|
||||
public class FactoryMachineCraftIngredient
|
||||
{
|
||||
public List<ItemCount> group = new();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,7 @@ namespace Campofinale
|
||||
public delegate void HandlerDelegate(Player sender, string command, string[] args, Player target);
|
||||
}
|
||||
public static List<Player> clients = new List<Player>();
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user