Aetheria/Assets/Scripts/StrategyGameManager.cs
hyperion51 0ae4a388f5 Improved Context Menus
Context menus now support dropdown options
Context menus can now be created for UI elements with new dedicated cancellation click catcher
Game manager creates context menus based on the object being clicked, no need for duplicate code in every context that object appears
2020-05-22 00:01:07 +01:00

815 lines
34 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NaughtyAttributes;
using RethinkDb.Driver.Net;
using TMPro;
using UnityEngine;
using Unity.Mathematics;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using static Unity.Mathematics.math;
using float2 = Unity.Mathematics.float2;
using Random = UnityEngine.Random;
public class StrategyGameManager : MonoBehaviour
{
public bool TestMode;
[Section("Scene Links")]
public Camera Camera;
public TechTreeMsagl TechTree;
public MeshRenderer GalaxyBackground;
public Transform ZoneRoot;
public MeshRenderer ZoneBackground;
public MeshRenderer ZoneBoundary;
public ClickRaycaster ClickRaycaster;
public ReadOnlyPropertiesPanel PropertiesPanel;
public ContextMenu ContextMenu;
public RectTransform GameMenuRoot;
public RectTransform CorpMenuRoot;
public CorporationMenuItem CorpOptionPrefab;
public TabButton CorpMenuContinueButton;
public TMP_InputField CorpNameInputField;
[Section("Tab Links")]
public TabGroup PrimaryTabGroup;
public TabButton GalaxyTabButton;
public TabButton ZoneTabButton;
public TabButton TechTabButton;
[Section("Prefabs & Prototypes")]
public Prototype GalaxyZonePrototype;
public Prototype GalaxyZoneLinkPrototype;
public ZoneObject ZoneObjectPrefab;
public ZoneShip ZoneShipPrefab;
public MeshFilter BeltPrefab;
[Section("Textures")]
public Texture2D PlanetoidSprite;
public Texture2D PlanetSprite;
public Texture2D GasGiantSprite;
public Texture2D OrbitalSprite;
public Texture2D SunSprite;
public Texture2D WormholeSprite;
[Section("UI Properties")]
public Color SelectedColor;
public Color UnselectedColor;
public float GalaxyScale;
public float ZoneSizeScale = .01f;
public float ZoneMassScale = .01f;
public float ZoneMassPower = .5f;
public int AsteroidSpritesheetWidth = 4;
public int AsteroidSpritesheetHeight = 4;
private DatabaseCache _cache;
private GameContext _context;
// private GalaxyResponseMessage _galaxyResponse;
private TabButton _currentTab;
private bool _galaxyPopulated;
private Guid _populatedZone;
private Guid _selectedZone;
private GalaxyZone _selectedGalaxyZone;
private Dictionary<Guid, GalaxyZone> _galaxyZoneObjects = new Dictionary<Guid, GalaxyZone>();
private Dictionary<Guid, ZoneObject> _zoneObjects = new Dictionary<Guid, ZoneObject>(); // Key is Orbit
private Dictionary<Guid, AsteroidBelt> _zoneBelts = new Dictionary<Guid, AsteroidBelt>();
private Dictionary<Ship, ZoneShip> _zoneShips = new Dictionary<Ship, ZoneShip>();
private List<ZoneObject> _wormholes = new List<ZoneObject>();
private Vector3 _galaxyCameraPos = -Vector3.forward;
private float _galaxyOrthoSize = 50;
private Material _boundaryMaterial;
private Material _backgroundMaterial;
private bool _techLayoutGenerated;
private Connection _connection;
// private bool _choosingCorporation;
private Guid _playerCorporation;
private Dictionary<CorporationMenuItem, Guid> _corpOptionMap = new Dictionary<CorporationMenuItem, Guid>();
private CorporationMenuItem _selectedParent;
void Start()
{
ConsoleController.MessageReceiver = this;
_galaxyOrthoSize = GalaxyScale / 2;
_cache = new DatabaseCache();
if (TestMode)
{
_cache.Load(new DirectoryInfo(Application.dataPath).Parent.FullName);
_context = new GameContext(_cache, Debug.Log);
TechTree.Context = _context;
_context.MapLayers = _cache.GetAll<GalaxyMapLayerData>().ToDictionary(ml => ml.Name);
_context.GalaxyZones = _cache.GetAll<ZoneData>()
.ToDictionary(z => z.ID, z => new SimplifiedZoneData
{
Links = z.Wormholes.ToArray(),
Name = z.Name,
Position = z.Position,
ZoneID = z.ID
});
foreach (var zone in _context.GalaxyZones.Keys) GenerateZone(zone);
var megas = _cache.GetAll<MegaCorporation>();
if (megas.First().HomeZone == Guid.Empty)
{
_context.PlaceMegas();
}
var player = _cache.GetAll<Player>().FirstOrDefault();
if (player == null)
{
player = new Player
{
Context = _context,
ID = Guid.NewGuid(),
Username = Environment.UserName
};
_cache.Add(player);
}
if (player.Corporation == Guid.Empty)
{
GameMenuRoot.gameObject.SetActive(false);
CorpMenuRoot.gameObject.SetActive(true);
foreach (var mega in megas)
{
var corpOption = Instantiate(CorpOptionPrefab, CorpMenuRoot);
_corpOptionMap[corpOption] = mega.ID;
corpOption.Title.text = mega.Name;
corpOption.Logo.sprite = Resources.Load<Sprite>(mega.Logo.Substring("Assets/Resources/".Length).Split('.').First());
corpOption.Description.text = mega.Description;
var corpOptionImage = corpOption.GetComponent<Image>();
corpOptionImage.color = UnselectedColor;
corpOption.GetComponent<Button>().onClick.AddListener(() =>
{
if (_selectedParent != null)
{
_selectedParent.GetComponent<Image>().color = UnselectedColor;
}
_selectedParent = corpOption;
corpOptionImage.color = SelectedColor;
});
foreach (var attributeValue in mega.Personality.Select(kvp =>
new {attribute = _cache.Get<PersonalityAttribute>(kvp.Key), val = kvp.Value}))
{
var attributeInstance = Instantiate(corpOption.AttributePrefab, corpOption.transform);
attributeInstance.Slider.value = attributeValue.val;
attributeInstance.Title.text = attributeValue.attribute.Name;
attributeInstance.HighLabel.text = attributeValue.attribute.HighName;
attributeInstance.LowLabel.text = attributeValue.attribute.LowName;
}
}
CorpMenuContinueButton.OnClick += _ =>
{
if (_selectedParent != null && !string.IsNullOrEmpty(CorpNameInputField.text))
{
var newCorp = new Corporation
{
Context = _context,
ID = Guid.NewGuid(),
Name = CorpNameInputField.text,
Parent = _corpOptionMap[_selectedParent]
};
_cache.Add(newCorp);
player.Corporation = newCorp.ID;
GameMenuRoot.gameObject.SetActive(true);
CorpMenuRoot.gameObject.SetActive(false);
_selectedZone = _cache.Get<MegaCorporation>(newCorp.Parent).HomeZone;
ZoneTabButton.OnPointerClick(null);
}
};
}
}
else
{
// 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 =>
{
_context.GalaxyZones = galaxy.Zones.ToDictionary(z => z.ZoneID);
_cache.Add(galaxy.GlobalData, true);
_context = new GameContext(_cache, Debug.Log);
TechTree.Context = _context;
_context.MapLayers["StarDensity"] = galaxy.StarDensity;
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 =>
{
// Cache zone data and contents
_cache.Add(zone.Zone);
foreach (var entry in zone.Contents) _cache.Add(entry);
if(_currentTab==GalaxyTabButton && _selectedZone == zone.Zone.ID)
PopulateZoneProperties(_selectedZone);
if (_currentTab == ZoneTabButton && _populatedZone != zone.Zone.ID) PopulateZone();
});
}
PrimaryTabGroup.OnTabChange += button =>
{
_currentTab = button;
if (_currentTab == GalaxyTabButton)
{
PropertiesPanel.gameObject.SetActive(true);
PopulateGalaxyProperties();
if (!_galaxyPopulated) PopulateGalaxy();
Camera.transform.position = _galaxyCameraPos;
Camera.orthographicSize = _galaxyOrthoSize;
}
else if (_currentTab == ZoneTabButton)
{
PropertiesPanel.gameObject.SetActive(true);
var zone = _cache.Get<ZoneData>(_selectedZone);
if (_populatedZone != _selectedZone && zone != null)
PopulateZone();
PopulateZoneProperties(_populatedZone);
Camera.transform.position = -Vector3.forward;
if (zone != null)
Camera.orthographicSize = zone.Radius * ZoneSizeScale;
}
else if (_currentTab == TechTabButton)
{
PropertiesPanel.gameObject.SetActive(true);
PopulateTechProperties();
if (!_techLayoutGenerated)
{
TechTree.Initialize();
TechTree.Blueprints = _cache.GetAll<BlueprintData>().ToArray();
TechTree.GenerateTechs();
}
}
else PropertiesPanel.gameObject.SetActive(false);
};
_boundaryMaterial = ZoneBoundary.material;
_backgroundMaterial = ZoneBackground.material;
ClickRaycaster.OnClickMiss += () =>
{
if (_currentTab == GalaxyTabButton) PopulateGalaxyProperties();
else if (_currentTab == ZoneTabButton) PopulateZoneProperties(_populatedZone);
else if (_currentTab == TechTabButton) PopulateTechProperties();
};
}
private void PopulateGalaxyProperties()
{
PropertiesPanel.Clear();
PropertiesPanel.Title.text = _context.GlobalData.GalaxyName;
PropertiesPanel.AddSection("Galaxy");
PropertiesPanel.AddProperty("Sectors", $"{_context.GalaxyZones.Count}");
}
private void PopulateZoneProperties(Guid zone)
{
PropertiesPanel.Clear();
var zoneData = _cache.Get<ZoneData>(zone);
PropertiesPanel.Title.text = zoneData.Name;
PropertiesPanel.AddSection("Sector");
PropertiesPanel.AddProperty("Planets", $"{zoneData.Planets.Length}");
}
private void PopulateTechProperties()
{
PropertiesPanel.Clear();
PropertiesPanel.Title.text = "Technologies";
var count = _context.Cache.GetAll<BlueprintData>().Count();
PropertiesPanel.AddProperty("Discovered Techs", $"{count}");
PropertiesPanel.AddProperty("Available Techs", $"{count}");
PropertiesPanel.AddProperty("Researched Techs", $"{count}");
}
private void Update()
{
if (_context != null)
{
_context.Time = Time.time;
//Debug.Log($"Unity delta time: {Time.deltaTime}");
_context.Update();
}
if (_currentTab == GalaxyTabButton)
{
_galaxyCameraPos = Camera.transform.position;
_galaxyOrthoSize = Camera.orthographicSize;
}
if (_currentTab == ZoneTabButton && _populatedZone == _selectedZone)
{
foreach (var planet in _zoneObjects)
{
planet.Value.transform.position = float3(_context.GetOrbitPosition(planet.Key) * ZoneSizeScale, .1f);
}
foreach (var belt in _zoneBelts)
{
belt.Value.Transform.position = float3(_context.GetOrbitPosition(belt.Key) * ZoneSizeScale, .15f);
belt.Value.Update();
}
foreach (var ship in _zoneShips)
{
ship.Value.transform.position = float3(ship.Key.Position * ZoneSizeScale, .05f);
ship.Value.Icon.transform.up = (Vector2) ship.Key.Direction;
var thrusterScale = ship.Value.Thruster.localScale;
thrusterScale.x = ship.Key.Axes[ship.Key.GetAxis<Thruster>()].Value;
ship.Value.Thruster.localScale = thrusterScale;
}
}
}
private void OnApplicationQuit()
{
if (TestMode)
{
// TODO: Save game state on exit
}
}
void ShowContextMenu(object clickTarget)
{
ContextMenu.gameObject.SetActive(true);
ContextMenu.Clear();
if (clickTarget is PlanetData planet)
{
ContextMenu.AddOption("Test Option 1", () => Debug.Log("Test Option 1 Selected"));
ContextMenu.AddOption("Test Option 2", () => Debug.Log("Test Option 2 Selected"));
ContextMenu.AddDropdown("Test Dropdown", new []
{
("Dropdown Option 1", (Action) (() => Debug.Log("Dropdown Option 1 Selected"))),
("Dropdown Option 2", (Action) (() => Debug.Log("Dropdown Option 2 Selected"))),
("Dropdown Option 3", (Action) (() => Debug.Log("Dropdown Option 3 Selected")))
});
ContextMenu.AddOption("Test Option 3", () => Debug.Log("Test Option 3 Selected"));
}
ContextMenu.Show();
}
void PopulateGalaxy()
{
_galaxyPopulated = true;
GalaxyBackground.transform.localScale = Vector3.one * GalaxyScale;
var galaxyMat = GalaxyBackground.material;
galaxyMat.SetFloat("Arms", _context.GlobalData.Arms);
galaxyMat.SetFloat("Twist", _context.GlobalData.Twist);
galaxyMat.SetFloat("TwistPower", _context.GlobalData.TwistPower);
galaxyMat.SetFloat("SpokeOffset", _context.MapLayers["StarDensity"].SpokeOffset);
galaxyMat.SetFloat("SpokeScale", _context.MapLayers["StarDensity"].SpokeScale);
galaxyMat.SetFloat("CoreBoost", _context.MapLayers["StarDensity"].CoreBoost);
galaxyMat.SetFloat("CoreBoostOffset", _context.MapLayers["StarDensity"].CoreBoostOffset);
galaxyMat.SetFloat("CoreBoostPower", _context.MapLayers["StarDensity"].CoreBoostPower);
galaxyMat.SetFloat("EdgeReduction", _context.MapLayers["StarDensity"].EdgeReduction);
galaxyMat.SetFloat("NoisePosition", _context.MapLayers["StarDensity"].NoisePosition);
galaxyMat.SetFloat("NoiseAmplitude", _context.MapLayers["StarDensity"].NoiseAmplitude);
galaxyMat.SetFloat("NoiseOffset", _context.MapLayers["StarDensity"].NoiseOffset);
galaxyMat.SetFloat("NoiseGain", _context.MapLayers["StarDensity"].NoiseGain);
galaxyMat.SetFloat("NoiseLacunarity", _context.MapLayers["StarDensity"].NoiseLacunarity);
galaxyMat.SetFloat("NoiseFrequency", _context.MapLayers["StarDensity"].NoiseFrequency);
// var zones = _galaxyResponse.Zones.ToDictionary(z=>z.ZoneID);
var linkedZones = new List<Guid>();
foreach (var zone in _context.GalaxyZones.Values)
{
linkedZones.Add(zone.ZoneID);
var instance = GalaxyZonePrototype.Instantiate<Transform>();
instance.position = float3((Vector2) zone.Position - Vector2.one * .5f,0) * GalaxyScale;
var instanceZone = instance.GetComponent<GalaxyZone>();
_galaxyZoneObjects[zone.ZoneID] = instanceZone;
instanceZone.Label.text = zone.Name;
instanceZone.Background.GetComponent<ClickableCollider>().OnClick += (_, pointer) =>
{
if (_selectedGalaxyZone != null)
_selectedGalaxyZone.Background.material.SetColor("_TintColor", UnselectedColor);
if(_selectedZone != zone.ZoneID)
CultClient.Send(new ZoneRequestMessage{ZoneID = zone.ZoneID});
if (TestMode)
{
// if(!_context.Cache.Get<ZoneData>(zone.ZoneID).Visited)
// {
// GenerateZone(zone.ZoneID);
// }
PopulateZoneProperties(zone.ZoneID);
}
_selectedZone = zone.ZoneID;
_selectedGalaxyZone = instanceZone;
_selectedGalaxyZone.Background.material.SetColor("_TintColor", SelectedColor);
_selectedZone = zone.ZoneID;
// If the user double clicks on a zone, switch to the zone tab
if(pointer.clickCount == 2) ZoneTabButton.OnPointerClick(pointer);
};
if(_selectedZone == zone.ZoneID)
{
_selectedGalaxyZone = instanceZone;
_selectedGalaxyZone.Background.material.SetColor("_TintColor", SelectedColor);
}
foreach (var linkedZone in zone.Links.Where(l=>!linkedZones.Contains(l)))
{
var link = GalaxyZoneLinkPrototype.Instantiate<Transform>();
var diff = _context.GalaxyZones[linkedZone].Position - zone.Position;
link.position = instance.position + Vector3.forward*.1f;
link.rotation = Quaternion.Euler(0,0,atan2(diff.y, diff.x) * Mathf.Rad2Deg);
link.localScale = new Vector3(length(diff) * GalaxyScale, 1, 1);
}
}
}
void GenerateZone(Guid zone)
{
var zoneData = _cache.Get<ZoneData>(zone);
float2 position;
do
{
position = float2(Random.value, Random.value);
} while (_context.MapLayers["StarDensity"].Evaluate(position, _context.GlobalData) < .1f);
OrbitData[] orbits;
PlanetData[] planets;
ZoneGenerator.GenerateZone(
context: _context,
zone: zoneData,
mapLayers: _context.MapLayers.Values,
resources: _cache.GetAll<SimpleCommodityData>().Where(i=>i.ResourceDensity.Any()),
orbitData: out orbits,
planetsData: out planets);
_cache.AddAll(orbits);
_cache.AddAll(planets);
zoneData.Visited = true;
}
void PopulateZone()
{
// Delete all the existing zone contents
foreach (var zoneObject in _zoneObjects.Values) Destroy(zoneObject.gameObject);//zoneObject.GetComponent<Prototype>().ReturnToPool();
_zoneObjects.Clear();
foreach (var zoneObject in _wormholes) Destroy(zoneObject.gameObject); //zoneObject.GetComponent<Prototype>().ReturnToPool();
_wormholes.Clear();
foreach (var belt in _zoneBelts.Values) Destroy(belt.Transform.gameObject);
_zoneBelts.Clear();
foreach (var ship in _zoneShips.Values) Destroy(ship.gameObject);
_zoneShips.Clear();
_populatedZone = _selectedZone;
var zoneData = _cache.Get<ZoneData>(_populatedZone);
if (TestMode && !zoneData.Visited)
{
GenerateZone(_populatedZone);
}
_context.ForceLoadZone = _populatedZone;
float zoneDepth = 0;
foreach (var planet in _context.ZonePlanets[_populatedZone])
{
var planetData = _cache.Get<PlanetData>(planet);
if (!planetData.Belt)
{
var planetObject = Instantiate(ZoneObjectPrefab, ZoneRoot);
_zoneObjects[planetData.Orbit] = planetObject;
planetObject.Label.text = planetData.Name;
planetObject.GravityMesh.gameObject.SetActive(true);
planetObject.GravityMesh.transform.localScale =
Vector3.one * (pow(planetData.Mass, _context.GlobalData.GravityRadiusExponent) *
_context.GlobalData.GravityRadiusMultiplier * 2 * ZoneSizeScale);
var depth = pow(planetData.Mass, ZoneMassPower) * ZoneMassScale;
if (depth > zoneDepth)
zoneDepth = depth;
planetObject.GravityMesh.material.SetFloat("_Depth", depth);
planetObject.Icon.material.SetTexture("_MainTex",
planetData.Mass > _context.GlobalData.SunMass ? SunSprite :
planetData.Mass > _context.GlobalData.GasGiantMass ? GasGiantSprite :
planetData.Mass > _context.GlobalData.PlanetMass ? PlanetSprite :
PlanetoidSprite);
planetObject.Icon.GetComponent<ClickableCollider>().OnClick += (collider, data) =>
{
if (data.button == PointerEventData.InputButton.Left)
{
PropertiesPanel.Clear();
PropertiesPanel.Title.text = planetData.Name;
PropertiesPanel.AddSection(planetData.Mass > _context.GlobalData.SunMass ? "Star" :
planetData.Mass > _context.GlobalData.GasGiantMass ? "Gas Giant" :
planetData.Mass > _context.GlobalData.PlanetMass ? "Planet" :
"Planetoid");
PropertiesPanel.AddProperty("Mass", $"{planetData.Mass}");
PropertiesPanel.AddList("Resources", planetData.Resources.Select(resource =>
{
var itemData = _context.Cache.Get<SimpleCommodityData>(resource.Key);
return new Tuple<string, string>(itemData.Name, $"{resource.Value:0}");
}));
}
else if (data.button == PointerEventData.InputButton.Right)
{
ShowContextMenu(planetData);
}
};
}
else
{
var beltObject = Instantiate(BeltPrefab, ZoneRoot);
var collider = beltObject.GetComponent<MeshCollider>();
var belt = new AsteroidBelt(_context, beltObject, collider, planetData, AsteroidSpritesheetWidth, AsteroidSpritesheetHeight, ZoneSizeScale);
_zoneBelts[_cache.Get<OrbitData>(planetData.Orbit).Parent] = belt;
beltObject.GetComponent<ClickableCollider>().OnClick += (_, data) =>
{
if (data.button == PointerEventData.InputButton.Left)
{
PropertiesPanel.Clear();
PropertiesPanel.Title.text = planetData.Name;
PropertiesPanel.AddSection("Asteroid Belt");
PropertiesPanel.AddProperty("Mass", $"{planetData.Mass}");
PropertiesPanel.AddList("Resources", planetData.Resources.Select(resource =>
{
var itemData = _context.Cache.Get<SimpleCommodityData>(resource.Key);
return new Tuple<string, string>(itemData.Name, $"{resource.Value:0}");
}));
}
else if (data.button == PointerEventData.InputButton.Right)
{
ShowContextMenu(planetData);
}
};
}
}
var radius = (zoneData.Radius * ZoneSizeScale * 2);
_backgroundMaterial.SetFloat("_ClipDistance", radius);
_backgroundMaterial.SetFloat("_HeightRange", zoneDepth + _boundaryMaterial.GetFloat("_Depth"));
ZoneBoundary.transform.localScale = Vector3.one * radius;
foreach (var wormhole in zoneData.Wormholes)
{
var otherZone = _context.GalaxyZones[wormhole];
var wormholeObject = Instantiate(ZoneObjectPrefab, ZoneRoot);
_wormholes.Add(wormholeObject);
wormholeObject.transform.position = (Vector2) (_context.WormholePosition(zoneData.ID, wormhole) * ZoneSizeScale);
wormholeObject.GravityMesh.gameObject.SetActive(false);
wormholeObject.Icon.material.SetTexture("_MainTex", WormholeSprite);
wormholeObject.Label.text = otherZone.Name;
wormholeObject.Icon.GetComponent<ClickableCollider>().OnClick += (_, pointer) =>
{
// If the user double clicks on a wormhole, switch to that zone
if (pointer.clickCount == 2)
{
_selectedGalaxyZone.Background.material.SetColor("_TintColor", UnselectedColor);
if(_selectedZone != wormhole && !TestMode)
CultClient.Send(new ZoneRequestMessage{ZoneID = wormhole});
_selectedZone = wormhole;
if(TestMode)
PopulateZone();
_selectedGalaxyZone = _galaxyZoneObjects[wormhole];
_selectedGalaxyZone.Background.material.SetColor("_TintColor", SelectedColor);
}
};
}
}
void spawn(string[] args)
{
if (!TestMode)
return;
var zoneData = _cache.Get<ZoneData>(_populatedZone);
if (zoneData == null)
{
Debug.Log("Attempted to spawn ship but no zone is populated!");
return;
}
// Parse first argument as hull name, default to Fighter if argument missing
HullData hullData;
if (args.Length > 1)
{
hullData = _cache.GetAll<HullData>().FirstOrDefault(h => h.Name == args[1]);
if (hullData == null)
{
Debug.Log($"Hull with name \"{args[1]}\" not found!");
return;
}
}
else
{
hullData = _cache.GetAll<HullData>().FirstOrDefault(h => h.Name == "Fighter");
}
var hull = _context.CreateInstance(hullData.ID, .9f) as Gear;
List<Gear> gear = new List<Gear>();
if (args.Length > 2)
{
foreach (string arg in args.Skip(2))
{
var gearData = _cache.GetAll<GearData>().FirstOrDefault(h => h.Name == arg);
if (gearData == null)
{
Debug.Log($"Gear with name \"{arg}\" not found!");
return;
}
gear.Add(_context.CreateInstance(gearData.ID, .9f) as Gear);
}
}
else
{
// If no gear arguments supplied and we're spawning a ship, get the first thruster and put it in
if (args[0] == "ship")
{
var thrusterData = _cache.GetAll<GearData>().FirstOrDefault(g => g.Behaviors.Any(b => b is ThrusterData));
var thruster = _context.CreateInstance(thrusterData.ID, .9f) as Gear;
gear.Add(thruster);
}
}
if (args[0] == "ship")
{
var entity = new Ship(_context, hull.ID, gear.Select(i=>i.ID), Enumerable.Empty<Guid>(), _populatedZone);
_context.Cache.Add(entity);
_context.ZoneEntities[_populatedZone][entity.ID] = entity;
//_context.Agents.Add(new AgentController(_context, _populatedZone, entity.ID));
var zoneShip = Instantiate(ZoneShipPrefab, ZoneRoot);
zoneShip.Label.text = $"Ship {_zoneShips.Count}";
_zoneShips[entity] = zoneShip;
}
else
{
Debug.Log($"Unknown entity type: \"{args[0]}\"");
}
}
void newzone(string[] args)
{
var zoneData = _cache.Get<ZoneData>(_selectedZone);
if (zoneData == null)
{
Debug.Log("Attempted to regenerate zone but no zone is selected!");
return;
}
if(_populatedZone!=Guid.Empty)
_context.UnloadZone(_populatedZone);
_cache.Delete(zoneData);
_context.GalaxyZones.Remove(zoneData.ID);
var newZone = zoneData.Copy();
newZone.ID = Guid.NewGuid();
newZone.Name = newZone.ID.ToString().Substring(0, 8);
newZone.Visited = false;
var linkedZones = _cache.GetAll<ZoneData>().Where(z => z.Wormholes.Any(w => w == zoneData.ID)).ToArray();
foreach (var linkedZone in linkedZones)
{
linkedZone.Wormholes.Remove(zoneData.ID);
linkedZone.Wormholes.Add(newZone.ID);
}
newZone.Wormholes = linkedZones.Select(z => z.ID).ToList();
var zone = _context.GalaxyZones[newZone.ID] = new SimplifiedZoneData
{
Links = newZone.Wormholes.ToArray(),
Name = newZone.Name,
Position = newZone.Position,
ZoneID = newZone.ID
};
var galaxyZone = _galaxyZoneObjects[zoneData.ID];
_galaxyZoneObjects.Remove(zoneData.ID);
galaxyZone.Label.text = newZone.Name;
_galaxyZoneObjects[newZone.ID] = galaxyZone;
var collider = galaxyZone.Background.GetComponent<ClickableCollider>();
collider.Clear();
collider.OnClick += (_, pointer) =>
{
if (_selectedGalaxyZone != null)
_selectedGalaxyZone.Background.material.SetColor("_TintColor", UnselectedColor);
if(_selectedZone != zone.ZoneID)
CultClient.Send(new ZoneRequestMessage{ZoneID = zone.ZoneID});
_selectedZone = zone.ZoneID;
_selectedGalaxyZone = galaxyZone;
_selectedGalaxyZone.Background.material.SetColor("_TintColor", SelectedColor);
_selectedZone = zone.ZoneID;
// If the user double clicks on a zone, switch to the zone tab
if(pointer.clickCount == 2) ZoneTabButton.OnPointerClick(pointer);
};
_cache.Add(newZone);
_selectedZone = newZone.ID;
_populatedZone = Guid.Empty;
if(_currentTab == ZoneTabButton)
PopulateZone();
}
}
public class AsteroidBelt
{
public Transform Transform;
private MeshFilter _filter;
private MeshCollider _collider;
private Vector3[] _vertices;
private Vector3[] _normals;
private Vector2[] _uvs;
private int[] _indices;
private PlanetData _data;
private GameContext _context;
private Mesh _mesh;
private float _zoneScale;
public AsteroidBelt(GameContext context, MeshFilter meshFilter, MeshCollider collider, PlanetData data, int spritesheetWidth, int spritesheetHeight, float zoneScale)
{
Transform = collider.transform;
_context = context;
_data = data;
_filter = meshFilter;
_collider = collider;
_zoneScale = zoneScale;
_vertices = new Vector3[data.Asteroids.Length*4];
_normals = new Vector3[data.Asteroids.Length*4];
_uvs = new Vector2[data.Asteroids.Length*4];
_indices = new int[data.Asteroids.Length*6];
var maxDist = 0f;
var spriteSize = float2(1f / spritesheetWidth, 1f / spritesheetHeight);
// vertex order: bottom left, top left, top right, bottom right
for (var i = 0; i < _data.Asteroids.Length; i++)
{
if (_data.Asteroids[i].x > maxDist)
maxDist = _data.Asteroids[i].x;
var spriteX = Random.Range(0, spritesheetWidth);
var spriteY = Random.Range(0, spritesheetHeight);
_uvs[i * 4] = new Vector2(spriteX * spriteSize.x, spriteY * spriteSize.y);
_uvs[i * 4 + 1] = new Vector2(spriteX * spriteSize.x, spriteY * spriteSize.y + spriteSize.y);
_uvs[i * 4 + 2] = new Vector2(spriteX * spriteSize.x + spriteSize.x, spriteY * spriteSize.y + spriteSize.y);
_uvs[i * 4 + 3] = new Vector2(spriteX * spriteSize.x + spriteSize.x, spriteY * spriteSize.y);
_indices[i * 6] = i * 4;
_indices[i * 6 + 1] = i * 4 + 1;
_indices[i * 6 + 2] = i * 4 + 3;
_indices[i * 6 + 3] = i * 4 + 3;
_indices[i * 6 + 4] = i * 4 + 1;
_indices[i * 6 + 5] = i * 4 + 2;
}
for (var i = 0; i < _normals.Length; i++)
{
_normals[i] = -Vector3.forward;
}
_mesh = new Mesh();
_mesh.vertices = _vertices;
_mesh.uv = _uvs;
_mesh.triangles = _indices;
_mesh.normals = _normals;
_mesh.bounds = new Bounds(Vector3.zero, Vector3.one * maxDist);
_filter.mesh = _mesh;
//_collider.sharedMesh = _mesh;
}
public void Update()
{
for (var i = 0; i < _data.Asteroids.Length; i++)
{
var rotation = Quaternion.Euler(0, 0, (float) (_context.Time * _data.Asteroids[i].w % 360.0));
var position = (Vector3) (Vector2)
OrbitData.Evaluate((float) frac(_context.Time / -_context.OrbitalPeriod(_data.Asteroids[i].x) *
_context.GlobalData.OrbitSpeedMultiplier + _data.Asteroids[i].y)) * (_data.Asteroids[i].x * _zoneScale);
_vertices[i * 4] = rotation * new Vector3(-_data.Asteroids[i].z,-_data.Asteroids[i].z,0) + position;
_vertices[i * 4 + 1] = rotation * new Vector3(-_data.Asteroids[i].z,_data.Asteroids[i].z,0) + position;
_vertices[i * 4 + 2] = rotation * new Vector3(_data.Asteroids[i].z,_data.Asteroids[i].z,0) + position;
_vertices[i * 4 + 3] = rotation * new Vector3(_data.Asteroids[i].z,-_data.Asteroids[i].z,0) + position;
}
_mesh.vertices = _vertices;
_collider.sharedMesh = _mesh;
}
}