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:
hyperion51 2020-04-14 07:03:34 +01:00
commit 6ca699be26
7 changed files with 159 additions and 111 deletions

View file

@ -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}

View file

@ -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>
{

View file

@ -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;
}

View file

@ -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 =>
{

View file

@ -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;

View file

@ -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)
{

View file

@ -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);