factory manager now is working!!

This commit is contained in:
AlessandroCH
2025-08-07 01:05:16 +02:00
parent fee2df2fd9
commit aa59766cfd
12 changed files with 702 additions and 103 deletions

View File

@@ -11,6 +11,7 @@ using MongoDB.Driver;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using static Campofinale.Game.Adventure.AdventureBookManager; using static Campofinale.Game.Adventure.AdventureBookManager;
using static Campofinale.Game.Factory.FactoryManager;
using static Campofinale.Resource.ResourceManager; using static Campofinale.Resource.ResourceManager;
namespace Campofinale.Database namespace Campofinale.Database
@@ -103,7 +104,10 @@ namespace Campofinale.Database
{ {
return _database.GetCollection<SpaceshipRoom>("spaceship_rooms").Find(c => c.owner == roleId).ToList(); return _database.GetCollection<SpaceshipRoom>("spaceship_rooms").Find(c => c.owner == roleId).ToList();
} }
public FactoryData LoadFactoryData(ulong roleId)
{
return _database.GetCollection<FactoryData>("factory").Find(c => c.roleId == roleId).ToList().FirstOrDefault();
}
public List<Item> LoadInventoryItems(ulong roleId) public List<Item> LoadInventoryItems(ulong roleId)
{ {
return _database.GetCollection<Item>("items").Find(c => c.owner == roleId).ToList(); return _database.GetCollection<Item>("items").Find(c => c.owner == roleId).ToList();
@@ -319,6 +323,22 @@ namespace Campofinale.Database
new ReplaceOptions { IsUpsert = true } new ReplaceOptions { IsUpsert = true }
); );
} }
public void UpsertFactoryData(FactoryData item)
{
if (item._id == ObjectId.Empty)
{
item._id = ObjectId.GenerateNewId();
}
var collection = _database.GetCollection<FactoryData>("factory");
var filter =
Builders<FactoryData>.Filter.Eq(c => c.roleId, item.roleId);
var result = collection.ReplaceOne(
filter,
item,
new ReplaceOptions { IsUpsert = true }
);
}
public void UpsertItem(Item item) public void UpsertItem(Item item)
{ {
if (item._id == ObjectId.Empty) if (item._id == ObjectId.Empty)
@@ -427,6 +447,6 @@ namespace Campofinale.Database
} }
} }
} }
} }

View File

@@ -33,9 +33,25 @@ namespace Campofinale.Game.Entities
this.BornRot = rot; this.BornRot = rot;
this.templateId = templateId; this.templateId = templateId;
this.sceneNumId = scene; this.sceneNumId = scene;
} }
public void InitDefaultProperties()
{
InteractiveData data = ResourceManager.interactiveData.Find(i => i.id == templateId);
if (data != null)
{
properties.AddRange(data.saveProperties);
}
}
public void SetPropValue(uint val, string key)
{
ParamKeyValue keyValue = properties.Find(p => p.key == key);
if (keyValue != null)
{
keyValue.value.valueArray[0].valueBit64 = val;
}
}
public SceneInteractive ToProto() public SceneInteractive ToProto()
{ {
@@ -105,15 +121,17 @@ namespace Campofinale.Game.Entities
{ {
string oriTemplateId = ResourceManager.interactiveTable.interactiveDataDict[templateId].templateId; string oriTemplateId = ResourceManager.interactiveTable.interactiveDataDict[templateId].templateId;
InteractiveData data=ResourceManager.interactiveData.Find(i=>i.id == oriTemplateId); InteractiveData data=ResourceManager.interactiveData.Find(i=>i.id == oriTemplateId);
if(data != null) if(data != null)
{ {
return (true,data.propertyKeyToIdMap[key]); return (true,data.propertyKeyToIdMap[key]);
} }
Logger.PrintError("Interactive Data not found");
return (false, maxCur + 1); return (false, maxCur + 1);
} }
catch (Exception ex) catch (Exception ex)
{ {
//Logger.PrintError(ex.Message); Logger.PrintError(ex.Message);
return (false,maxCur+1); return (false,maxCur+1);
} }

View File

@@ -43,7 +43,11 @@ namespace Campofinale.Game.Entities
{ {
List<AttrInfo> attrInfo = new(); List<AttrInfo> attrInfo = new();
EnemyTable table = ResourceManager.enemyTable[templateId]; EnemyTable table = ResourceManager.enemyTable[templateId];
enemyAttributeTemplateTable[table.attrTemplateId].levelDependentAttributes[level].attrs.ForEach(attr => if(level >= enemyAttributeTemplateTable[table.attrTemplateId].levelDependentAttributes.Count)
{
level = 80;
}
enemyAttributeTemplateTable[table.attrTemplateId].levelDependentAttributes[level-1].attrs.ForEach(attr =>
{ {
attrInfo.Add(new AttrInfo() attrInfo.Add(new AttrInfo()
{ {

View File

@@ -5,13 +5,17 @@ namespace Campofinale.Game.Factory.Components
{ {
public class FComponentTravelPole : FComponent public class FComponentTravelPole : FComponent
{ {
public uint defaultNext;
public FComponentTravelPole(uint id) : base(id, FCComponentType.TravelPole) public FComponentTravelPole(uint id) : base(id, FCComponentType.TravelPole)
{ {
} }
public override void SetComponentInfo(ScdFacCom proto) public override void SetComponentInfo(ScdFacCom proto)
{ {
proto.TravelPole = new(); proto.TravelPole = new()
{
DefaultNext = defaultNext
};
} }
} }
} }

View File

@@ -1,9 +1,15 @@
using Campofinale.Game.Entities; using Campofinale.Database;
using Campofinale.Game.Entities;
using Campofinale.Game.Factory.Components; using Campofinale.Game.Factory.Components;
using Campofinale.Packets.Sc; using Campofinale.Packets.Sc;
using Campofinale.Protocol; using Campofinale.Protocol;
using Campofinale.Resource; using Campofinale.Resource;
using Campofinale.Resource.Table;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Attributes;
using System.Linq;
using System.Numerics;
using System.Xml.Linq;
using static Campofinale.Resource.ResourceManager; using static Campofinale.Resource.ResourceManager;
namespace Campofinale.Game.Factory namespace Campofinale.Game.Factory
@@ -12,18 +18,40 @@ namespace Campofinale.Game.Factory
{ {
public Player player; public Player player;
public List<FactoryChapter> chapters = new(); public List<FactoryChapter> chapters = new();
public ObjectId _id;
public class FactoryData
{
public ulong roleId;
public ObjectId _id;
public List<FactoryChapter> chapters = new();
}
public FactoryManager(Player player) public FactoryManager(Player player)
{ {
this.player = player; this.player = player;
} }
public void Load() public void Load()
{ {
//TODO Save FactoryData data = DatabaseManager.db.LoadFactoryData(player.roleId);
chapters.Add(new FactoryChapter("domain_1", player.roleId)); if (data != null)
chapters.Add(new FactoryChapter("domain_2", player.roleId)); {
_id=data._id;
chapters = data.chapters;
}
if(!ChapterExist("domain_1")) chapters.Add(new FactoryChapter("domain_1", player.roleId));
if(!ChapterExist("domain_2")) chapters.Add(new FactoryChapter("domain_2", player.roleId));
}
public bool ChapterExist(string id)
{
return chapters.Find(c=>c.chapterId==id)!=null;
}
public void Save()
{
DatabaseManager.db.UpsertFactoryData(new FactoryData()
{
_id= _id,
roleId=player.roleId,
chapters=chapters
});
} }
public void ExecOp(CsFactoryOp op, ulong seq) public void ExecOp(CsFactoryOp op, ulong seq)
{ {
@@ -62,11 +90,180 @@ namespace Campofinale.Game.Factory
public List<FactoryNode> nodes=new(); public List<FactoryNode> nodes=new();
public uint v = 1; public uint v = 1;
public uint compV = 0; 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() public void Update()
{ {
try try
{ {
UpdatePowerGrid(nodes);
foreach (FactoryNode node in nodes) foreach (FactoryNode node in nodes)
{ {
node.Update(this); node.Update(this);
@@ -89,51 +286,242 @@ namespace Campofinale.Game.Factory
switch (op.OpType) switch (op.OpType)
{ {
case FactoryOpType.Place: case FactoryOpType.Place:
CreateNode(op.Place, seq); 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; break;
default: default:
break; 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() public uint nextCompV()
{ {
compV++; compV++;
return compV; return compV;
} }
private void CreateNode(CsdFactoryOpPlace place, ulong seq) 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++; v++;
uint nodeId = v; uint nodeId = v;
CsdFactoryOpPlace place = op.Place;
FactoryBuildingTable table = ResourceManager.factoryBuildingTable[place.TemplateId]; FactoryBuildingTable table = ResourceManager.factoryBuildingTable[place.TemplateId];
FactoryNode node = new() FactoryNode node = new()
{ {
nodeId = nodeId, nodeId = nodeId,
templateId = place.TemplateId, templateId = place.TemplateId,
mapId = place.MapId, mapId = place.MapId,
sceneNumId = GetOwner().sceneManager.GetCurScene().sceneNumId,
nodeType = table.GetNodeType(), nodeType = table.GetNodeType(),
position = new Vector3f(place.Position), position = new Vector3f(place.Position),
direction = new Vector3f(place.Direction), direction = new Vector3f(place.Direction),
guid = GetOwner().random.NextRand() worldPosition = new Vector3f(place.InteractiveParam.Position),
guid = GetOwner().random.NextRand(),
}; };
node.InitComponents(this); node.InitComponents(this);
GetOwner().Send(new PacketScFactoryModifyChapterNodes(GetOwner(), chapterId, node));
nodes.Add(node); nodes.Add(node);
ScFactoryModifyChapterNodes edit = new() node.SendEntity(GetOwner(), chapterId);
{
ChapterId = chapterId, GetOwner().Send(new PacketScFactoryOpRet(GetOwner(), node.nodeId,op),seq);
Tms = DateTime.UtcNow.ToUnixTimestampMilliseconds(),
};
GetOwner().Send(new PacketScFactorySyncChapter(GetOwner(), chapterId));
edit.Nodes.Add(node.ToProto());
Logger.Print(Newtonsoft.Json.JsonConvert.SerializeObject(edit, Newtonsoft.Json.Formatting.Indented));
EntityInteractive e = new(place.TemplateId, GetOwner().roleId, new Vector3f(place.Position), new Vector3f(place.Direction), GetOwner().sceneManager.GetCurScene().sceneNumId, node.guid);
GetOwner().sceneManager.GetCurScene().entities.Add(e);
GetOwner().sceneManager.GetCurScene().SpawnEntity(e);
GetOwner().Send(ScMsgId.ScFactoryModifyChapterNodes, edit);
GetOwner().Send(new PacketScFactoryOpRet(GetOwner(), node.nodeId,FactoryOpType.Place),seq);
} }
@@ -165,46 +553,39 @@ namespace Campofinale.Game.Factory
public string templateId; public string templateId;
public Vector3f position=new(); public Vector3f position=new();
public Vector3f direction = new(); public Vector3f direction = new();
public Vector3f worldPosition = new();
public string instKey=""; public string instKey="";
public bool deactive = false; public bool deactive = false;
public int mapId; public int mapId;
public int sceneNumId;
public bool forcePowerOn = false; public bool forcePowerOn = false;
public List<FComponent> components = new(); public List<FComponent> components = new();
[BsonIgnore] [BsonIgnore]
public bool powered = false; public bool powered = false;
[BsonIgnore] [BsonIgnore]
public uint connectedPowerNode = 0; public bool lastPowered = false;
public List<ConnectedComp> connectedComps = new();
public ulong guid; 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) public void Update(FactoryChapter chapter)
{ {
if(!templateId.Contains("hub")) LevelScene scen = GetLevelData(sceneNumId);
if (GetComponent<FComponentPowerPole>() != null) if (lastPowered != powered)
{ {
FactoryNode curEnergyNode = chapter.nodes.Find(n => n.nodeId == connectedPowerNode && n.position.Distance(position) <= 20 && n.InPower()); lastPowered = powered;
if (templateId != "power_pole_2") chapter.GetOwner().Send(new PacketScFactoryModifyChapterNodes(chapter.GetOwner(), chapter.chapterId, this));
{
FactoryNode energyNode = chapter.GetNodesInRange(position, 20).Find(n=>n.GetComponent< FComponentPowerPole>()!=null && n.InPower());
if (energyNode != null && curEnergyNode==null && energyNode.connectedPowerNode!=nodeId)
{
powered= true;
connectedPowerNode = energyNode.nodeId;
chapter.GetOwner().Send(ScMsgId.ScFactoryModifyChapterNodes, new ScFactoryModifyChapterNodes() { Tms = DateTime.UtcNow.ToUnixTimestampMilliseconds(), Nodes = { this.ToProto()} });
}
else
{
if (curEnergyNode == null && powered==true)
{
powered = false;
connectedPowerNode = 0;
chapter.GetOwner().Send(ScMsgId.ScFactoryModifyChapterNodes, new ScFactoryModifyChapterNodes() { Tms = DateTime.UtcNow.ToUnixTimestampMilliseconds(), Nodes = { this.ToProto() } });
}
}
}
else
{
//Check near
}
} }
} }
public bool InPower() public bool InPower()
{ {
@@ -222,41 +603,54 @@ namespace Campofinale.Game.Factory
{ {
FMesh mesh = new FMesh(); FMesh mesh = new FMesh();
if (ResourceManager.factoryBuildingTable.ContainsKey(templateId)) if (ResourceManager.factoryBuildingTable.TryGetValue(templateId, out FactoryBuildingTable table))
{ {
FactoryBuildingTable table = ResourceManager.factoryBuildingTable[templateId]; float width = table.range.width - 1;
float height = table.range.height - 1;
float depth = table.range.depth-1;
double centerX = position.x + table.range.width / 2.0; Vector3f p1_final = new Vector3f();
double centerZ = position.z + table.range.depth / 2.0; Vector3f p2_final = new Vector3f();
Vector3f p1 = new Vector3f(position.x, position.y, position.z); switch (direction.y)
Vector3f p2 = new Vector3f( {
position.x + table.range.width, case 0f:
position.y + table.range.height, case 360f:
position.z + table.range.depth 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;
p1 = RotateAroundY(p1, new Vector3f((float)centerX, position.y, (float)centerZ), direction.y); case 90f:
p2 = RotateAroundY(p2, new Vector3f((float)centerX, position.y, (float)centerZ), direction.y); // Rotazione 90°: Larghezza e profondità si scambiano.
mesh.points.Add(p1); // Il mesh parte da 'position' ma si estende su assi diversi.
mesh.points.Add(p2); 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; return mesh;
} }
private Vector3f RotateAroundY(Vector3f point, Vector3f origin, double angleDegrees)
{
double angleRadians = angleDegrees * (Math.PI / 180.0);
double cosTheta = Math.Cos(angleRadians);
double sinTheta = Math.Sin(angleRadians);
double dx = point.x - origin.x;
double dz = point.z - origin.z;
double rotatedX = origin.x + (dx * cosTheta - dz * sinTheta);
double rotatedZ = origin.z + (dx * sinTheta + dz * cosTheta);
return new Vector3f((float)rotatedX, point.y, (float)rotatedZ);
}
public ScdFacNode ToProto() public ScdFacNode ToProto()
{ {
ScdFacNode node = new ScdFacNode() ScdFacNode node = new ScdFacNode()
@@ -270,7 +664,7 @@ namespace Campofinale.Game.Factory
Power = new() Power = new()
{ {
InPower= InPower(), InPower= InPower(),
NeedInPower=false, NeedInPower=true,
}, },
NodeType=(int)nodeType, NodeType=(int)nodeType,
@@ -286,7 +680,8 @@ namespace Campofinale.Game.Factory
if(templateId!="__inventory__") if(templateId!="__inventory__")
{ {
node.Transform.Mesh = GetMesh().ToProto(); node.Transform.Mesh = GetMesh().ToProto();
node.Transform.WorldPosition = position.ToProto(); node.Transform.Position = position.ToProtoScd();
node.Transform.WorldPosition = worldPosition.ToProto();
node.Transform.WorldRotation = direction.ToProto(); node.Transform.WorldRotation = direction.ToProto();
node.InteractiveObject = new() node.InteractiveObject = new()
{ {
@@ -354,6 +749,50 @@ namespace Campofinale.Game.Factory
} }
} }
public void SendEntity(Player player, string chapterId)
{
Entity exist = player.sceneManager.GetCurScene().entities.Find(e => e.guid == guid);
if (exist != null)
{
exist.Position = worldPosition;
exist.Rotation = direction;
ScMoveObjectMove move = new()
{
ServerNotify = true,
MoveInfo =
{
new MoveObjectMoveInfo()
{
Objid = guid,
SceneNumId=sceneNumId,
MotionInfo = new()
{
Position=exist.Position.ToProto(),
Rotation=exist.Rotation.ToProto(),
Speed=new Vector()
{
},
State=MotionState.MotionNone
}
}
}
};
player.Send(ScMsgId.ScMoveObjectMove, move);
}
else
{
EntityInteractive e = new(interactiveFacWrapperTable[templateId].interactiveTemplateId, player.roleId, worldPosition, direction, sceneNumId, guid);
e.InitDefaultProperties();
e.SetPropValue(nodeId, "factory_inst_id");
player.sceneManager.GetCurScene().entities.Add(e);
player.sceneManager.GetCurScene().SpawnEntity(e);
}
}
[BsonDiscriminator(Required = true)] [BsonDiscriminator(Required = true)]
[BsonKnownTypes(typeof(FComponentSelector))] [BsonKnownTypes(typeof(FComponentSelector))]

View File

@@ -3,8 +3,10 @@ using Campofinale.Game.Inventory;
using Campofinale.Packets.Sc; using Campofinale.Packets.Sc;
using Campofinale.Resource; using Campofinale.Resource;
using Campofinale.Resource.Dynamic; using Campofinale.Resource.Dynamic;
using Campofinale.Resource.Table;
using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Attributes;
using System; using System;
using System.Diagnostics;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using static Campofinale.Resource.Dynamic.SpawnerConfig; using static Campofinale.Resource.Dynamic.SpawnerConfig;
using static Campofinale.Resource.ResourceManager; using static Campofinale.Resource.ResourceManager;
@@ -220,13 +222,18 @@ namespace Campofinale.Game
{ {
foreach (var level in ResourceManager.levelDatas) foreach (var level in ResourceManager.levelDatas)
{ {
if(scenes.Find(s=>s.sceneNumId==level.idNum) == null) int grade = 1;
if (ResourceManager.levelGradeTable.ContainsKey(level.id))
{
grade = ResourceManager.levelGradeTable[level.id].grades.Last().grade;
}
if (scenes.Find(s=>s.sceneNumId==level.idNum) == null)
scenes.Add(new Scene() scenes.Add(new Scene()
{ {
guid = (ulong)player.random.Next(), guid = (ulong)player.random.Next(),
ownerId=player.roleId, ownerId=player.roleId,
sceneNumId=level.idNum, sceneNumId=level.idNum,
grade= grade
}); });
} }
} }
@@ -260,6 +267,8 @@ namespace Campofinale.Game
public List<ulong> activeScripts = new(); public List<ulong> activeScripts = new();
public List<LevelScript> scripts = new(); public List<LevelScript> scripts = new();
public int grade = 0;
public int GetCollection(string id) public int GetCollection(string id)
{ {
if (collections.ContainsKey(id)) if (collections.ContainsKey(id))
@@ -304,7 +313,18 @@ namespace Campofinale.Game
{ {
Unload(); Unload();
LevelScene lv_scene = ResourceManager.GetLevelData(sceneNumId); LevelScene lv_scene = ResourceManager.GetLevelData(sceneNumId);
LevelGradeInfo sceneGrade = null;
LevelGradeTable table = null;
ResourceManager.levelGradeTable.TryGetValue(lv_scene.id, out table);
if (table != null)
{
sceneGrade=table.grades.Find(g=>g.grade==grade);
}
if (sceneGrade == null)
{
sceneGrade = new();
}
lv_scene.levelData.interactives.ForEach(en => lv_scene.levelData.interactives.ForEach(en =>
{ {
if (GetOwner().noSpawnAnymore.Contains(en.levelLogicId) && sceneNumId != 87) if (GetOwner().noSpawnAnymore.Contains(en.levelLogicId) && sceneNumId != 87)
@@ -342,7 +362,7 @@ namespace Campofinale.Game
{ {
if(GetOwner().noSpawnAnymore.Contains(en.levelLogicId) && sceneNumId != 87) return; if(GetOwner().noSpawnAnymore.Contains(en.levelLogicId) && sceneNumId != 87) return;
EntityMonster entity = new(en.entityDataIdKey,en.level,ownerId,en.position,en.rotation, sceneNumId, en.levelLogicId) EntityMonster entity = new(en.entityDataIdKey,sceneGrade.monsterBaseLevel+ en.level,ownerId,en.position,en.rotation, sceneNumId, en.levelLogicId)
{ {
type=en.entityType, type=en.entityType,
belongLevelScriptId=en.belongLevelScriptId, belongLevelScriptId=en.belongLevelScriptId,
@@ -366,7 +386,16 @@ namespace Campofinale.Game
entity.defaultHide = en.defaultHide; entity.defaultHide = en.defaultHide;
entities.Add(entity); entities.Add(entity);
}); });
GetOwner().factoryManager.chapters.ForEach(ch =>
{
ch.nodes.ForEach(n =>
{
if (n.sceneNumId == sceneNumId)
{
n.SendEntity(GetOwner(), ch.chapterId);
}
});
});
UpdateShowEntities(); UpdateShowEntities();
} }

View File

@@ -0,0 +1,37 @@
using Campofinale.Game.Factory;
using Campofinale.Network;
using Campofinale.Protocol;
namespace Campofinale.Packets.Sc
{
public class PacketScFactoryModifyChapterNodes : Packet
{
public PacketScFactoryModifyChapterNodes(Player client,string chapterId,FactoryNode node) {
ScFactoryModifyChapterNodes edit = new()
{
ChapterId = chapterId,
Tms = DateTime.UtcNow.ToUnixTimestampMilliseconds()/1000,
Nodes =
{
node.ToProto()
}
};
SetData(ScMsgId.ScFactoryModifyChapterNodes, edit);
}
public PacketScFactoryModifyChapterNodes(Player client, string chapterId, uint nodeId)
{
ScFactoryModifyChapterNodes edit = new()
{
ChapterId = chapterId,
Tms = DateTime.UtcNow.ToUnixTimestampMilliseconds() / 1000,
RemoveNodes =
{
nodeId
}
};
SetData(ScMsgId.ScFactoryModifyChapterNodes, edit);
}
}
}

View File

@@ -6,23 +6,50 @@ namespace Campofinale.Packets.Sc
public class PacketScFactoryOpRet : Packet public class PacketScFactoryOpRet : Packet
{ {
public PacketScFactoryOpRet(Player client, uint nodeId,FactoryOpType type) { public PacketScFactoryOpRet(Player client, uint val,CsFactoryOp op) {
ScFactoryOpRet proto = new ScFactoryOpRet() ScFactoryOpRet proto = new ScFactoryOpRet()
{ {
RetCode=FactoryOpRetCode.Ok, RetCode=FactoryOpRetCode.Ok,
OpType=type, OpType=op.OpType,
}; };
if(type == FactoryOpType.Place) if(op.OpType == FactoryOpType.Place)
{ {
proto.Place = new() proto.Place = new()
{ {
NodeId = nodeId NodeId = val
}; };
proto.Index = "CHANNLE_BUILDING";
} }
if (op.OpType == FactoryOpType.MoveNode)
{
proto.MoveNode = new()
{
};
}
if (op.OpType == FactoryOpType.AddConnection)
{
proto.AddConnection = new()
{
Index = val,
};
}
if (op.OpType == FactoryOpType.Dismantle)
{
proto.Dismantle = new()
{
};
}
if (op.OpType == FactoryOpType.SetTravelPoleDefaultNext)
{
proto.SetTravelPoleDefaultNext = new()
{
};
}
proto.Index=op.Index;
SetData(ScMsgId.ScFactoryOpRet, proto); SetData(ScMsgId.ScFactoryOpRet, proto);
} }

View File

@@ -12,7 +12,7 @@ namespace Campofinale.Packets.Sc
public PacketScFactorySyncChapter(Player client, string chapterId) { public PacketScFactorySyncChapter(Player client, string chapterId) {
string json = File.ReadAllText("ScFactorySyncChapter.json"); /*string json = File.ReadAllText("ScFactorySyncChapter.json");
//ScFactorySyncChapter chapter = Newtonsoft.Json.JsonConvert.DeserializeObject<ScFactorySyncChapter>(json); //ScFactorySyncChapter chapter = Newtonsoft.Json.JsonConvert.DeserializeObject<ScFactorySyncChapter>(json);
ScFactorySyncChapter chapter = new() ScFactorySyncChapter chapter = new()
@@ -61,7 +61,7 @@ namespace Campofinale.Packets.Sc
} }
} }
}*/ }
}, },
Blackboard = new() Blackboard = new()
{ {
@@ -119,7 +119,7 @@ namespace Campofinale.Packets.Sc
{ {
}, },
});*/ });
LevelGradeInfo sceneGrade = ResourceManager.levelGradeTable[levelGroup].grades[0]; LevelGradeInfo sceneGrade = ResourceManager.levelGradeTable[levelGroup].grades[0];
chapter.Blackboard.Power.PowerGen += sceneGrade.bandwidth; chapter.Blackboard.Power.PowerGen += sceneGrade.bandwidth;
chapter.Blackboard.Power.PowerSaveMax += sceneGrade.bandwidth; chapter.Blackboard.Power.PowerSaveMax += sceneGrade.bandwidth;
@@ -185,9 +185,9 @@ namespace Campofinale.Packets.Sc
foreach(FactoryNode node in client.factoryManager.GetChapter(chapterId).nodes) foreach(FactoryNode node in client.factoryManager.GetChapter(chapterId).nodes)
{ {
chapter.Nodes.Add(node.ToProto()); chapter.Nodes.Add(node.ToProto());
} }*/
//Logger.Print(Newtonsoft.Json.JsonConvert.SerializeObject(chapter,Newtonsoft.Json.Formatting.Indented)); //Logger.Print(Newtonsoft.Json.JsonConvert.SerializeObject(chapter,Newtonsoft.Json.Formatting.Indented));
SetData(ScMsgId.ScFactorySyncChapter, chapter); SetData(ScMsgId.ScFactorySyncChapter, client.factoryManager.GetChapter(chapterId).ToProto());
} }
} }

View File

@@ -617,6 +617,7 @@ namespace Campofinale
inventoryManager.Save(); inventoryManager.Save();
spaceshipManager.Save(); spaceshipManager.Save();
adventureBookManager.Save(); adventureBookManager.Save();
factoryManager.Save();
if(Server.config.serverOptions.missionsEnabled) missionSystem.Save(); if(Server.config.serverOptions.missionsEnabled) missionSystem.Save();
SaveCharacters(); SaveCharacters();
SaveMails(); SaveMails();

View File

@@ -5,6 +5,7 @@ using Newtonsoft.Json;
using System.Numerics; using System.Numerics;
using System; using System;
using static Campofinale.Resource.ResourceManager.LevelScene; using static Campofinale.Resource.ResourceManager.LevelScene;
using static Campofinale.Resource.ResourceManager.LevelScene.LevelData;
namespace Campofinale.Resource namespace Campofinale.Resource
{ {
@@ -73,6 +74,7 @@ namespace Campofinale.Resource
public static Dictionary<int, ItemTypeTable> itemTypeTable = new(); // public static Dictionary<int, ItemTypeTable> itemTypeTable = new(); //
public static Dictionary<string, SNSChatTable> snsChatTable = new();// public static Dictionary<string, SNSChatTable> snsChatTable = new();//
public static Dictionary<string, GiftItemTable> giftItemTable = new(); public static Dictionary<string, GiftItemTable> giftItemTable = new();
public static Dictionary<string, InteractiveFacWrapperTable> interactiveFacWrapperTable = new();
public static List<MissionDataTable> missionDataTable = new(); public static List<MissionDataTable> missionDataTable = new();
public static InteractiveTable interactiveTable = new(); // public static InteractiveTable interactiveTable = new(); //
@@ -225,6 +227,7 @@ namespace Campofinale.Resource
foreach (string json in jsonFiles) foreach (string json in jsonFiles)
{ {
InteractiveData data = JsonConvert.DeserializeObject<InteractiveData>(ReadJsonFile(json)); InteractiveData data = JsonConvert.DeserializeObject<InteractiveData>(ReadJsonFile(json));
if (data != null) if (data != null)
{ {
interactiveData.Add(data); interactiveData.Add(data);
@@ -339,7 +342,8 @@ namespace Campofinale.Resource
public class InteractiveData public class InteractiveData
{ {
public string id; public string id;
public Dictionary<string, int> propertyKeyToIdMap; public Dictionary<string, int> propertyKeyToIdMap = new();
public List<ParamKeyValue> saveProperties = new();
} }
public class FactoryBuildingTable public class FactoryBuildingTable
{ {
@@ -816,6 +820,10 @@ namespace Campofinale.Resource
param.ValueIntList.Add(val.valueBit64); param.ValueIntList.Add(val.valueBit64);
param.ValueType = (int)ParamValueType.Int; param.ValueType = (int)ParamValueType.Int;
break; break;
case ParamRealType.UInt:
param.ValueIntList.Add(val.valueBit64);
param.ValueType = (int)ParamValueType.Int;
break;
case ParamRealType.WaterVolumePtr: case ParamRealType.WaterVolumePtr:
param.ValueIntList.Add(val.valueBit64); param.ValueIntList.Add(val.valueBit64);
param.ValueType = (int)ParamValueType.Int; param.ValueType = (int)ParamValueType.Int;
@@ -980,6 +988,10 @@ namespace Campofinale.Resource
{ {
return new Vector3f(v.x * scalar, v.y * scalar, v.z * scalar); return new Vector3f(v.x * scalar, v.y * scalar, v.z * scalar);
} }
public static Vector3f operator +(Vector3f v, Vector3f v2)
{
return new Vector3f(v.x + v2.x, v.y + v2.y, v.z + v2.z);
}
public Vector3f(float x, float y, float z) public Vector3f(float x, float y, float z)
{ {
this.x = x; this.x = x;

View File

@@ -0,0 +1,8 @@
namespace Campofinale.Resource.Table
{
[TableCfgType("TableCfg/InteractiveFacWrapperTable.json", LoadPriority.LOW)]
public class InteractiveFacWrapperTable
{
public string interactiveTemplateId;
}
}