Live Tree Gen
Added client-server communication to sync client techs with DB techs and visualize the tree of actual techs
This commit is contained in:
parent
dabfc62481
commit
6ca699be26
7 changed files with 159 additions and 111 deletions
|
|
@ -4593,13 +4593,13 @@ MonoBehaviour:
|
|||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_textInfo:
|
||||
textComponent: {fileID: 258993626}
|
||||
characterCount: 13
|
||||
characterCount: 0
|
||||
spriteCount: 0
|
||||
spaceCount: 2
|
||||
wordCount: 2
|
||||
spaceCount: 0
|
||||
wordCount: 0
|
||||
linkCount: 0
|
||||
lineCount: 1
|
||||
pageCount: 1
|
||||
lineCount: 0
|
||||
pageCount: 0
|
||||
materialCount: 1
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
|
|
@ -14421,6 +14421,7 @@ MonoBehaviour:
|
|||
Tech: {fileID: 586612708}
|
||||
RadialLink: {fileID: 1417816149}
|
||||
Arrow: {fileID: 1083812776}
|
||||
TestMode: 0
|
||||
TechCount: 500
|
||||
SeedTechs: 15
|
||||
RollingWindowSize: 100
|
||||
|
|
@ -14431,7 +14432,7 @@ MonoBehaviour:
|
|||
PackingMethod: 0
|
||||
Sections: 360
|
||||
PaddingRadians: 3.14
|
||||
StartTier: 12
|
||||
StartTier: 3
|
||||
Scale: 2
|
||||
LinkPoints: 16
|
||||
LinkDepth: 5
|
||||
|
|
@ -17572,13 +17573,13 @@ MonoBehaviour:
|
|||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_textInfo:
|
||||
textComponent: {fileID: 904172350}
|
||||
characterCount: 2
|
||||
characterCount: 0
|
||||
spriteCount: 0
|
||||
spaceCount: 0
|
||||
wordCount: 1
|
||||
wordCount: 0
|
||||
linkCount: 0
|
||||
lineCount: 1
|
||||
pageCount: 1
|
||||
lineCount: 0
|
||||
pageCount: 0
|
||||
materialCount: 1
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
|
|
@ -22582,7 +22583,7 @@ MonoBehaviour:
|
|||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1126386499}
|
||||
m_Enabled: 0
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 1c1faf0a46b9cf24498cd5ec93c34c71, type: 3}
|
||||
m_Name:
|
||||
|
|
@ -22591,6 +22592,8 @@ MonoBehaviour:
|
|||
PrimaryTabGroup: {fileID: 143833105}
|
||||
GalaxyTabButton: {fileID: 646091942}
|
||||
ZoneTabButton: {fileID: 618245060}
|
||||
TechTabButton: {fileID: 1250888060}
|
||||
TechTree: {fileID: 712278635}
|
||||
GalaxyZonePrototype: {fileID: 559120531}
|
||||
GalaxyZoneLinkPrototype: {fileID: 899487252}
|
||||
GalaxyBackground: {fileID: 1938745697}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ using System.Reflection;
|
|||
using System.Text.RegularExpressions;
|
||||
using LiteNetLib;
|
||||
using MessagePack;
|
||||
using QuickGraph;
|
||||
using Unity.Mathematics;
|
||||
using static Unity.Mathematics.math;
|
||||
using Random = Unity.Mathematics.Random;
|
||||
|
|
@ -293,33 +292,33 @@ public static class ObjectExtensions
|
|||
(r2.y + r2.height >= r1.y && r2.y <= r1.y + r1.height);
|
||||
}
|
||||
|
||||
public static IEnumerable<T> FindPath<T>(this IEnumerable<Edge<T>> data, T source, T target, Func<T, T, double> costFunction, bool bestFirst = true) where T : class
|
||||
{
|
||||
List<DijkstraVertex<T>> members = new List<DijkstraVertex<T>>{new DijkstraVertex<T>{Vertex = source}};
|
||||
List<T> searched = new List<T>();
|
||||
while (true)
|
||||
{
|
||||
var v = members.Where(m=>!searched.Contains(m.Vertex)).OrderBy(m=>bestFirst?m.Heuristic:m.Cost).FirstOrDefault();
|
||||
if (v == null) return null; // No vertices left unsearched
|
||||
if (v.Vertex == target)
|
||||
{
|
||||
Stack<DijkstraVertex<T>> path = new Stack<DijkstraVertex<T>>();
|
||||
path.Push(v);
|
||||
while(path.Peek().Parent!=null)
|
||||
path.Push(path.Peek().Parent);
|
||||
return path.Select(dv => dv.Vertex).ToList();
|
||||
}
|
||||
members.AddRange(data.Where(l => l.Source == v.Vertex).Select(l => l.Target).Concat(data.Where(l => l.Target == v.Vertex).Select(l => l.Source))
|
||||
.Where(n => members.All(m => m.Vertex != n)).Select(n =>
|
||||
{
|
||||
var c = new DijkstraVertex<T> {Parent = v, Vertex = n, Cost = v.Cost + costFunction(v.Vertex,n)};
|
||||
if (bestFirst)
|
||||
c.Heuristic = c.Cost + costFunction(c.Vertex,target);
|
||||
return c;
|
||||
}));
|
||||
searched.Add(v.Vertex);
|
||||
}
|
||||
}
|
||||
// public static IEnumerable<T> FindPath<T>(this IEnumerable<Edge<T>> data, T source, T target, Func<T, T, double> costFunction, bool bestFirst = true) where T : class
|
||||
// {
|
||||
// List<DijkstraVertex<T>> members = new List<DijkstraVertex<T>>{new DijkstraVertex<T>{Vertex = source}};
|
||||
// List<T> searched = new List<T>();
|
||||
// while (true)
|
||||
// {
|
||||
// var v = members.Where(m=>!searched.Contains(m.Vertex)).OrderBy(m=>bestFirst?m.Heuristic:m.Cost).FirstOrDefault();
|
||||
// if (v == null) return null; // No vertices left unsearched
|
||||
// if (v.Vertex == target)
|
||||
// {
|
||||
// Stack<DijkstraVertex<T>> path = new Stack<DijkstraVertex<T>>();
|
||||
// path.Push(v);
|
||||
// while(path.Peek().Parent!=null)
|
||||
// path.Push(path.Peek().Parent);
|
||||
// return path.Select(dv => dv.Vertex).ToList();
|
||||
// }
|
||||
// members.AddRange(data.Where(l => l.Source == v.Vertex).Select(l => l.Target).Concat(data.Where(l => l.Target == v.Vertex).Select(l => l.Source))
|
||||
// .Where(n => members.All(m => m.Vertex != n)).Select(n =>
|
||||
// {
|
||||
// var c = new DijkstraVertex<T> {Parent = v, Vertex = n, Cost = v.Cost + costFunction(v.Vertex,n)};
|
||||
// if (bestFirst)
|
||||
// c.Heuristic = c.Cost + costFunction(c.Vertex,target);
|
||||
// return c;
|
||||
// }));
|
||||
// searched.Add(v.Vertex);
|
||||
// }
|
||||
// }
|
||||
|
||||
class DijkstraVertex<T>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,11 +5,22 @@ using LiteNetLib;
|
|||
using MessagePack;
|
||||
using Unity.Mathematics;
|
||||
|
||||
[Union(0, typeof(PingMessage)), Union(1, typeof(LoginMessage)), Union(2, typeof(RegisterMessage)),
|
||||
Union(3, typeof(VerifyMessage)), Union(4, typeof(ErrorMessage)), Union(5, typeof(LoginSuccessMessage)),
|
||||
Union(6, typeof(ChatMessage)), Union(7, typeof(ChatBroadcastMessage)), Union(8, typeof(ChangeNameMessage)),
|
||||
Union(9, typeof(GalaxyRequestMessage)), Union(10, typeof(GalaxyResponseMessage)),
|
||||
Union(11, typeof(ZoneRequestMessage)), Union(12, typeof(ZoneResponseMessage)), MessagePackObject]
|
||||
[Union(0, typeof(PingMessage)),
|
||||
Union(1, typeof(LoginMessage)),
|
||||
Union(2, typeof(RegisterMessage)),
|
||||
Union(3, typeof(VerifyMessage)),
|
||||
Union(4, typeof(ErrorMessage)),
|
||||
Union(5, typeof(LoginSuccessMessage)),
|
||||
Union(6, typeof(ChatMessage)),
|
||||
Union(7, typeof(ChatBroadcastMessage)),
|
||||
Union(8, typeof(ChangeNameMessage)),
|
||||
Union(9, typeof(GalaxyRequestMessage)),
|
||||
Union(10, typeof(GalaxyResponseMessage)),
|
||||
Union(11, typeof(ZoneRequestMessage)),
|
||||
Union(12, typeof(ZoneResponseMessage)),
|
||||
Union(13, typeof(BlueprintsRequestMessage)),
|
||||
Union(14, typeof(BlueprintsResponseMessage)),
|
||||
MessagePackObject]
|
||||
public abstract class Message
|
||||
{
|
||||
[IgnoreMember] public NetPeer Peer;
|
||||
|
|
@ -108,4 +119,17 @@ public class ZoneResponseMessage : Message
|
|||
{
|
||||
[Key(0)] public ZoneData Zone;
|
||||
[Key(1)] public DatabaseEntry[] Contents;
|
||||
}
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class BlueprintsRequestMessage : Message
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class BlueprintsResponseMessage : Message
|
||||
{
|
||||
[Key(0)] public BlueprintData[] Blueprints;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,9 @@ public class StrategyGameManager : MonoBehaviour
|
|||
// Request galaxy description from the server
|
||||
CultClient.Send(new GalaxyRequestMessage());
|
||||
|
||||
// Request blueprints from the server
|
||||
CultClient.Send(new BlueprintsRequestMessage());
|
||||
|
||||
// Listen for the server's galaxy description
|
||||
CultClient.AddMessageListener<GalaxyResponseMessage>(galaxy =>
|
||||
{
|
||||
|
|
@ -74,6 +77,8 @@ public class StrategyGameManager : MonoBehaviour
|
|||
if (_currentTab == GalaxyTabButton && !_galaxyPopulated) PopulateGalaxy();
|
||||
});
|
||||
|
||||
CultClient.AddMessageListener<BlueprintsResponseMessage>(response => _cache.AddAll(response.Blueprints, true));
|
||||
|
||||
// Listen for zone descriptions from the server
|
||||
CultClient.AddMessageListener<ZoneResponseMessage>(zone =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -128,6 +128,8 @@ public class TechTreeMsagl : MonoBehaviour
|
|||
_arrowInstances.Clear();
|
||||
|
||||
var graph = new GeometryGraph();
|
||||
|
||||
var settings = new SugiyamaLayoutSettings();
|
||||
|
||||
if (TestMode)
|
||||
{
|
||||
|
|
@ -154,7 +156,18 @@ public class TechTreeMsagl : MonoBehaviour
|
|||
|
||||
foreach (var targetBlueprint in Blueprints)
|
||||
{
|
||||
//foreach(var sourceBlueprint in Blueprints.Where(sb => targetBlueprint.Dependencies.Any(dep=>sb.ID==dep)))
|
||||
foreach (var sourceBlueprint in Blueprints.Where(sb =>
|
||||
targetBlueprint.Dependencies.Any(dep => sb.ID == dep)))
|
||||
{
|
||||
graph.Edges.Add(new Edge(nodeMap[sourceBlueprint], nodeMap[targetBlueprint]));
|
||||
var splitName = sourceBlueprint.Name.Split(' ');
|
||||
if (splitName.Length > 1)
|
||||
{
|
||||
var nameStart = string.Join(" ", splitName.Take(splitName.Length - 1));
|
||||
if(targetBlueprint.Name.StartsWith(nameStart))
|
||||
settings.AddSameLayerNeighbors(nodeMap[sourceBlueprint], nodeMap[targetBlueprint]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -179,8 +192,6 @@ public class TechTreeMsagl : MonoBehaviour
|
|||
}
|
||||
}
|
||||
|
||||
var settings = new SugiyamaLayoutSettings();
|
||||
|
||||
var islandsBySize = islands.OrderByDescending(i => i.Nodes.Count);
|
||||
var largestIsland = islandsBySize.First();
|
||||
foreach (var island in islandsBySize.Skip(1))
|
||||
|
|
@ -294,7 +305,7 @@ public class TechTreeMsagl : MonoBehaviour
|
|||
{
|
||||
var tech = Tech.Instantiate<TechNode>();
|
||||
tech.transform.position = (Vector2) positions[vertex];
|
||||
tech.Label.text = $"{(int) vertex.UserData}";
|
||||
tech.Label.text = $"{(TestMode ? ((int) vertex.UserData).ToString() : ((BlueprintData) vertex.UserData).ID.ToString().Substring(0,2))}";
|
||||
var gradient = tech.Label.colorGradient;
|
||||
gradient.bottomLeft = gradient.bottomRight = islandColors[islandMap[vertex]];
|
||||
tech.Label.colorGradient = gradient;
|
||||
|
|
|
|||
|
|
@ -156,68 +156,68 @@ public class TechTreeTest : MonoBehaviour
|
|||
i => i.Key,
|
||||
i => i.Select(g => g.Key).ToArray());
|
||||
|
||||
if (MultipleDependencies)
|
||||
{
|
||||
var vertexTiers = new Dictionary<IntVertex, int>();
|
||||
foreach (var island in islandsInverse.Values)
|
||||
{
|
||||
vertexTiers[island[0]] = 0;
|
||||
foreach (var vertex in island.Skip(1))
|
||||
{
|
||||
vertexTiers[vertex] = edges.FindPath(vertex, island[0], (v1, v2) => 1).Count();
|
||||
// var tryGetPath = graph.ShortestPathsDijkstra(edge => 1, vertex);
|
||||
// if (tryGetPath(island[0], out var path))
|
||||
// {
|
||||
// vertexTiers[vertex] = path.Count();
|
||||
// }
|
||||
// else Debug.Log("Path to root not found?");
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var island in islandsInverse.Values)
|
||||
{
|
||||
foreach (var vertex in island.Skip(1))
|
||||
{
|
||||
//var tryGetPath = graph.ShortestPathsDijkstra(edge => 1, vertex);
|
||||
//var ancestors = island.Take(Array.IndexOf(island, vertex) - 1);
|
||||
var possibleDependencies = island.Where(v =>
|
||||
{
|
||||
var dist = edges.FindPath(vertex, v, (v1, v2) => 1).Count();
|
||||
return v != vertex &&
|
||||
vertexTiers[v] < vertexTiers[vertex] &&
|
||||
abs(vertexTiers[v] - vertexTiers[vertex]) < MaxDependencyTierDifference &&
|
||||
dist < MaxDependencyDistance && dist > 2;
|
||||
// if (v != vertex && tryGetPath(v, out var path))
|
||||
// {
|
||||
// return path.Count() > 1 && path.Count() < MaxDependencyDistance;
|
||||
// }
|
||||
//
|
||||
// return false;
|
||||
}).ToArray();
|
||||
var dependencies = new List<int>();
|
||||
while (dependencies.Count < possibleDependencies.Length && Random.value < MultipleDependencyProbability)
|
||||
{
|
||||
var depIndex = Random.Range(0, possibleDependencies.Length);
|
||||
dependencies.Add(depIndex);
|
||||
edges.Add(new Edge<IntVertex>(possibleDependencies[depIndex], vertex));
|
||||
}
|
||||
// while (Random.value < MultipleDependencyProbability)
|
||||
// {
|
||||
// var index = Array.IndexOf(island, vertex);
|
||||
// int depIndex;
|
||||
// int tries = 0;
|
||||
// do
|
||||
// {
|
||||
// depIndex = Random.Range(max(0, index - MultipleDependencyRollingWindow), index);
|
||||
// } while (tries < 10 && dependencies.Contains(depIndex));
|
||||
//
|
||||
// if (tries < 10)
|
||||
// edges.Add(new Edge<IntVertex>(island[depIndex], vertex));
|
||||
// else break;
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (MultipleDependencies)
|
||||
// {
|
||||
// var vertexTiers = new Dictionary<IntVertex, int>();
|
||||
// foreach (var island in islandsInverse.Values)
|
||||
// {
|
||||
// vertexTiers[island[0]] = 0;
|
||||
// foreach (var vertex in island.Skip(1))
|
||||
// {
|
||||
// vertexTiers[vertex] = edges.FindPath(vertex, island[0], (v1, v2) => 1).Count();
|
||||
// // var tryGetPath = graph.ShortestPathsDijkstra(edge => 1, vertex);
|
||||
// // if (tryGetPath(island[0], out var path))
|
||||
// // {
|
||||
// // vertexTiers[vertex] = path.Count();
|
||||
// // }
|
||||
// // else Debug.Log("Path to root not found?");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// foreach (var island in islandsInverse.Values)
|
||||
// {
|
||||
// foreach (var vertex in island.Skip(1))
|
||||
// {
|
||||
// //var tryGetPath = graph.ShortestPathsDijkstra(edge => 1, vertex);
|
||||
// //var ancestors = island.Take(Array.IndexOf(island, vertex) - 1);
|
||||
// var possibleDependencies = island.Where(v =>
|
||||
// {
|
||||
// var dist = edges.FindPath(vertex, v, (v1, v2) => 1).Count();
|
||||
// return v != vertex &&
|
||||
// vertexTiers[v] < vertexTiers[vertex] &&
|
||||
// abs(vertexTiers[v] - vertexTiers[vertex]) < MaxDependencyTierDifference &&
|
||||
// dist < MaxDependencyDistance && dist > 2;
|
||||
// // if (v != vertex && tryGetPath(v, out var path))
|
||||
// // {
|
||||
// // return path.Count() > 1 && path.Count() < MaxDependencyDistance;
|
||||
// // }
|
||||
// //
|
||||
// // return false;
|
||||
// }).ToArray();
|
||||
// var dependencies = new List<int>();
|
||||
// while (dependencies.Count < possibleDependencies.Length && Random.value < MultipleDependencyProbability)
|
||||
// {
|
||||
// var depIndex = Random.Range(0, possibleDependencies.Length);
|
||||
// dependencies.Add(depIndex);
|
||||
// edges.Add(new Edge<IntVertex>(possibleDependencies[depIndex], vertex));
|
||||
// }
|
||||
// // while (Random.value < MultipleDependencyProbability)
|
||||
// // {
|
||||
// // var index = Array.IndexOf(island, vertex);
|
||||
// // int depIndex;
|
||||
// // int tries = 0;
|
||||
// // do
|
||||
// // {
|
||||
// // depIndex = Random.Range(max(0, index - MultipleDependencyRollingWindow), index);
|
||||
// // } while (tries < 10 && dependencies.Contains(depIndex));
|
||||
// //
|
||||
// // if (tries < 10)
|
||||
// // edges.Add(new Edge<IntVertex>(island[depIndex], vertex));
|
||||
// // else break;
|
||||
// // }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if (EliminateIslands!=EliminateIslandMode.None)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -140,6 +140,12 @@ namespace ChatApp.Server
|
|||
StarDensity = mapLayers["StarDensity"]
|
||||
}));
|
||||
|
||||
server.AddMessageListener<BlueprintsRequestMessage>(blueprintRequest => blueprintRequest.Peer.Send(
|
||||
new BlueprintsResponseMessage
|
||||
{
|
||||
Blueprints = cache.GetAll<BlueprintData>().ToArray()
|
||||
}));
|
||||
|
||||
server.AddMessageListener<ZoneRequestMessage>(zoneRequest =>
|
||||
{
|
||||
var zone = cache.Get<ZoneData>(zoneRequest.ZoneID);
|
||||
|
|
|
|||
Loading…
Reference in a new issue