2 Commits

Author SHA1 Message Date
  Laurids Jeppe ca6937c2ac (WIP) Updating to Netcode Part 1 1 year ago
  Laurids Jeppe a3744fa71f small version updates 1 year ago
26 changed files with 1067 additions and 551 deletions
Unified View
  1. +51
    -36
      Assets/GWConquest/Scripts/Battle.cs
  2. +47
    -28
      Assets/GWConquest/Scripts/BattleFlank.cs
  3. +62
    -48
      Assets/GWConquest/Scripts/District.cs
  4. +59
    -65
      Assets/GWConquest/Scripts/DistrictFactory.cs
  5. +27
    -0
      Assets/GWConquest/Scripts/DistrictUpgrade.cs
  6. +186
    -116
      Assets/GWConquest/Scripts/Formation.cs
  7. +5
    -0
      Assets/GWConquest/Scripts/GWNetworkArray.cs
  8. +11
    -0
      Assets/GWConquest/Scripts/GWNetworkArray.cs.meta
  9. +37
    -0
      Assets/GWConquest/Scripts/GWNetworkList.cs
  10. +11
    -0
      Assets/GWConquest/Scripts/GWNetworkList.cs.meta
  11. +74
    -0
      Assets/GWConquest/Scripts/GWNullable.cs
  12. +11
    -0
      Assets/GWConquest/Scripts/GWNullable.cs.meta
  13. +77
    -69
      Assets/GWConquest/Scripts/Inventory.cs
  14. +37
    -0
      Assets/GWConquest/Scripts/ItemRegistry.cs
  15. +37
    -55
      Assets/GWConquest/Scripts/Planet.cs
  16. +75
    -42
      Assets/GWConquest/Scripts/Player.cs
  17. +44
    -0
      Assets/GWConquest/Scripts/UID.cs
  18. +11
    -0
      Assets/GWConquest/Scripts/UID.cs.meta
  19. +104
    -83
      Assets/GWConquest/Scripts/Unit.cs
  20. +32
    -2
      Assets/GWConquest/Scripts/UnitClass.cs
  21. +12
    -0
      Assets/GWConquest/Scripts/Util.cs
  22. +4
    -2
      Assets/GWConquest/Textures/Art/FactionPreviewDominion.renderTexture
  23. +4
    -2
      Assets/GWConquest/Textures/Art/FactionPreviewRepublic.renderTexture
  24. +10
    -3
      Assets/GWConquest/Textures/UI/Materials/kreiswichs3.mat
  25. +1
    -0
      Packages/manifest.json
  26. +38
    -0
      Packages/packages-lock.json

+ 51
- 36
Assets/GWConquest/Scripts/Battle.cs View File

@ -3,19 +3,33 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using Photon.Bolt; using Photon.Bolt;
using Photon.Bolt.Utils; using Photon.Bolt.Utils;
using Unity.Netcode;
using Unity.Collections;
namespace GWConquest namespace GWConquest
{ {
public class Battle : GWBoltBehaviour<IBattleState>
public class Battle : NetworkBehaviour
{ {
public EntityList FormationList;
private GWNetworkList<NetworkBehaviourReference> formations;
private NetworkVariable<int> zoneID;
private NetworkVariable<FixedString128Bytes> battleName;
private GWNetworkList<NetworkBehaviourReference> flanks;
private NetworkVariable<int> flankCount;
private NetworkVariable<bool> isOver;
private NetworkVariable<int> victorID;
private NetworkVariable<float> preparingCooldown;
public IEnumerable<Formation> Formations
{
get => formations.Select(r => r.GetBehaviour<Formation>());
}
public IEnumerable<Player> AllPlayers { public IEnumerable<Player> AllPlayers {
get => FormationList.Select((f,i) => f.Entity.GetComponent<Formation>().Player).Distinct();
get => Formations.Select(f => f.Player).Distinct();
} }
public IEnumerable<Unit> AllUnits { public IEnumerable<Unit> AllUnits {
get => FormationList.SelectMany(e => e.Entity.GetComponent<Formation>().Units);
get => Formations.SelectMany(f => f.Units);
} }
private List<UnitAction> UnitActions = new List<UnitAction>(); private List<UnitAction> UnitActions = new List<UnitAction>();
@ -68,30 +82,30 @@ namespace GWConquest
} }
public int FlankCount { public int FlankCount {
get => State.FlankCount;
set => State.FlankCount = value;
get => flankCount.Value;
set => flankCount.Value = value;
} }
public void SetFlank(int index, BattleFlank flank)
public void SetFlank(ushort index, BattleFlank flank)
{ {
flank.FlankId = index; flank.FlankId = index;
State.Flanks[index] = flank?.entity;
flanks[index] = flank;
} }
public BattleFlank GetFlank(int index)
public BattleFlank GetFlank(ushort index)
{ {
return State.Flanks[index].GetComponent<BattleFlank>();
return flanks[index].GetBehaviour<BattleFlank>();
} }
public IEnumerable<BattleFlank> AllFlanks public IEnumerable<BattleFlank> AllFlanks
{ {
get => State.Flanks.Where(e => e != null).Select(e => e.GetComponent<BattleFlank>());
get => flanks.Select(r => r.GetBehaviour<BattleFlank>());
} }
public Zone Zone { public Zone Zone {
get => Zone.GetFromId(State.Zone);
get => Zone.GetFromId(zoneID.Value);
set { set {
State.Zone = Zone.GetZoneId(value);
zoneID.Value = Zone.GetZoneId(value);
transform.position = value.transform.position; transform.position = value.transform.position;
} }
} }
@ -101,29 +115,32 @@ namespace GWConquest
} }
public bool IsOver { public bool IsOver {
get => State.IsOver;
set => State.IsOver = value;
get => isOver.Value;
set => isOver.Value = value;
} }
public float PreparingCooldown { public float PreparingCooldown {
get => State.PreparingCooldown;
set => State.PreparingCooldown = value;
get => preparingCooldown.Value;
set => preparingCooldown.Value = value;
} }
public bool IsInPreparing { public bool IsInPreparing {
get => PreparingCooldown > 0; get => PreparingCooldown > 0;
} }
public override void Attached()
private void OnZoneChanged(int oldID, int newID)
{
if(newID != -1)
{
Zone.GetFromId(newID).CurrentBattle = this;
}
}
public override void OnNetworkSpawn()
{ {
FormationList = new EntityList(State, "FormationList");
zoneID.OnValueChanged += OnZoneChanged;
State.AddCallback("Zone", () => {
if(State.Zone != -1)
{
Zone.CurrentBattle = this;
}
});
base.OnNetworkSpawn();
} }
private BattleFlank InstantiateNewFlank(int maxUnitCount) private BattleFlank InstantiateNewFlank(int maxUnitCount)
@ -138,13 +155,13 @@ namespace GWConquest
public void Init() { public void Init() {
PreparingCooldown = GameManager.Instance.BattlePreparingCooldown; PreparingCooldown = GameManager.Instance.BattlePreparingCooldown;
State.FlankCount = Zone.zoneType == ZoneType.Ground ? 6 : 2;
flankCount.Value = Zone.zoneType == ZoneType.Ground ? 6 : 2;
int maxUnitPerFlank = Zone.zoneType == ZoneType.Ground ? 9 : 20; int maxUnitPerFlank = Zone.zoneType == ZoneType.Ground ? 9 : 20;
var allPlayers = AllPlayers.ToList(); var allPlayers = AllPlayers.ToList();
if(allPlayers.Count() >= 2) if(allPlayers.Count() >= 2)
{ {
for(int i = 0; i < State.FlankCount; i += 2)
for(int i = 0; i < flankCount.Value; i += 2)
{ {
var flank1 = InstantiateNewFlank(maxUnitPerFlank); var flank1 = InstantiateNewFlank(maxUnitPerFlank);
var flank2 = InstantiateNewFlank(maxUnitPerFlank); var flank2 = InstantiateNewFlank(maxUnitPerFlank);
@ -155,8 +172,8 @@ namespace GWConquest
flank1.Player = allPlayers[0]; flank1.Player = allPlayers[0];
flank2.Player = allPlayers[1]; flank2.Player = allPlayers[1];
SetFlank(i, flank1);
SetFlank(i+1, flank2);
SetFlank((ushort) i, flank1);
SetFlank((ushort) (i+1), flank2);
} }
} }
else { else {
@ -166,7 +183,7 @@ namespace GWConquest
public void AddFormation(Formation f) public void AddFormation(Formation f)
{ {
FormationList.Add(f.entity);
formations.Add(f);
f.OnAddedToBattle(this); f.OnAddedToBattle(this);
@ -175,7 +192,7 @@ namespace GWConquest
public void RemoveFormation(Formation f) public void RemoveFormation(Formation f)
{ {
FormationList.Remove(f.entity);
formations.Remove(f);
foreach(Unit u in f.Units) foreach(Unit u in f.Units)
{ {
@ -200,10 +217,8 @@ namespace GWConquest
} }
} }
public override void SimulateOwner()
public void FixedUpdate()
{ {
base.SimulateOwner();
if(IsInPreparing) if(IsInPreparing)
{ {
PreparingCooldown -= BoltNetwork.FrameDeltaTime; PreparingCooldown -= BoltNetwork.FrameDeltaTime;
@ -250,10 +265,10 @@ namespace GWConquest
var victoriousPlayer = AllPlayers.FirstOrDefault(); var victoriousPlayer = AllPlayers.FirstOrDefault();
if(victoriousPlayer != null) if(victoriousPlayer != null)
{ {
State.VictorID = victoriousPlayer.PlayerId;
victorID.Value = victoriousPlayer.PlayerId;
} }
else { else {
State.VictorID = -1;
victorID.Value = -1;
} }
foreach(Unit unit in AllUnits) foreach(Unit unit in AllUnits)


+ 47
- 28
Assets/GWConquest/Scripts/BattleFlank.cs View File

@ -2,11 +2,21 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using UnityEngine; using UnityEngine;
using Photon.Bolt; using Photon.Bolt;
using Unity.Netcode;
namespace GWConquest { namespace GWConquest {
public class BattleFlank : GWBoltBehaviour<IBattleFlankState>
public class BattleFlank : NetworkBehaviour
{ {
private NetworkVariable<NetworkBehaviourReference> battle;
private NetworkVariable<ushort> flankID;
private NetworkVariable<int> maxUnitCount;
private NetworkVariable<ushort> playerID;
private GWNetworkList<NullableNetworkBehaviourReference> units;
private NetworkVariable<NetworkBehaviourReference> opposingFlank;
private GWNetworkList<float> deathCooldowns;
public const int SlotsPerRowGround = 3; public const int SlotsPerRowGround = 3;
public const int SlotsPerRowSpace = 2; public const int SlotsPerRowSpace = 2;
@ -14,61 +24,54 @@ namespace GWConquest {
public BattleFlankUI CurrentUI; public BattleFlankUI CurrentUI;
public Battle Battle { public Battle Battle {
get => BoltEntityCache.Get<Battle>(State.Battle);
set => State.Battle = BoltEntityCache.Set(value);
get => battle.Value.GetBehaviour<Battle>();
set => battle.Value = value;
} }
public int FlankId {
get => State.FlankId;
set => state.FlankId = value;
public ushort FlankId {
get => flankID.Value;
set => flankID.Value = value;
} }
public bool IsSpace => Battle.IsSpaceBattle; public bool IsSpace => Battle.IsSpaceBattle;
public int MaxUnitCount { public int MaxUnitCount {
get => State.MaxUnitCount;
set => State.MaxUnitCount = value;
get => maxUnitCount.Value;
set => maxUnitCount.Value = value;
} }
public BattleFlank OpposingFlank { public BattleFlank OpposingFlank {
get => BoltEntityCache.Get<BattleFlank>(State.OpposingFlank);
set => State.OpposingFlank = BoltEntityCache.Set(value);
get => opposingFlank.Value.GetBehaviour<BattleFlank>();
set => opposingFlank.Value = value;
} }
public Player Player { public Player Player {
get => BoltEntityCache.Get<Player>(State.Player);
set => State.Player = BoltEntityCache.Set(value);
get => Player.GetPlayerById(playerID.Value);
set => playerID.Value = value.PlayerId;
} }
public Unit GetUnit(int index) { public Unit GetUnit(int index) {
return State.Units[index]?.GetComponent<Unit>();
return units[index].GetBehaviour<Unit>();
} }
public void SetUnit(int index, Unit unit) public void SetUnit(int index, Unit unit)
{ {
State.Units[index] = unit?.entity;
units[index] = unit;
} }
public float GetDeathCooldown(int index) public float GetDeathCooldown(int index)
{ {
return State.DeathCooldowns[index];
return deathCooldowns[index];
} }
public void SetDeathCooldown(int index, float cooldown) public void SetDeathCooldown(int index, float cooldown)
{ {
State.DeathCooldowns[index] = cooldown;
deathCooldowns[index] = cooldown;
} }
public int GetUnitIndex(Unit unit) public int GetUnitIndex(Unit unit)
{ {
for(int i = 0; i < State.MaxUnitCount; i++)
{
if(State.Units[i] == unit.entity)
{
return i;
}
}
return -1;
return units.IndexOf(unit);
} }
public int GetRowFromIndex(int index) public int GetRowFromIndex(int index)
@ -101,7 +104,7 @@ namespace GWConquest {
public bool IsBroken { public bool IsBroken {
get => State.Units.Count(e => e != null) == 0;
get => units.Count(r => r.HasValue) == 0;
} }
public void RemoveUnit(Unit unit) public void RemoveUnit(Unit unit)
@ -115,17 +118,17 @@ namespace GWConquest {
public IEnumerable<Unit> Units { public IEnumerable<Unit> Units {
get { get {
return State.Units.Where(e => e != null).Select((e,i) => e.GetComponent<Unit>());
return units.Where(r => r.HasValue).Select(r => r.GetBehaviour<Unit>());
} }
} }
public override void SimulateOwner()
public void FixedUpdate()
{ {
for(int i = 0; i < MaxUnitCount; i++) for(int i = 0; i < MaxUnitCount; i++)
{ {
if(GetDeathCooldown(i) > 0) if(GetDeathCooldown(i) > 0)
{ {
State.DeathCooldowns[i] -= BoltNetwork.FrameDeltaTime;
deathCooldowns[i] -= BoltNetwork.FrameDeltaTime;
if(GetDeathCooldown(i) <= 0) if(GetDeathCooldown(i) <= 0)
{ {
var unit = GetUnit(i); var unit = GetUnit(i);
@ -138,6 +141,22 @@ namespace GWConquest {
} }
} }
} }
public override void OnNetworkSpawn()
{
maxUnitCount.OnValueChanged += (oldVal, newVal) => {
units.Clear();
deathCooldowns.Clear();
for(int i = 0; i < newVal; i++)
{
units.Add(null);
deathCooldowns.Add(0f);
}
};
base.OnNetworkSpawn();
}
} }
} }

+ 62
- 48
Assets/GWConquest/Scripts/District.cs View File

@ -3,14 +3,30 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using Photon.Bolt; using Photon.Bolt;
using Photon.Bolt.Utils; using Photon.Bolt.Utils;
using Unity.Netcode;
using Unity.Collections;
namespace GWConquest namespace GWConquest
{ {
public class District : GWBoltBehaviour<IDistrictState>
public class District : NetworkBehaviour
{ {
public static List<District> AllDistricts = new List<District>(); public static List<District> AllDistricts = new List<District>();
public static List<DistrictConnection> AllConnections = new List<DistrictConnection>(); public static List<DistrictConnection> AllConnections = new List<DistrictConnection>();
private NetworkVariable<int> storageCapacity;
private NetworkVariable<int> controllingPlayerID;
public Inventory Inventory;
private NetworkVariable<float> itemProductionCooldown;
private NetworkVariable<int> zoneID;
private NetworkVariable<NetworkBehaviourReference> planet;
private NetworkVariable<int> level;
private NetworkVariable<DistrictType> districtType;
private NetworkVariable<FixedString128Bytes> districtName;
private NetworkVariable<Vector3> relativePosition;
private GWNetworkList<NetworkBehaviourReference> connectedDistricts;
private GWNetworkList<ushort> upgrades;
private NetworkVariable<float> captureCooldown;
public bool DistrictStatic; public bool DistrictStatic;
public Sprite DefaultSprite; public Sprite DefaultSprite;
@ -19,8 +35,6 @@ namespace GWConquest
public DistrictType DistrictType = DistrictType.Civil; public DistrictType DistrictType = DistrictType.Civil;
public int DistrictLevel; public int DistrictLevel;
public EntityList ConnectionList;
public StringList UpgradeList;
private Zone _zone; private Zone _zone;
public Zone Zone { public Zone Zone {
@ -42,7 +56,7 @@ namespace GWConquest
public Player ControllingPlayer { public Player ControllingPlayer {
get { get {
var id = State.ControllingPlayerId;
var id = controllingPlayerID.Value;
if(id < 0) if(id < 0)
{ {
return null; return null;
@ -54,66 +68,61 @@ namespace GWConquest
} }
else else
{ {
return Player.GetPlayerById(State.ControllingPlayerId);
return Player.GetPlayerById(controllingPlayerID.Value);
} }
} }
set { set {
if(value == null) if(value == null)
{ {
State.ControllingPlayerId = -1;
controllingPlayerID.Value = -1;
} }
else { else {
State.ControllingPlayerId = value.PlayerId;
controllingPlayerID.Value = value.PlayerId;
} }
} }
} }
public Inventory Inventory;
public int StorageCapacity { public int StorageCapacity {
get => State.StorageCapacity;
set => State.StorageCapacity = value;
get => storageCapacity.Value;
set => storageCapacity.Value = value;
} }
public override void Attached()
public override void OnNetworkSpawn()
{ {
ConnectionList = new EntityList(State, "ConnectedDistricts");
UpgradeList = new StringList(State, "Upgrades");
if(entity.IsOwner)
if(IsOwner)
{ {
StorageCapacity = GameManager.Instance.DefaultStorageCapacity; StorageCapacity = GameManager.Instance.DefaultStorageCapacity;
State.ControllingPlayerId = -1;
controllingPlayerID.Value = -1;
} }
Inventory = new Inventory(State, "Inventory");
Inventory.StorageCapacity = StorageCapacity; Inventory.StorageCapacity = StorageCapacity;
State.AddCallback("StorageCapacity", () => {
Inventory.StorageCapacity = StorageCapacity;
});
storageCapacity.OnValueChanged += (prev, now) => Inventory.StorageCapacity = now;
//BoltLog.Info("Setting storage capacity to {0}", StorageCapacity); //BoltLog.Info("Setting storage capacity to {0}", StorageCapacity);
AllDistricts.Add(this); AllDistricts.Add(this);
if(DistrictStatic) if(DistrictStatic)
{ {
if(entity.IsOwner)
if(IsOwner)
{ {
State.ZoneID = Zone.GetZoneId(GetComponent<Zone>());
State.DistrictType = (int) DistrictType;
State.DistrictName = DistrictName;
State.Level = DistrictLevel;
zoneID.Value = Zone.GetZoneId(GetComponent<Zone>());
districtType.Value = DistrictType;
districtName.Value = DistrictName;
level.Value = DistrictLevel;
} }
Planet = GetComponentInParent<Planet>(); Planet = GetComponentInParent<Planet>();
} }
base.OnNetworkSpawn();
} }
public void InitNonStatic() public void InitNonStatic()
{ {
Planet = BoltEntityCache.Get<Planet>(State.Planet);
Planet = planet.Value.GetBehaviour<Planet>();
if(DistrictType == DistrictType.SpaceStation) if(DistrictType == DistrictType.SpaceStation)
{ {
@ -125,22 +134,22 @@ namespace GWConquest
Util.ArrayAppend(ref Planet.groundZones, Zone); Util.ArrayAppend(ref Planet.groundZones, Zone);
} }
if(entity.IsOwner)
if(IsOwner)
{ {
State.ZoneID = Zone.GetZoneId(GetComponent<Zone>());
State.DistrictType = (int) DistrictType;
State.DistrictName = DistrictName;
State.Level = DistrictLevel;
State.RelativePosition = transform.localPosition;
zoneID.Value = Zone.GetZoneId(GetComponent<Zone>());
districtType.Value = DistrictType;
districtName.Value = DistrictName;
level.Value = DistrictLevel;
relativePosition.Value = transform.localPosition;
} }
else { else {
Zone.SetZoneId(State.ZoneID);
DistrictType = (DistrictType) State.DistrictType;
DistrictName = State.DistrictName;
DistrictLevel = state.Level;
Zone.SetZoneId(zoneID.Value);
DistrictType = districtType.Value;
DistrictName = districtName.Value.ToString();
DistrictLevel = level.Value;
transform.SetParent(Planet.transform, false); transform.SetParent(Planet.transform, false);
transform.localPosition = State.RelativePosition;
transform.localPosition = relativePosition.Value;
gameObject.name = DistrictName; gameObject.name = DistrictName;
} }
@ -149,9 +158,9 @@ namespace GWConquest
public void InitConnections() public void InitConnections()
{ {
foreach(var ent in ConnectionList)
foreach(var reference in connectedDistricts)
{ {
var otherDistrict = ent.Entity.GetComponent<District>();
var otherDistrict = reference.GetBehaviour<District>();
if(!AllConnections.Exists(c => c.district1 == this && c.district2 == otherDistrict || c.district2 == this && c.district1 == otherDistrict)) if(!AllConnections.Exists(c => c.district1 == this && c.district2 == otherDistrict || c.district2 == this && c.district1 == otherDistrict))
{ {
var go = new GameObject("District Connection"); var go = new GameObject("District Connection");
@ -252,17 +261,17 @@ namespace GWConquest
{ {
if(Zone.Formations.Where(f => f.MovementState == FormationMovementState.Idle).FirstOrDefault() != null) if(Zone.Formations.Where(f => f.MovementState == FormationMovementState.Idle).FirstOrDefault() != null)
{ {
if(State.CaptureCooldown >= GameManager.Instance.DistrictCaptureCooldown)
if(captureCooldown.Value >= GameManager.Instance.DistrictCaptureCooldown)
{ {
BoltLog.Info($"Allegiance changed in district {this} to player {player}"); BoltLog.Info($"Allegiance changed in district {this} to player {player}");
ControllingPlayer = player; ControllingPlayer = player;
} }
else { else {
if(State.CaptureCooldown == 0)
if(captureCooldown.Value == 0)
{ {
BoltLog.Info("Player {0} is the only player in district {1}, starting allegiance change...", player, this); BoltLog.Info("Player {0} is the only player in district {1}, starting allegiance change...", player, this);
} }
State.CaptureCooldown += BoltNetwork.FrameDeltaTime;
captureCooldown.Value += BoltNetwork.FrameDeltaTime;
} }
return; return;
} }
@ -270,10 +279,10 @@ namespace GWConquest
} }
} }
State.CaptureCooldown = 0;
captureCooldown.Value = 0;
} }
public override void SimulateOwner()
public void FixedUpdate()
{ {
CheckControllingChange(); CheckControllingChange();
@ -284,11 +293,11 @@ namespace GWConquest
bool producesCredits = DistrictType == DistrictType.Civil; bool producesCredits = DistrictType == DistrictType.Civil;
if(producingItem != null || producesCredits) { if(producingItem != null || producesCredits) {
if(State.ItemProductionCooldown <= 0f)
if(itemProductionCooldown.Value <= 0f)
{ {
if(producingItem != null) if(producingItem != null)
{ {
Inventory.AddItem(producingItem, 1);
Inventory.AddItem(ItemRegistry.Instance.IDFromName(producingItem), 1);
} }
if(producesCredits) if(producesCredits)
@ -296,10 +305,10 @@ namespace GWConquest
ControllingPlayer.Credits++; ControllingPlayer.Credits++;
} }
State.ItemProductionCooldown = ProducingCooldown;
itemProductionCooldown.Value = ProducingCooldown;
} }
else { else {
State.ItemProductionCooldown -= BoltNetwork.FrameDeltaTime;
itemProductionCooldown.Value -= Time.fixedDeltaTime;
} }
} }
} }
@ -319,6 +328,11 @@ namespace GWConquest
return player != null && cost.AvailableIn(accesibleItems, player); return player != null && cost.AvailableIn(accesibleItems, player);
} }
public void AddDistrictUpgrade(ushort upgradeID)
{
upgrades.Add(upgradeID);
}
} }
public enum DistrictType public enum DistrictType


+ 59
- 65
Assets/GWConquest/Scripts/DistrictFactory.cs View File

@ -3,11 +3,44 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using Photon.Bolt; using Photon.Bolt;
using Photon.Bolt.Utils; using Photon.Bolt.Utils;
using Unity.Netcode;
using System;
namespace GWConquest namespace GWConquest
{ {
public class DistrictFactory : GWBoltBehaviour<IFactoryState>
public struct ProductionQueueEntry : INetworkSerializeByMemcpy, IEquatable<ProductionQueueEntry>
{ {
public ushort UnitClass;
public float TimeProduced;
public ushort PlayerID;
public bool IsUpgrade;
public Player Player {
get => Player.GetPlayerById(PlayerID);
}
public bool Equals(ProductionQueueEntry other)
{
return UnitClass == other.UnitClass &&
TimeProduced == other.TimeProduced &&
PlayerID == other.PlayerID &&
IsUpgrade == other.IsUpgrade;
}
public ProductionQueueEntry IncreaseTime(float deltaTime)
{
return new ProductionQueueEntry() {
UnitClass = UnitClass,
PlayerID = PlayerID,
IsUpgrade = IsUpgrade,
TimeProduced = TimeProduced + deltaTime
};
}
}
public class DistrictFactory : NetworkBehaviour
{
public GWNetworkList<ProductionQueueEntry> productionQueue;
public bool StartsBroken = false; public bool StartsBroken = false;
public string[] SpecialUnits; public string[] SpecialUnits;
@ -34,52 +67,34 @@ namespace GWConquest
return classes.Union(special); return classes.Union(special);
} }
public int MaxQueueLength
{
get
{
return State.ProductionQueue.Length;
}
}
public int ProductionQueueLength public int ProductionQueueLength
{ {
get
{
for(int i = 0; i < MaxQueueLength; i++)
{
if(Util.IsStringEmpty(State.ProductionQueue[i].UnitClass))
{
return i;
}
}
return MaxQueueLength;
}
get => productionQueue.Count;
} }
public bool IsProducing public bool IsProducing
{ {
get get
{ {
return !Util.IsStringEmpty(State.ProductionQueue[0].UnitClass);
return ProductionQueueLength > 0;
} }
} }
public IBuildable GetProductionQueueEntry(int i) public IBuildable GetProductionQueueEntry(int i)
{ {
if(State.ProductionQueue[i].IsUpgrade)
if(productionQueue[i].IsUpgrade)
{ {
return DistrictUpgrade.FromName(State.ProductionQueue[i].UnitClass);
return DistrictUpgrade.FromID(productionQueue[i].UnitClass);
} }
else { else {
return UnitClass.FromName(State.ProductionQueue[i].UnitClass);
return UnitClass.FromID(productionQueue[i].UnitClass);
} }
} }
public float GetProductionTime(int i) public float GetProductionTime(int i)
{ {
return State.ProductionQueue[i].TimeProduced;
return productionQueue[i].TimeProduced;
} }
public float GetProductionPercentage(int i) public float GetProductionPercentage(int i)
@ -94,30 +109,7 @@ namespace GWConquest
public void RemoveProductionQueueEntry(int index) public void RemoveProductionQueueEntry(int index)
{ {
if(index == MaxQueueLength - 1)
{
State.ProductionQueue[index].UnitClass = null;
State.ProductionQueue[index].TimeProduced = 0f;
State.ProductionQueue[index].Player = null;
}
else
{
for (int i = index; i < MaxQueueLength - 1; i++)
{
var nextEntry = State.ProductionQueue[i + 1];
State.ProductionQueue[i].UnitClass = nextEntry.UnitClass;
State.ProductionQueue[i].TimeProduced = nextEntry.TimeProduced;
State.ProductionQueue[i].Player = nextEntry.Player;
if (Util.IsStringEmpty(nextEntry.UnitClass))
{
return;
}
}
State.ProductionQueue[MaxQueueLength - 1].UnitClass = null;
State.ProductionQueue[MaxQueueLength - 1].TimeProduced = 0f;
State.ProductionQueue[MaxQueueLength - 1].Player = null;
}
productionQueue.RemoveAt(index);
} }
public void AddProductionQueueEntry(IBuildable buildable, Player player) public void AddProductionQueueEntry(IBuildable buildable, Player player)
@ -137,18 +129,19 @@ namespace GWConquest
foreach(var cost in buildable.BuildCost.Costs) foreach(var cost in buildable.BuildCost.Costs)
{ {
var itemId = ItemRegistry.Instance.IDFromName(cost.Item);
if(cost.Item == "Credits") if(cost.Item == "Credits")
{ {
player.Credits -= cost.Amount; player.Credits -= cost.Amount;
} }
else { else {
if(districtInv.HasItem(cost.Item, cost.Amount))
if(districtInv.HasItem(itemId, cost.Amount))
{ {
districtInv.RemoveItem(cost.Item, cost.Amount);
districtInv.RemoveItem(itemId, cost.Amount);
} }
else if(!contested && planetInv.HasItem(cost.Item, cost.Amount))
else if(!contested && planetInv.HasItem(itemId, cost.Amount))
{ {
planetInv.RemoveItem(cost.Item, cost.Amount);
planetInv.RemoveItem(itemId, cost.Amount);
} }
else { else {
BoltLog.Error("Error while building {0}: Item {1} x {2} not found in inventories", buildable, cost.Item, cost.Amount); BoltLog.Error("Error while building {0}: Item {1} x {2} not found in inventories", buildable, cost.Item, cost.Amount);
@ -159,14 +152,15 @@ namespace GWConquest
} }
int length = ProductionQueueLength; int length = ProductionQueueLength;
if(length < MaxQueueLength)
{
BoltLog.Info("Adding unit {0} to production queue on district {1}", buildable, gameObject.name);
State.ProductionQueue[length].UnitClass = buildable.ShortName;
State.ProductionQueue[length].TimeProduced = 0f;
State.ProductionQueue[length].Player = player.entity;
State.ProductionQueue[length].IsUpgrade = buildable is DistrictUpgrade;
}
BoltLog.Info("Adding unit {0} to production queue on district {1}", buildable, gameObject.name);
productionQueue.Add(new ProductionQueueEntry() {
UnitClass = buildable.ID,
TimeProduced = 0f,
PlayerID = player.PlayerId,
IsUpgrade = buildable is DistrictUpgrade
});
} }
public float GetBuildTimeForBuildable(IBuildable buildable) public float GetBuildTimeForBuildable(IBuildable buildable)
@ -174,11 +168,11 @@ namespace GWConquest
return buildable.BuildTime * GameManager.Instance.TimeScale; return buildable.BuildTime * GameManager.Instance.TimeScale;
} }
public override void SimulateOwner()
public void FixedUpdate()
{ {
if(IsProducing) if(IsProducing)
{ {
State.ProductionQueue[0].TimeProduced += BoltNetwork.FrameDeltaTime;
productionQueue[0] = productionQueue[0].IncreaseTime(Time.fixedDeltaTime);
IBuildable buildable = GetProductionQueueEntry(0); IBuildable buildable = GetProductionQueueEntry(0);
if (DebugUI.FreeBuild || GetProductionTime(0) >= GetBuildTimeForBuildable(buildable)) if (DebugUI.FreeBuild || GetProductionTime(0) >= GetBuildTimeForBuildable(buildable))
{ {
@ -187,7 +181,7 @@ namespace GWConquest
Zone zone = GetComponent<Zone>(); Zone zone = GetComponent<Zone>();
if(zone != null) if(zone != null)
{ {
Unit.SpawnUnit(zone, buildable as UnitClass, State.ProductionQueue[0].Player.GetComponent<Player>());
Unit.SpawnUnit(zone, buildable as UnitClass, productionQueue[0].Player);
} }
else else
{ {
@ -196,7 +190,7 @@ namespace GWConquest
} }
else if(buildable is DistrictUpgrade) else if(buildable is DistrictUpgrade)
{ {
District.UpgradeList.Add((buildable as DistrictUpgrade).ShortName);
District.AddDistrictUpgrade(buildable.ID);
} }
RemoveProductionQueueEntry(0); RemoveProductionQueueEntry(0);
} }


+ 27
- 0
Assets/GWConquest/Scripts/DistrictUpgrade.cs View File

@ -8,16 +8,20 @@ namespace GWConquest
public class DistrictUpgrade : IBuildable public class DistrictUpgrade : IBuildable
{ {
private static DistrictUpgrade[] Upgrades;
private static Dictionary<string, DistrictUpgrade> UpgradeRegistry; private static Dictionary<string, DistrictUpgrade> UpgradeRegistry;
public static void LoadRegistry() public static void LoadRegistry()
{ {
BoltLog.Info("Loading district upgrades..."); BoltLog.Info("Loading district upgrades...");
List<DistrictUpgrade> upgradeList = new List<DistrictUpgrade>();
UpgradeRegistry = new Dictionary<string, DistrictUpgrade>(); UpgradeRegistry = new Dictionary<string, DistrictUpgrade>();
TextAsset database = Resources.Load<TextAsset>("Database/DistrictUpgrades"); TextAsset database = Resources.Load<TextAsset>("Database/DistrictUpgrades");
CSVFile csv = CSVFile.ParseCSV(database.text); CSVFile csv = CSVFile.ParseCSV(database.text);
ushort nextID = 0;
for (int i = 0; i < csv.Length; i++) for (int i = 0; i < csv.Length; i++)
{ {
try try
@ -73,6 +77,10 @@ namespace GWConquest
upgrade.LoadTexture(); upgrade.LoadTexture();
upgrade.ID = nextID;
nextID++;
upgradeList.Add(upgrade);
UpgradeRegistry.Add(upgrade.ShortName, upgrade); UpgradeRegistry.Add(upgrade.ShortName, upgrade);
} }
catch (Exception ex) catch (Exception ex)
@ -82,9 +90,27 @@ namespace GWConquest
} }
} }
Upgrades = upgradeList.ToArray();
BoltLog.Info("District upgrades loaded."); BoltLog.Info("District upgrades loaded.");
} }
public static DistrictUpgrade FromID(ushort id)
{
if(Upgrades == null)
{
LoadRegistry();
}
if(id < Upgrades.Length)
{
return Upgrades[id];
}
else {
Debug.LogWarning($"Unknown district id: {id}");
return null;
}
}
public static DistrictUpgrade FromName(string name) public static DistrictUpgrade FromName(string name)
{ {
if(UpgradeRegistry == null) if(UpgradeRegistry == null)
@ -117,6 +143,7 @@ namespace GWConquest
} }
public ushort ID {get; private set;}
public string ShortName {get; private set;} public string ShortName {get; private set;}
public string FullName {get; private set;} public string FullName {get; private set;}
public Sprite Sprite {get; private set;} public Sprite Sprite {get; private set;}


+ 186
- 116
Assets/GWConquest/Scripts/Formation.cs View File

@ -5,62 +5,101 @@ using System.Collections.Generic;
using System.Collections; using System.Collections;
using Photon.Bolt; using Photon.Bolt;
using Photon.Bolt.Utils; using Photon.Bolt.Utils;
using Unity.Netcode;
namespace GWConquest namespace GWConquest
{ {
public class Formation : GWBoltEntityListener<IFormationState>, IMovable<Zone>
public struct Transition : INetworkSerializeByMemcpy
{
public int OriginZoneID;
public int TargetZoneID;
public float TransitionLength;
public bool IsCurved;
public Zone OriginZone {
get => Zone.GetFromId(OriginZoneID);
}
public Zone TargetZone {
get => Zone.GetFromId(TargetZoneID);
}
}
public class Formation : NetworkBehaviour, IMovable<Zone>
{ {
public static List<Formation> AllFormations = new List<Formation>(); public static List<Formation> AllFormations = new List<Formation>();
private Zone lastZone;
private NetworkVariable<int> currentZoneID;
private NetworkVariable<bool> isSpace;
private NetworkVariable<Transition> currentTransition;
private NetworkVariable<NetworkBehaviourReference> player;
private GWNetworkList<NetworkBehaviourReference> units;
private GWNetworkList<int> pathQueue;
private NetworkVariable<NullableNetworkBehaviourReference> currentBattle;
private NetworkVariable<NullableNetworkBehaviourReference> heroUnit;
private GWNetworkList<NetworkBehaviourReference> subFormations;
private NetworkVariable<string> formationName;
private NetworkVariable<int> formationNumber;
private NetworkVariable<NullableNetworkBehaviourReference> movementTargetFormation;
private NetworkVariable<NullableNetworkBehaviourReference> movementOriginFormation;
private NetworkVariable<bool> isEmbarked;
private NetworkVariable<NullableNetworkBehaviourReference> parentFormation;
private NetworkVariable<float> morale;
private NetworkVariable<float> startingMorale;
private NetworkVariable<FormationMovementState> movementState;
private NetworkVariable<float> actionCooldown;
private NetworkVariable<float> actionCooldownMax;
private NetworkVariable<Vector3> fleetRestingPoint;
public Zone currentZone public Zone currentZone
{ {
get get
{ {
return Zone.GetFromId(State.CurrentZone);
return Zone.GetFromId(currentZoneID.Value);
} }
set set
{ {
State.CurrentZone = Zone.GetZoneId(value);
OnZoneChanged();
currentZoneID.Value = Zone.GetZoneId(value);
//OnZoneChanged();
} }
} }
private void OnZoneChanged()
private void OnZoneChanged(int previousValue, int newValue)
{ {
Zone newZone = Zone.GetFromId(State.CurrentZone);
if(lastZone != newZone)
if(previousValue != newValue)
{ {
if(lastZone != null)
Zone previousZone = Zone.GetFromId(previousValue);
Zone newZone = Zone.GetFromId(newValue);
if(previousZone != null)
{ {
lastZone.OnFormationDeparting(this);
previousZone.OnFormationDeparting(this);
} }
if(newZone != null) if(newZone != null)
{ {
newZone.OnFormationArrived(this); newZone.OnFormationArrived(this);
} }
BoltLog.Info("Current zone changed from {0} to {1} on formation {2}", lastZone, newZone, this);
lastZone = newZone;
BoltLog.Info("Current zone changed from {0} to {1} on formation {2}", previousZone, newZone, this);
} }
} }
public ZoneType ZoneType { public ZoneType ZoneType {
get => State.IsSpace ? ZoneType.Space : ZoneType.Ground;
set => State.IsSpace = value == ZoneType.Space;
get => isSpace.Value ? ZoneType.Space : ZoneType.Ground;
set => isSpace.Value = value == ZoneType.Space;
} }
public Player Player public Player Player
{ {
get => BoltEntityCache.Get<Player>(State.Player);
set => State.Player = BoltEntityCache.Set(value);
get => player.Value.GetBehaviour<Player>();
set => player.Value = value;
} }
public string FormationName public string FormationName
{ {
get => State.FormationName;
get => formationName.Value;
set { set {
State.FormationName = value;
formationName.Value = value;
keepFormationName = true; keepFormationName = true;
} }
} }
@ -72,30 +111,29 @@ namespace GWConquest
private Vector3 restingPosition; private Vector3 restingPosition;
public float AnimCompletion { public float AnimCompletion {
get => animDistanceCovered / State.CurrentTransition.TransitionLength;
get => animDistanceCovered / CurrentTransition.TransitionLength;
} }
public float AnimTimeLeft { public float AnimTimeLeft {
get => (State.CurrentTransition.TransitionLength - animDistanceCovered) / movementSpeed;
get => (CurrentTransition.TransitionLength - animDistanceCovered) / movementSpeed;
} }
public EntityList UnitEntities;
public EntityList SubFormationEntities;
public IEnumerable<Unit> Units {
get => units.Select(r => r.GetBehaviour<Unit>());
}
public IEnumerable<Unit> Units
{
get => UnitEntities.Select((e,i) => e.Entity.GetComponent<Unit>());
public IEnumerable<Formation> SubFormations {
get => units.Select(r => r.GetBehaviour<Formation>());
} }
public int UnitCount { public int UnitCount {
get => UnitEntities.Count;
get => units.Count;
} }
public Unit HeroUnit public Unit HeroUnit
{ {
get => BoltEntityCache.Get<Unit>(State.HeroUnit);
set => State.HeroUnit = BoltEntityCache.Set(value);
get => heroUnit.Value.GetBehaviour<Unit>();
set => heroUnit.Value = value;
} }
public IEnumerable<ItemStack> AllItems public IEnumerable<ItemStack> AllItems
@ -103,52 +141,54 @@ namespace GWConquest
get => Units.SelectMany(u => u.Inventory); get => Units.SelectMany(u => u.Inventory);
} }
public IEnumerable<Formation> SubFormations
{
get => SubFormationEntities.Select((e,i) => e.Entity.GetComponent<Formation>());
public IEnumerable<Zone> PathQueue {
get => pathQueue.Select(id => Zone.GetFromId(id));
} }
public ZoneList PathQueue;
public Formation MovementTargetFormation { public Formation MovementTargetFormation {
get => BoltEntityCache.Get<Formation>(State.MovementTargetFormation);
set => State.MovementTargetFormation = BoltEntityCache.Set(value);
get => movementTargetFormation.Value.GetBehaviour<Formation>();
set => movementTargetFormation.Value = value;
} }
public Formation MovementOriginFormation { public Formation MovementOriginFormation {
get => BoltEntityCache.Get<Formation>(State.MovementOriginFormation);
set => State.MovementOriginFormation = BoltEntityCache.Set(value);
get => movementOriginFormation.Value.GetBehaviour<Formation>();
set => movementOriginFormation.Value = value;
} }
public bool IsOnSpaceGroundTransition public bool IsOnSpaceGroundTransition
{ {
get => MovementState == FormationMovementState.Moving && Zone.GetFromId(State.CurrentTransition.OriginZone).zoneType != Zone.GetFromId(State.CurrentTransition.TargetZone).zoneType;
get => MovementState == FormationMovementState.Moving && CurrentTransition.OriginZone.zoneType != CurrentTransition.TargetZone.zoneType;
}
public Transition CurrentTransition
{
get => currentTransition.Value;
} }
public bool IsEmbarked { public bool IsEmbarked {
get => State.IsEmbarked;
set => State.IsEmbarked = value;
get => isEmbarked.Value;
set => isEmbarked.Value = value;
} }
public Formation ParentFormation { public Formation ParentFormation {
get => BoltEntityCache.Get<Formation>(State.ParentFormation);
set => State.ParentFormation = BoltEntityCache.Set(value);
get => parentFormation.Value.GetBehaviour<Formation>();
set => parentFormation.Value = value;
} }
public const float MoraleCap = 27 * 3 * 100; public const float MoraleCap = 27 * 3 * 100;
public float Morale { public float Morale {
get => State.Morale;
set => State.Morale = value;
get => morale.Value;
set => morale.Value = value;
} }
public float StartingMorale { public float StartingMorale {
get => State.StartingMorale;
set => State.StartingMorale = value;
get => startingMorale.Value;
set => startingMorale.Value = value;
} }
public FormationMovementState MovementState { public FormationMovementState MovementState {
get => (FormationMovementState) State.MovementState;
set => State.MovementState = (int) value;
get => movementState.Value;
set => movementState.Value = value;
} }
public bool IsMoving { public bool IsMoving {
@ -158,17 +198,17 @@ namespace GWConquest
} }
public float ActionCooldown { public float ActionCooldown {
get => State.ActionCooldown;
get => actionCooldown.Value;
} }
public float ActionCooldownPercent { public float ActionCooldownPercent {
get => State.ActionCooldown / State.ActionCooldownMax;
get =>actionCooldown.Value / actionCooldownMax.Value;
} }
public void SetActionCooldown(float value) public void SetActionCooldown(float value)
{ {
State.ActionCooldown = value;
State.ActionCooldownMax = value;
actionCooldown.Value = value;
actionCooldownMax.Value = value;
} }
public GameObject movingArmyPrefab; public GameObject movingArmyPrefab;
@ -180,8 +220,8 @@ namespace GWConquest
public float movementSpeed {get => GameManager.Instance.DefaultMovementSpeed;} public float movementSpeed {get => GameManager.Instance.DefaultMovementSpeed;}
public int FormationNumber { public int FormationNumber {
get => State.FormationNumber;
set => State.FormationNumber = value;
get => formationNumber.Value;
set => formationNumber.Value = value;
} }
public bool keepFormationName = false; public bool keepFormationName = false;
@ -200,9 +240,9 @@ namespace GWConquest
{ {
return z.planet; return z.planet;
} }
else if(State.CurrentTransition.OriginZone != -1)
else if(CurrentTransition.OriginZoneID != -1)
{ {
return Zone.GetFromId(State.CurrentTransition.OriginZone).planet;
return CurrentTransition.OriginZone.planet;
} }
else return null; else return null;
} }
@ -237,7 +277,7 @@ namespace GWConquest
public void StartMovingOnPath(List<Zone> path, Formation targetFormation=null) public void StartMovingOnPath(List<Zone> path, Formation targetFormation=null)
{ {
if (path.Count > 1 && entity.IsControlled && CanMove)
if (path.Count > 1 && IsOwner && CanMove)
{ {
if(!CanMoveTo(path[0], path[1])) if(!CanMoveTo(path[0], path[1]))
{ {
@ -282,14 +322,14 @@ namespace GWConquest
if(IsEmbarked) if(IsEmbarked)
{ {
if(ParentFormation != null && ParentFormation.entity.IsAttached)
if(ParentFormation != null)
{ {
MovementOriginFormation = ParentFormation; MovementOriginFormation = ParentFormation;
ParentFormation.RemoveSubFormation(this); ParentFormation.RemoveSubFormation(this);
} }
} }
PathQueue.SetEntries(path);
pathQueue.SetEntries(path.Select(z => Zone.GetZoneId(z)));
if(targetFormation != null) if(targetFormation != null)
{ {
@ -307,7 +347,7 @@ namespace GWConquest
public void MoveToZone(Zone target) public void MoveToZone(Zone target)
{ {
if(entity.IsOwner && MovementState == FormationMovementState.PreparingMovement)
if(IsOwner && MovementState == FormationMovementState.PreparingMovement)
{ {
if(!CanMoveTo(currentZone, target)) if(!CanMoveTo(currentZone, target))
{ {
@ -354,12 +394,12 @@ namespace GWConquest
BoltLog.Warn($"There is {remainingFuel} required fuel remaining after consuming everything, this should not happen!"); BoltLog.Warn($"There is {remainingFuel} required fuel remaining after consuming everything, this should not happen!");
} }
State.CurrentTransition.OriginZone = Zone.GetZoneId(currentZone);
State.CurrentTransition.TargetZone = Zone.GetZoneId(target);
bool isGroundTransition = target.zoneType == ZoneType.Ground || currentZone.zoneType == ZoneType.Ground;
//float lengthFactor = isGroundTransition ? GameManager.Instance.GroundTransitionLengthFactor : GameManager.Instance.SpaceTransitionLengthFactor;
State.CurrentTransition.TransitionLength = Zone.GetTransitionLength(currentZone, target);
State.CurrentTransition.IsCurved = isGroundTransition;
currentTransition.Value = new Transition() {
OriginZoneID = Zone.GetZoneId(currentZone),
TargetZoneID = Zone.GetZoneId(target),
TransitionLength = Zone.GetTransitionLength(currentZone, target),
IsCurved = target.zoneType == ZoneType.Ground || currentZone.zoneType == ZoneType.Ground
};
CoveredDistance = 0; CoveredDistance = 0;
currentZone = null; currentZone = null;
@ -386,15 +426,15 @@ namespace GWConquest
} }
private void OnTransitStateChanged()
private void OnTransitStateChanged(FormationMovementState previousValue, FormationMovementState newValue)
{ {
animDistanceCovered = 0; animDistanceCovered = 0;
if(MovementState == FormationMovementState.Moving)
if(newValue == FormationMovementState.Moving)
{ {
var originZone = Zone.GetFromId(State.CurrentTransition.OriginZone);
var targetZone = Zone.GetFromId(State.CurrentTransition.TargetZone);
var originZone = CurrentTransition.OriginZone;
var targetZone = CurrentTransition.TargetZone;
if (State.CurrentTransition.IsCurved)
if (CurrentTransition.IsCurved)
{ {
if (IsOnSpaceGroundTransition && IngameUI.PlanetViewEnabled) if (IsOnSpaceGroundTransition && IngameUI.PlanetViewEnabled)
{ {
@ -423,11 +463,13 @@ namespace GWConquest
} }
} }
public override void SimulateOwner()
public void FixedUpdate()
{ {
if(IsServer)
{
if(IsEmbarked) if(IsEmbarked)
{ {
if(ParentFormation != null && ParentFormation.entity.IsAttached)
if(ParentFormation != null)
{ {
if(currentZone != ParentFormation.currentZone) if(currentZone != ParentFormation.currentZone)
{ {
@ -443,19 +485,22 @@ namespace GWConquest
if(MovementState == FormationMovementState.Moving) if(MovementState == FormationMovementState.Moving)
{ {
CoveredDistance += movementSpeed * BoltNetwork.FrameDeltaTime; CoveredDistance += movementSpeed * BoltNetwork.FrameDeltaTime;
if (CoveredDistance >= State.CurrentTransition.TransitionLength)
if (CoveredDistance >= CurrentTransition.TransitionLength)
{ {
currentZone = Zone.GetFromId(State.CurrentTransition.TargetZone);
currentZone = CurrentTransition.TargetZone;
if(currentZone.zoneType == ZoneType.Space) if(currentZone.zoneType == ZoneType.Space)
{ {
State.FleetRestingPoint = currentZone.planet.GetFleetArrivalPosition(Zone.GetFromId(State.CurrentTransition.OriginZone));
fleetRestingPoint.Value = currentZone.planet.GetFleetArrivalPosition(CurrentTransition.OriginZone);
} }
State.CurrentTransition.OriginZone = -1;
State.CurrentTransition.TargetZone = -1;
State.CurrentTransition.TransitionLength = 0;
currentTransition.Value = new Transition()
{
OriginZoneID = -1,
TargetZoneID = -1,
TransitionLength = 0
};
CoveredDistance = 0; CoveredDistance = 0;
MovementState = FormationMovementState.FinishingMovement; MovementState = FormationMovementState.FinishingMovement;
@ -466,27 +511,27 @@ namespace GWConquest
if(ActionCooldown <= 0) if(ActionCooldown <= 0)
{ {
State.ActionCooldown = 0;
actionCooldown.Value = 0;
if(MovementState == FormationMovementState.PreparingMovement) if(MovementState == FormationMovementState.PreparingMovement)
{ {
Zone z = PathQueue.First(); Zone z = PathQueue.First();
PathQueue.RemoveAt(0);
pathQueue.RemoveAt(0);
MoveToZone(z); MoveToZone(z);
} }
else if(MovementState == FormationMovementState.FinishingMovement) else if(MovementState == FormationMovementState.FinishingMovement)
{ {
if(PathQueue.Count > 0)
if(pathQueue.Count > 0)
{ {
if(CanMoveTo(currentZone, PathQueue[0]))
if(CanMoveTo(currentZone, PathQueue.First()))
{ {
SetActionCooldown(GameManager.Instance.MovementStartingCooldown); SetActionCooldown(GameManager.Instance.MovementStartingCooldown);
MovementState = FormationMovementState.PreparingMovement; MovementState = FormationMovementState.PreparingMovement;
} }
else else
{ {
BoltLog.Info($"Formation {this} has not enough fuel for transition {currentZone} -> {PathQueue[0]}");
PathQueue.Clear();
BoltLog.Info($"Formation {this} has not enough fuel for transition {currentZone} -> {PathQueue.First()}");
pathQueue.Clear();
MovementState = FormationMovementState.Idle; MovementState = FormationMovementState.Idle;
} }
@ -495,7 +540,7 @@ namespace GWConquest
{ {
if(MovementTargetFormation != null) if(MovementTargetFormation != null)
{ {
if(MovementTargetFormation.entity.IsAttached && MovementTargetFormation.currentZone == currentZone)
if(MovementTargetFormation.HasNetworkObject && MovementTargetFormation.currentZone == currentZone)
{ {
MovementTargetFormation.AddSubFormation(this); MovementTargetFormation.AddSubFormation(this);
} }
@ -511,7 +556,8 @@ namespace GWConquest
} }
} }
else { else {
State.ActionCooldown -= BoltNetwork.FrameDeltaTime;
actionCooldown.Value -= Time.fixedDeltaTime;
}
} }
} }
@ -536,7 +582,7 @@ namespace GWConquest
private void Update() private void Update()
{ {
if (entity.IsAttached)
if (HasNetworkObject)
{ {
if (GameManager.EntitiesLoaded) if (GameManager.EntitiesLoaded)
{ {
@ -556,13 +602,13 @@ namespace GWConquest
if (MovementState == FormationMovementState.Moving) if (MovementState == FormationMovementState.Moving)
{ {
animDistanceCovered += movementSpeed * Time.deltaTime; animDistanceCovered += movementSpeed * Time.deltaTime;
Zone originZone = Zone.GetFromId(State.CurrentTransition.OriginZone);
Zone targetZone = Zone.GetFromId(State.CurrentTransition.TargetZone);
Zone originZone = CurrentTransition.OriginZone;
Zone targetZone = CurrentTransition.TargetZone;
Vector3 originPos = originZone.transform.position; Vector3 originPos = originZone.transform.position;
Vector3 targetPos = targetZone.transform.position; Vector3 targetPos = targetZone.transform.position;
if (!State.CurrentTransition.IsCurved)
if (!CurrentTransition.IsCurved)
{ {
originPos += originZone.planet.GetFleetArrivalPosition(targetZone) * originZone.planet.GetCurrentCircleRadius(); originPos += originZone.planet.GetFleetArrivalPosition(targetZone) * originZone.planet.GetCurrentCircleRadius();
targetPos += targetZone.planet.GetFleetArrivalPosition(originZone) * targetZone.planet.GetCurrentCircleRadius(); targetPos += targetZone.planet.GetFleetArrivalPosition(originZone) * targetZone.planet.GetCurrentCircleRadius();
@ -588,7 +634,7 @@ namespace GWConquest
//{ //{
newPos = Vector3.Lerp(originPos, newPos = Vector3.Lerp(originPos,
targetPos, targetPos,
animDistanceCovered / State.CurrentTransition.TransitionLength);
animDistanceCovered / CurrentTransition.TransitionLength);
newRot = Quaternion.LookRotation(newPos - oldPos, Vector3.up); newRot = Quaternion.LookRotation(newPos - oldPos, Vector3.up);
//} //}
@ -684,43 +730,41 @@ namespace GWConquest
var planet = currentZone.planet; var planet = currentZone.planet;
float currentCircleRadius = planet.GetCurrentCircleRadius(); float currentCircleRadius = planet.GetCurrentCircleRadius();
return planet.transform.position + State.FleetRestingPoint * 0.5f * currentCircleRadius;
return planet.transform.position + fleetRestingPoint.Value * 0.5f * currentCircleRadius;
} }
public override void Attached()
public override void OnNetworkSpawn()
{ {
BoltLog.Info("Formation attached: {0}", this); BoltLog.Info("Formation attached: {0}", this);
UnitEntities = new EntityList(State, "Units");
SubFormationEntities = new EntityList(State, "SubFormations");
FormationInventory = new CombinedInventory(() => Units.Select(u => u.Inventory)); FormationInventory = new CombinedInventory(() => Units.Select(u => u.Inventory));
PathQueue = new ZoneList(State, "PathQueue");
AllFormations.Add(this); AllFormations.Add(this);
if(entity.IsOwner)
if(IsOwner)
{ {
State.CurrentZone = -1;
currentZoneID.Value = -1;
MovementState = FormationMovementState.Idle; MovementState = FormationMovementState.Idle;
CoveredDistance = 0; CoveredDistance = 0;
FormationNumber = UnityEngine.Random.Range(1, 100); FormationNumber = UnityEngine.Random.Range(1, 100);
} }
State.AddCallback("MovementState", OnTransitStateChanged);
State.AddCallback("CurrentZone", OnZoneChanged);
movementState.OnValueChanged += OnTransitStateChanged;
currentZoneID.OnValueChanged += OnZoneChanged;
base.OnNetworkSpawn();
} }
public float GetFormationStrength() public float GetFormationStrength()
{ {
if(entity.IsAttached)
if(HasNetworkObject)
{ {
return UnitEntities.Sum(unit => {
if(unit.Entity != null && unit.Entity.IsAttached)
return Units.Sum(unit => {
if(unit != null && unit.HasNetworkObject)
{ {
return unit.Entity.GetComponent<Unit>().Class.UnitStrength;
return unit.Class.UnitStrength;
} }
else { else {
return 0f; return 0f;
@ -740,7 +784,7 @@ namespace GWConquest
{ {
currentZone.OnFormationChanged(this); currentZone.OnFormationChanged(this);
} }
if(entity.IsOwner)
if(IsOwner)
{ {
if(!keepFormationName) if(!keepFormationName)
{ {
@ -754,7 +798,7 @@ namespace GWConquest
public void OnUnitRemoved(Unit unit) public void OnUnitRemoved(Unit unit)
{ {
OnUnitsChanged?.Invoke(); OnUnitsChanged?.Invoke();
if(entity.IsOwner)
if(IsOwner)
{ {
if(!keepFormationName) if(!keepFormationName)
{ {
@ -765,14 +809,14 @@ namespace GWConquest
public void AddSubFormation(Formation f) public void AddSubFormation(Formation f)
{ {
SubFormationEntities.Add(f.entity);
subFormations.Add(f);
f.ParentFormation = this; f.ParentFormation = this;
f.IsEmbarked = true; f.IsEmbarked = true;
} }
public void RemoveSubFormation(Formation f) public void RemoveSubFormation(Formation f)
{ {
SubFormationEntities.Remove(f.entity);
subFormations.Remove(f);
f.ParentFormation = null; f.ParentFormation = null;
f.IsEmbarked = false; f.IsEmbarked = false;
} }
@ -893,7 +937,7 @@ namespace GWConquest
} }
} }
State.FormationName = name;
formationName.Value = name;
} }
public override string ToString() public override string ToString()
@ -957,7 +1001,7 @@ namespace GWConquest
foreach(Unit u in Units) foreach(Unit u in Units)
{ {
u.BattleState = isArriving ? BattleUnitState.Arriving : BattleUnitState.InReserve; u.BattleState = isArriving ? BattleUnitState.Arriving : BattleUnitState.InReserve;
u.state.ActionCooldown = 0;
u.ResetActionCooldown();
if(!battle.IsSpaceBattle && !u.Class.IsHero) if(!battle.IsSpaceBattle && !u.Class.IsHero)
{ {
@ -988,12 +1032,12 @@ namespace GWConquest
public void RemoveDeadUnits() public void RemoveDeadUnits()
{ {
for(int i = UnitEntities.Count-1; i >= 0; i--)
for(int i = units.Count-1; i >= 0; i--)
{ {
var unit = UnitEntities[i].Entity.GetComponent<Unit>();
var unit = units[i].GetBehaviour<Unit>();
if(unit.IsDead) if(unit.IsDead)
{ {
UnitEntities.RemoveAt(i);
units.RemoveAt(i);
OnUnitRemoved(unit); OnUnitRemoved(unit);
BoltNetwork.Destroy(unit.gameObject); BoltNetwork.Destroy(unit.gameObject);
@ -1002,7 +1046,33 @@ namespace GWConquest
} }
} }
public void AddUnit(Unit unit)
{
units.Add(unit);
}
public static Formation SpawnFormation(Zone zone, Player player)
{
BoltEntity formationEntity = BoltNetwork.Instantiate(BoltPrefabs.Formation);
player.AssignControl(formationEntity);
Formation playerFormation = formationEntity.GetComponent<Formation>();
playerFormation.Initialize(zone, player);
return playerFormation;
}
public void Initialize(Zone zone, Player player)
{
gameObject.name = "Formation_" + NetworkObjectId.ToString();
Player = player;
currentZone = zone;
ZoneType = zone.zoneType;
if(ZoneType == ZoneType.Space)
{
Vector3 startPos = zone.planet.GetFleetRestingPosition();
fleetRestingPoint.Value = startPos;
}
}
} }


+ 5
- 0
Assets/GWConquest/Scripts/GWNetworkArray.cs View File

@ -0,0 +1,5 @@
using Unity.Netcode;
namespace GWConquest {
}

+ 11
- 0
Assets/GWConquest/Scripts/GWNetworkArray.cs.meta View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5893ec9dc0d5802479ca61e4b13ac64f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 37
- 0
Assets/GWConquest/Scripts/GWNetworkList.cs View File

@ -0,0 +1,37 @@
using Unity.Netcode;
using System.Collections;
using System.Collections.Generic;
using System;
namespace GWConquest
{
public class GWNetworkList<T> : NetworkList<T>, IList<T> where T : unmanaged, IEquatable<T>
{
public void CopyTo(T[] array, int arrayIndex)
{
for(int i = 0; i < Count; i++)
{
array[i+arrayIndex] = this[i];
}
}
public bool IsReadOnly {
get => false;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void SetEntries(IEnumerable<T> values)
{
Clear();
foreach(T val in values)
{
Add(val);
}
}
}
}

+ 11
- 0
Assets/GWConquest/Scripts/GWNetworkList.cs.meta View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4288849507c89dc46a142bbce180f2a5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 74
- 0
Assets/GWConquest/Scripts/GWNullable.cs View File

@ -0,0 +1,74 @@
using UnityEngine;
using Unity.Netcode;
using System;
namespace GWConquest {
public struct NullableNetworkBehaviourReference : INetworkSerializable, IEquatable<NullableNetworkBehaviourReference>
{
private NetworkBehaviourReference reference;
private bool hasValue;
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
serializer.SerializeValue(ref hasValue);
if(hasValue)
{
serializer.SerializeValue(ref reference);
}
}
public bool HasValue => hasValue;
public NetworkBehaviour Behaviour
{
get {
if(hasValue)
{
if(reference.TryGet(out NetworkBehaviour beh))
{
return beh;
}
else {
Debug.LogWarning($"Could not get network behaviour reference {reference}");
return null;
}
}
else return null;
}
}
public T GetBehaviour<T>() where T : NetworkBehaviour
{
return Behaviour as T;
}
public static implicit operator NullableNetworkBehaviourReference(NetworkBehaviour beh)
{
if(beh != null)
{
return new NullableNetworkBehaviourReference() { hasValue = true, reference = beh };
}
else {
return new NullableNetworkBehaviourReference() { hasValue = false };
}
}
public static implicit operator NetworkBehaviour(NullableNetworkBehaviourReference reference)
=> reference.Behaviour;
public bool Equals(NullableNetworkBehaviourReference other)
{
if(hasValue != other.hasValue)
return false;
if(hasValue)
{
return reference.Equals(other.reference);
}
else
{
return true;
}
}
}
}

+ 11
- 0
Assets/GWConquest/Scripts/GWNullable.cs.meta View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1420b6fa4f0378740b9eea39c2f80233
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 77
- 69
Assets/GWConquest/Scripts/Inventory.cs View File

@ -5,23 +5,24 @@ using System;
using System.Linq; using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using Unity.Netcode;
namespace GWConquest namespace GWConquest
{ {
[System.Serializable] [System.Serializable]
public struct ItemStack : IIconObject, IProtocolToken
public struct ItemStack : IIconObject, INetworkSerializable, IEquatable<ItemStack>
{ {
public static int GetMaxStackSize(string item) {
public static int GetMaxStackSize(ushort item) {
return GameManager.Instance.MaxStackSize; return GameManager.Instance.MaxStackSize;
} }
public bool IsUnit; public bool IsUnit;
public string ItemName;
public NetworkId UnitId;
public ushort ItemName;
public NetworkBehaviourReference UnitReference;
public Unit Unit public Unit Unit
{ {
get => BoltNetwork.FindEntity(UnitId)?.GetComponent<Unit>();
get => UnitReference.GetBehaviour<Unit>();
} }
public bool Stackable; public bool Stackable;
public int Amount; public int Amount;
@ -71,7 +72,23 @@ namespace GWConquest
} }
return new ItemStack { return new ItemStack {
IsUnit = false, IsUnit = false,
ItemName = itemName,
ItemName = ItemRegistry.Instance.IDFromName(itemName),
Stackable = item.Stackable,
Amount = amount
};
}
public static ItemStack FromItem(ushort itemID, int amount=1)
{
var item = ItemRegistry.Instance.GetEntry(itemID);
if(!item.Stackable && amount > 1)
{
BoltLog.Warn("Item {0} is not stackable to amount {1}", itemID, amount);
amount = 1;
}
return new ItemStack {
IsUnit = false,
ItemName = itemID,
Stackable = item.Stackable, Stackable = item.Stackable,
Amount = amount Amount = amount
}; };
@ -81,7 +98,7 @@ namespace GWConquest
{ {
return new ItemStack { return new ItemStack {
IsUnit = true, IsUnit = true,
UnitId = unit.entity.NetworkId,
UnitReference = unit,
Stackable = false, Stackable = false,
Amount = amount Amount = amount
}; };
@ -90,97 +107,88 @@ namespace GWConquest
public ItemStack Copy() { public ItemStack Copy() {
return new ItemStack() { return new ItemStack() {
IsUnit = IsUnit, IsUnit = IsUnit,
UnitId = UnitId,
UnitReference = UnitReference,
ItemName = ItemName, ItemName = ItemName,
Stackable = Stackable, Stackable = Stackable,
Amount = Amount Amount = Amount
}; };
} }
public static bool ItemsEqual(ItemStack stack1, ItemStack stack2)
public bool Equals(ItemStack other)
{ {
return stack1.IsUnit == stack2.IsUnit
&& (stack1.IsUnit ?
(stack1.Unit == stack2.Unit) :
(stack1.ItemName == stack2.ItemName));
return IsUnit == other.IsUnit
&& (IsUnit ?
(Unit == other.Unit) :
(ItemName.Equals(other.ItemName)));
} }
public void Write(UdpPacket packet)
public static bool ItemsEqual(ItemStack stack1, ItemStack stack2)
{ {
packet.WriteBool(IsUnit);
if(IsUnit)
{
packet.WriteULong(UnitId.PackedValue);
}
else {
packet.WriteString(ItemName);
}
packet.WriteBool(Stackable);
packet.WriteInt(Amount);
return stack1.Equals(stack2);
} }
public void Read(UdpPacket packet)
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{ {
IsUnit = packet.ReadBool();
if(IsUnit)
if (serializer.IsReader)
{ {
UnitId = new NetworkId(packet.ReadULong());
var reader = serializer.GetFastBufferReader();
reader.ReadValueSafe(out IsUnit);
if(IsUnit)
{
serializer.SerializeValue(ref UnitReference);
}
else {
reader.ReadValueSafe(out ItemName);
}
reader.ReadValueSafe(out Stackable);
reader.ReadValueSafe(out Amount);
}
else
{
var writer = serializer.GetFastBufferWriter();
writer.WriteValueSafe(IsUnit);
if(IsUnit)
{
serializer.SerializeValue(ref UnitReference);
}
else {
writer.WriteValueSafe(ItemName);
}
writer.WriteValueSafe(Stackable);
writer.WriteValueSafe(Amount);
} }
else {
ItemName = packet.ReadString();
}
Stackable = packet.ReadBool();
Amount = packet.ReadInt();
}
}
public class InventoryToken : BoltListToken<ItemStack>
{
public override void WriteEntry(UdpPacket packet, ItemStack item)
{
item.Write(packet);
} }
public override ItemStack ReadEntry(UdpPacket packet)
{
var item = new ItemStack();
item.Read(packet);
return item;
}
} }
public interface IInventory public interface IInventory
{ {
int GetItemAmount(string item);
int GetItemAmount(ushort item);
bool AddItem(string item, int amount);
bool AddItem(ushort item, int amount);
int GetRemainingSpace(string item);
int GetRemainingSpace(ushort item);
bool RemoveItem(string item, int amount);
bool RemoveItem(ushort item, int amount);
} }
public class Inventory : BoltList<ItemStack, InventoryToken>, IInventory
public class Inventory : GWNetworkList<ItemStack>, IInventory
{ {
// Question: Can there be more then one half-full stack for an item type?? // Question: Can there be more then one half-full stack for an item type??
public Inventory(IState _state, string _propertyName) : base(_state, _propertyName) { }
public int StorageCapacity = int.MaxValue; public int StorageCapacity = int.MaxValue;
public int GetItemAmount(string item)
public int GetItemAmount(ushort item)
{ {
return this.Where(stack => (!stack.IsUnit && stack.ItemName == item)).Sum(stack => stack.Amount); return this.Where(stack => (!stack.IsUnit && stack.ItemName == item)).Sum(stack => stack.Amount);
} }
public int GetItemStackAmount(string item)
public int GetItemStackAmount(ushort item)
{ {
return this.Count(stack => !stack.IsUnit && stack.ItemName == item); return this.Count(stack => !stack.IsUnit && stack.ItemName == item);
} }
public bool AddItem(string item, int amount)
public bool AddItem(ushort item, int amount)
{ {
if(GetRemainingSpace(item) >= amount) { if(GetRemainingSpace(item) >= amount) {
int maxStackSize = ItemStack.GetMaxStackSize(item); int maxStackSize = ItemStack.GetMaxStackSize(item);
@ -219,7 +227,7 @@ namespace GWConquest
} }
} }
public int GetRemainingSpace(string item)
public int GetRemainingSpace(ushort item)
{ {
int maxStackSize = ItemStack.GetMaxStackSize(item); int maxStackSize = ItemStack.GetMaxStackSize(item);
int emptyStacks = StorageCapacity - Count; int emptyStacks = StorageCapacity - Count;
@ -231,7 +239,7 @@ namespace GWConquest
return emptyStacks * maxStackSize + restAmount; return emptyStacks * maxStackSize + restAmount;
} }
public bool RemoveItem(string item, int amount)
public bool RemoveItem(ushort item, int amount)
{ {
int currentAmount = GetItemAmount(item); int currentAmount = GetItemAmount(item);
@ -258,7 +266,7 @@ namespace GWConquest
} }
} }
private int RemoveFromStacks(string item, int amount, bool partialStacksOnly)
private int RemoveFromStacks(ushort item, int amount, bool partialStacksOnly)
{ {
int maxStackSize = ItemStack.GetMaxStackSize(item); int maxStackSize = ItemStack.GetMaxStackSize(item);
int amountToRemove = amount; int amountToRemove = amount;
@ -291,7 +299,7 @@ namespace GWConquest
{ {
//TODO Unit Items //TODO Unit Items
Dictionary<string, ItemStack> dict = new Dictionary<string, ItemStack>();
Dictionary<ushort, ItemStack> dict = new Dictionary<ushort, ItemStack>();
foreach(var stack in items) foreach(var stack in items)
{ {
@ -323,18 +331,18 @@ namespace GWConquest
InventoryFunc = _inventoryFunc; InventoryFunc = _inventoryFunc;
} }
public int GetItemAmount(string item)
public int GetItemAmount(ushort item)
{ {
return InventoryFunc().Sum(inv => inv.GetItemAmount(item)); return InventoryFunc().Sum(inv => inv.GetItemAmount(item));
} }
public int GetRemainingSpace(string item)
public int GetRemainingSpace(ushort item)
{ {
return InventoryFunc().Sum(inv => inv.GetRemainingSpace(item)); return InventoryFunc().Sum(inv => inv.GetRemainingSpace(item));
} }
// TODO organize items for maximum space // TODO organize items for maximum space
public bool AddItem(string item, int amount)
public bool AddItem(ushort item, int amount)
{ {
if(GetRemainingSpace(item) >= amount) if(GetRemainingSpace(item) >= amount)
{ {
@ -362,7 +370,7 @@ namespace GWConquest
} }
} }
public bool RemoveItem(string item, int amount)
public bool RemoveItem(ushort item, int amount)
{ {
if(GetItemAmount(item) >= amount) if(GetItemAmount(item) >= amount)
{ {
@ -394,12 +402,12 @@ namespace GWConquest
public static class InventoryExtensions public static class InventoryExtensions
{ {
public static bool HasItem(this IInventory inventory, string item, int amount)
public static bool HasItem(this IInventory inventory, ushort item, int amount)
{ {
return inventory.GetItemAmount(item) >= amount; return inventory.GetItemAmount(item) >= amount;
} }
public static bool DoesItemFit(this IInventory inventory, string item, int amount)
public static bool DoesItemFit(this IInventory inventory, ushort item, int amount)
{ {
return inventory.GetRemainingSpace(item) >= amount; return inventory.GetRemainingSpace(item) >= amount;
} }


+ 37
- 0
Assets/GWConquest/Scripts/ItemRegistry.cs View File

@ -1,10 +1,17 @@
using UnityEngine; using UnityEngine;
using System.Collections.Generic; using System.Collections.Generic;
using Unity.Netcode;
using System;
namespace GWConquest namespace GWConquest
{ {
public class ItemRegistry : MonoBehaviour public class ItemRegistry : MonoBehaviour
{ {
public static ushort kFuel;
public static ushort kSupplies;
public static ushort kFood;
public static ushort kRecruits;
private static ItemRegistry _instance; private static ItemRegistry _instance;
public static ItemRegistry Instance { public static ItemRegistry Instance {
get { get {
@ -38,6 +45,11 @@ namespace GWConquest
{ {
itemMap.Add(e.Name, e); itemMap.Add(e.Name, e);
} }
kFuel = IDFromName("Fuel");
kSupplies = IDFromName("Supplies");
kFood = IDFromName("Food");
kRecruits = IDFromName("Recruits");
} }
public ItemEntry GetEntry(string itemName) public ItemEntry GetEntry(string itemName)
@ -47,6 +59,31 @@ namespace GWConquest
} }
else return null; else return null;
} }
public ItemEntry GetEntry(ushort id)
{
if(id >= Entries.Length)
{
Debug.LogWarning($"Unknown item id: {id}");
return null;
}
else {
return Entries[id];
}
}
public ushort IDFromName(string ItemName)
{
for(ushort i = 0; i < Entries.Length; i++)
{
if(Entries[i].Name == ItemName)
{
return i;
}
}
Debug.LogError($"Unknown item name: {ItemName}");
return 0;
}
} }
} }


+ 37
- 55
Assets/GWConquest/Scripts/Planet.cs View File

@ -4,11 +4,13 @@ using System.Linq;
using UnityEngine; using UnityEngine;
using Photon.Bolt; using Photon.Bolt;
using Photon.Bolt.Utils; using Photon.Bolt.Utils;
using Unity.Netcode;
using Unity.Collections;
namespace GWConquest namespace GWConquest
{ {
[ExecuteInEditMode] [ExecuteInEditMode]
public class Planet : GWBoltBehaviour<IPlanetState>
public class Planet : NetworkBehaviour
{ {
private static Planet[] _allPlanets; private static Planet[] _allPlanets;
public static Planet[] AllPlanets public static Planet[] AllPlanets
@ -32,6 +34,14 @@ namespace GWConquest
_allPlanets = null; _allPlanets = null;
} }
private NetworkVariable<FixedString128Bytes> planetNameVar;
private NetworkVariable<int> spaceZoneID;
private NetworkVariable<int> attackZoneID;
private GWNetworkList<NetworkBehaviourReference> connectedPlanets;
private NetworkVariable<ushort> planetPrefab;
private NetworkVariable<Quaternion> prefabRotation;
private NetworkVariable<float> prefabScale;
public GameObject textPrefab; public GameObject textPrefab;
public bool PlanetStatic = false; public bool PlanetStatic = false;
@ -43,7 +53,7 @@ namespace GWConquest
public string planetName; public string planetName;
public string PlanetName { public string PlanetName {
get => State.PlanetName;
get => planetNameVar.ToString();
} }
public string BackgroundMusic; public string BackgroundMusic;
@ -103,8 +113,6 @@ namespace GWConquest
[HideInInspector] [HideInInspector]
public List<PlanetConnection> connections = new List<PlanetConnection>(); public List<PlanetConnection> connections = new List<PlanetConnection>();
public EntityList ConnectedPlanetsList;
public PathfindingGraph<Zone> pathfindingGraph; public PathfindingGraph<Zone> pathfindingGraph;
public IInventory PlanetInventory; public IInventory PlanetInventory;
@ -136,9 +144,12 @@ namespace GWConquest
return connections.Exists(conn => (conn.planet1 == planet || conn.planet2 == planet)); return connections.Exists(conn => (conn.planet1 == planet || conn.planet2 == planet));
} }
public override void Attached()
public IEnumerable<Planet> ConnectedPlanets {
get => connectedPlanets.Select(r => r.GetBehaviour<Planet>());
}
public override void OnNetworkSpawn()
{ {
ConnectedPlanetsList = new EntityList(State, "ConnectedPlanets");
/*if(BoltNetwork.IsClient) /*if(BoltNetwork.IsClient)
{ {
@ -179,11 +190,11 @@ namespace GWConquest
zone.zoneType = ZoneType.Space; zone.zoneType = ZoneType.Space;
} }
if(entity.IsOwner)
if(IsOwner)
{ {
State.SpaceZoneID = Zone.GetZoneId(GetMainZone(ZoneType.Space));
State.AttackZoneID = Zone.GetZoneId(GetAttackZones(ZoneType.Ground)[0]);
State.PlanetName = planetName;
spaceZoneID.Value = Zone.GetZoneId(GetMainZone(ZoneType.Space));
attackZoneID.Value = Zone.GetZoneId(GetAttackZones(ZoneType.Ground)[0]);
planetNameVar.Value = planetName;
} }
PlanetPlacement.Instance.SpawnAsteroids(this); PlanetPlacement.Instance.SpawnAsteroids(this);
@ -205,15 +216,15 @@ namespace GWConquest
zone.zoneType = ZoneType.Space; zone.zoneType = ZoneType.Space;
} }
if(entity.IsOwner)
if(IsOwner)
{ {
State.SpaceZoneID = Zone.GetZoneId(GetMainZone(ZoneType.Space));
State.AttackZoneID = Zone.GetZoneId(GetAttackZones(ZoneType.Ground)[0]);
spaceZoneID.Value = Zone.GetZoneId(GetMainZone(ZoneType.Space));
attackZoneID.Value = Zone.GetZoneId(GetAttackZones(ZoneType.Ground)[0]);
} }
else { else {
planetName = State.PlanetName;
GetMainZone(ZoneType.Space).SetZoneId(State.SpaceZoneID);
GetAttackZones(ZoneType.Ground)[0].SetZoneId(State.AttackZoneID);
planetName = PlanetName;
GetMainZone(ZoneType.Space).SetZoneId(spaceZoneID.Value);
GetAttackZones(ZoneType.Ground)[0].SetZoneId(attackZoneID.Value);
PlanetPlacement.Instance.InitPlanetPrefab(this); PlanetPlacement.Instance.InitPlanetPrefab(this);
} }
@ -225,11 +236,11 @@ namespace GWConquest
{ {
if (conn.planet1 == this) if (conn.planet1 == this)
{ {
ConnectedPlanetsList.Add(conn.planet2.entity);
connectedPlanets.Add(conn.planet2);
} }
else if (conn.planet2 == this) else if (conn.planet2 == this)
{ {
ConnectedPlanetsList.Add(conn.planet1.entity);
connectedPlanets.Add(conn.planet1);
} }
} }
} }
@ -238,9 +249,9 @@ namespace GWConquest
{ {
var pp = PlanetPlacement.Instance; var pp = PlanetPlacement.Instance;
foreach(var entity in ConnectedPlanetsList)
foreach(var beh in connectedPlanets)
{ {
var otherPlanet = entity.Entity.GetComponent<Planet>();
var otherPlanet = beh.GetBehaviour<Planet>();
if(!IsConnectedTo(otherPlanet)) if(!IsConnectedTo(otherPlanet))
{ {
pp.SpawnPlanetConnection(this, otherPlanet); pp.SpawnPlanetConnection(this, otherPlanet);
@ -250,7 +261,7 @@ namespace GWConquest
public void FinishSetup() public void FinishSetup()
{ {
if(entity.IsOwner)
if(IsOwner)
{ {
UpdateConnectionsServer(); UpdateConnectionsServer();
} }
@ -327,9 +338,9 @@ namespace GWConquest
var currentPlayers = GetAllFormations(ZoneType.Space).Select(f => f.Player).Distinct(); var currentPlayers = GetAllFormations(ZoneType.Space).Select(f => f.Player).Distinct();
foreach(Player player in currentPlayers) foreach(Player player in currentPlayers)
{ {
if(!player.Faction.IsAI && GetVisibilityStatus(player) != PlanetVisibilityStatus.Visible)
if(!player.Faction.IsAI && player.GetPlanetVisibility(this) != PlanetVisibilityStatus.Visible)
{ {
SetPlanetVisible(player);
player.SetPlanetVisible(this);
} }
} }
} }
@ -356,7 +367,7 @@ namespace GWConquest
if(mainZone != null) if(mainZone != null)
{ {
var district = mainZone.GetComponent<District>(); var district = mainZone.GetComponent<District>();
if(district != null && district.entity.IsAttached)
if(district != null && district.IsSpawned)
{ {
return district.ControllingPlayer; return district.ControllingPlayer;
} }
@ -381,26 +392,12 @@ namespace GWConquest
} }
} }
public PlanetVisibilityStatus GetVisibilityStatus(Player player)
{
if(player.VisiblePlanetsList.FirstOrDefault(e => e.Entity == entity) != null)
{
return PlanetVisibilityStatus.Visible;
}
else if(player.KnownPlanetsList.FirstOrDefault(e => e.Entity == entity) != null)
{
return PlanetVisibilityStatus.Known;
}
else {
return PlanetVisibilityStatus.Hidden;
}
}
public static void UpdateVisibilityStatus() public static void UpdateVisibilityStatus()
{ {
foreach(var planet in Planet.AllPlanets) foreach(var planet in Planet.AllPlanets)
{ {
var status = planet.GetVisibilityStatus(Player.CurrentPlayer);
var status = Player.CurrentPlayer.GetPlanetVisibility(planet);
if(status != planet.VisibilityStatus) if(status != planet.VisibilityStatus)
{ {
planet.VisibilityStatus = status; planet.VisibilityStatus = status;
@ -433,22 +430,7 @@ namespace GWConquest
} }
} }
public void SetPlanetVisible(Player player)
{
if(GetVisibilityStatus(player) != PlanetVisibilityStatus.Visible)
{
player.VisiblePlanetsList.Add(entity);
foreach(var cpe in ConnectedPlanetsList)
{
var otherPlanet = cpe.Entity.GetComponent<Planet>();
if(otherPlanet.GetVisibilityStatus(player) == PlanetVisibilityStatus.Hidden)
{
player.KnownPlanetsList.Add(otherPlanet.entity);
}
}
}
}
public void UpdatePlanetRenderer() public void UpdatePlanetRenderer()
{ {


+ 75
- 42
Assets/GWConquest/Scripts/Player.cs View File

@ -3,11 +3,21 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using Photon.Bolt; using Photon.Bolt;
using Photon.Bolt.Utils; using Photon.Bolt.Utils;
using Unity.Netcode;
using Unity.Collections;
namespace GWConquest namespace GWConquest
{ {
public class Player : GWBoltBehaviour<IPlayerState>
public class Player : NetworkBehaviour
{ {
private NetworkVariable<ushort> playerID;
private NetworkVariable<FixedString512Bytes> playerName;
private NetworkVariable<ushort> factionIndex;
private NetworkVariable<bool> isAI;
private NetworkVariable<int> credits;
private GWNetworkList<NetworkBehaviourReference> knownPlanetsList;
private GWNetworkList<NetworkBehaviourReference> visiblePlanetsList;
public static List<Player> PlayerList = new List<Player>(); public static List<Player> PlayerList = new List<Player>();
public static Player CurrentPlayer; public static Player CurrentPlayer;
@ -19,7 +29,11 @@ namespace GWConquest
public Faction Faction public Faction Faction
{ {
get => GameManager.Instance.Factions[State.FactionIndex];
get => GameManager.Instance.Factions[factionIndex.Value];
}
public bool IsAI {
get => isAI.Value;
} }
public Color Color public Color Color
@ -29,83 +43,71 @@ namespace GWConquest
public int Credits public int Credits
{ {
get => State.Credits;
set => State.Credits = value;
get => credits.Value;
set => credits.Value = value;
} }
public int PlayerId
public ushort PlayerId
{ {
get => State.PlayerId;
get => playerID.Value;
} }
public EntityList KnownPlanetsList;
public EntityList VisiblePlanetsList;
private void OnPlanetsUpdated(NetworkListEvent<NetworkBehaviourReference> ev)
{
if(GameManager.EntitiesLoaded)
{
Planet.UpdateVisibilityStatus();
}
}
public override void Attached()
public override void OnNetworkSpawn()
{ {
Debug.Log("Attaching player..."); Debug.Log("Attaching player...");
PlayerList.Add(this); PlayerList.Add(this);
if(entity.IsOwner)
if(IsOwner)
{ {
State.PlayerId = PlayerList.IndexOf(this);
playerID.Value = (ushort) PlayerList.IndexOf(this);
} }
KnownPlanetsList = new EntityList(State, "KnownPlanetsList");
VisiblePlanetsList = new EntityList(State, "VisiblePlanetsList");
State.AddCallback("KnownPlanetsList", () => {
if(GameManager.EntitiesLoaded)
{
Planet.UpdateVisibilityStatus();
}
});
State.AddCallback("VisiblePlanetsList", () => {
if(GameManager.EntitiesLoaded)
{
Planet.UpdateVisibilityStatus();
}
});
knownPlanetsList.OnListChanged += OnPlanetsUpdated;
visiblePlanetsList.OnListChanged += OnPlanetsUpdated;
} }
public override void Detached()
public override void OnNetworkDespawn()
{ {
PlayerList.Remove(this); PlayerList.Remove(this);
} }
public override void ControlGained()
public override void OnGainedOwnership()
{ {
CurrentPlayer = this; CurrentPlayer = this;
BoltLog.Info("Current player is {0} with connection ID {1}", this, State.ConnectionId);
BoltLog.Info("Current player is {0} with connection ID {1}", this, OwnerClientId);
} }
public BoltConnection Connection
public NetworkClient Client
{ {
get get
{ {
if(State.IsAI || State.IsHost)
if(IsAI)
{ {
return null; return null;
} }
else else
{ {
return BoltNetwork.Connections.FirstOrDefault(conn => conn.ConnectionId == State.ConnectionId);
return NetworkManager.ConnectedClients[OwnerClientId];
} }
} }
} }
public void AssignControl(BoltEntity entity)
public void AssignControl(NetworkObject obj)
{ {
if(State.IsHost)
if(!IsAI)
{ {
entity.TakeControl();
}
else if(!State.IsAI)
{
entity.AssignControl(Connection);
obj.ChangeOwnership(OwnerClientId);
} }
} }
public void AssignStartingPlanets() public void AssignStartingPlanets()
@ -119,14 +121,45 @@ namespace GWConquest
d.ControllingPlayer = this; d.ControllingPlayer = this;
} }
p.SetPlanetVisible(this);
SetPlanetVisible(p);
} }
} }
} }
public override string ToString() public override string ToString()
{ {
return string.Format("Player (ID {0}, Faction {1})", State.PlayerId, Faction.FactionName);
return string.Format("Player (ID {0}, Faction {1})", PlayerId, Faction.FactionName);
}
public PlanetVisibilityStatus GetPlanetVisibility(Planet planet)
{
if(visiblePlanetsList.Contains(planet))
{
return PlanetVisibilityStatus.Visible;
}
else if(knownPlanetsList.Contains(planet))
{
return PlanetVisibilityStatus.Known;
}
else {
return PlanetVisibilityStatus.Hidden;
}
}
public void SetPlanetVisible(Planet planet)
{
if(GetPlanetVisibility(planet) != PlanetVisibilityStatus.Visible)
{
visiblePlanetsList.Add(planet);
foreach(var otherPlanet in planet.ConnectedPlanets)
{
if(GetPlanetVisibility(otherPlanet) == PlanetVisibilityStatus.Hidden)
{
knownPlanetsList.Add(otherPlanet);
}
}
}
} }
} }


+ 44
- 0
Assets/GWConquest/Scripts/UID.cs View File

@ -0,0 +1,44 @@
using Unity.Netcode;
using System;
namespace GWConquest {
public struct UID : INetworkSerializeByMemcpy, IEquatable<UID> {
public ushort value;
public UID(ushort _value)
{
value = _value;
}
public bool Equals(UID other)
{
return value == other.value;
}
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
return Equals((UID)obj);
}
public override int GetHashCode()
{
return value;
}
public static bool operator ==(UID id1, UID id2)
{
return id1.value == id2.value;
}
public static bool operator !=(UID id1, UID id2)
{
return id1.value != id2.value;
}
}
}

+ 11
- 0
Assets/GWConquest/Scripts/UID.cs.meta View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7793d4e07f641c04981bb5c3c3c33c90
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 104
- 83
Assets/GWConquest/Scripts/Unit.cs View File

@ -2,7 +2,7 @@
using UnityEngine; using UnityEngine;
using Photon.Bolt; using Photon.Bolt;
using Photon.Bolt.Utils; using Photon.Bolt.Utils;
using System.Collections.Generic;
using Unity.Netcode;
namespace GWConquest namespace GWConquest
{ {
@ -10,19 +10,38 @@ namespace GWConquest
Sprite Icon {get;} Sprite Icon {get;}
} }
public class Unit : GWBoltEntityListener<IUnitState>, IIconObject
public class Unit : NetworkBehaviour, IIconObject
{ {
private NetworkVariable<ushort> unitClass;
private NetworkVariable<NetworkBehaviourReference> formation;
private NetworkVariable<int> hitpoints;
private NetworkVariable<float> shields;
private NetworkVariable<float> shieldsCooldown;
private NetworkVariable<RevealState> revealState;
private NetworkVariable<BattleUnitState> battleState;
private NetworkVariable<float> actionCooldown;
private NetworkVariable<float> actionCooldownMax;
private Inventory inventory;
private Inventory equipment;
private NetworkVariable<int> flankTarget;
private NetworkVariable<float> morale;
private NetworkVariable<int> supplies;
private NetworkVariable<int> fuel;
private NetworkVariable<int> food;
public UnitClass Class public UnitClass Class
{ {
get => UnitClass.FromName(State.UnitClass);
get => UnitClass.FromID(unitClass.Value);
set { set {
if(value == null) if(value == null)
{ {
State.UnitClass = null;
Debug.LogError($"Unit Class set to null on unit {this}");
unitClass.Value = 0;
} }
else else
{ {
State.UnitClass = value.ShortName;
unitClass.Value = value.ID;
Inventory.StorageCapacity = value.InventorySlots; Inventory.StorageCapacity = value.InventorySlots;
Equipment.StorageCapacity = value.EquipmentSlots; Equipment.StorageCapacity = value.EquipmentSlots;
@ -37,24 +56,24 @@ namespace GWConquest
public Formation Formation public Formation Formation
{ {
get => BoltEntityCache.Get<Formation>(State.Formation);
set => State.Formation = BoltEntityCache.Set(value);
get => formation.Value.GetBehaviour<Formation>();
set => formation.Value = value;
} }
public int Hitpoints { public int Hitpoints {
get => State.Hitpoints;
set => State.Hitpoints = value;
get => hitpoints.Value;
set => hitpoints.Value = value;
} }
public float Shields { public float Shields {
get => State.Shields;
set => State.Shields = value;
get => shields.Value;
set => shields.Value = value;
} }
public float ShieldsCooldown public float ShieldsCooldown
{ {
get => State.ShieldsCooldown;
set => State.ShieldsCooldown = value;
get => shieldsCooldown.Value;
set => shieldsCooldown.Value = value;
} }
public float Armour { public float Armour {
@ -75,23 +94,23 @@ namespace GWConquest
public float Morale { public float Morale {
get => State.Morale;
set => State.Morale = value;
get => morale.Value;
set => morale.Value = value;
} }
public int Fuel { public int Fuel {
get => State.Fuel;
set => State.Fuel = value;
get => fuel.Value;
set => fuel.Value = value;
} }
public int Food { public int Food {
get => State.Food;
set => State.Food = value;
get => food.Value;
set => food.Value = value;
} }
public int Supplies { public int Supplies {
get => State.Supplies;
set => State.Supplies = value;
get => supplies.Value;
set => supplies.Value = value;
} }
public Player Player { public Player Player {
@ -99,10 +118,10 @@ namespace GWConquest
} }
public BattleUnitState BattleState { public BattleUnitState BattleState {
get => (BattleUnitState) State.BattleState;
get => battleState.Value;
set { set {
State.BattleState = (int) value;
if(BoltNetwork.IsServer)
battleState.Value = value;
if(IsServer)
{ {
if(CurrentBattle != null) if(CurrentBattle != null)
{ {
@ -113,10 +132,10 @@ namespace GWConquest
} }
public RevealState RevealState { public RevealState RevealState {
get => (RevealState) State.RevealState;
get => revealState.Value;
set { set {
State.RevealState = (int) value;
if(BoltNetwork.IsServer)
revealState.Value = value;
if(IsServer)
{ {
if(CurrentBattle != null) if(CurrentBattle != null)
{ {
@ -127,11 +146,11 @@ namespace GWConquest
} }
public float ActionCooldown { public float ActionCooldown {
get => State.ActionCooldown;
get => actionCooldown.Value;
} }
public float ActionCooldownPercent { public float ActionCooldownPercent {
get => State.ActionCooldown / State.ActionCooldownMax;
get => actionCooldown.Value / actionCooldownMax.Value;
} }
public BattleFlank FlankTarget { public BattleFlank FlankTarget {
@ -141,21 +160,26 @@ namespace GWConquest
return null; return null;
} }
else { else {
int ind = State.FlankTarget;
int ind = flankTarget.Value;
if(ind >= 0 && ind < CurrentBattle.FlankCount) if(ind >= 0 && ind < CurrentBattle.FlankCount)
{ {
return CurrentBattle.GetFlank(ind);
return CurrentBattle.GetFlank((ushort) ind);
} }
else return null; else return null;
} }
} }
set => State.FlankTarget = value == null ? -1 : value.FlankId;
set => flankTarget.Value = value == null ? -1 : value.FlankId;
} }
public void SetActionCooldown(float value) public void SetActionCooldown(float value)
{ {
State.ActionCooldown = value;
State.ActionCooldownMax = value;
actionCooldown.Value = value;
actionCooldownMax.Value = value;
}
public void ResetActionCooldown()
{
actionCooldown.Value = 0;
} }
[System.NonSerialized] [System.NonSerialized]
@ -184,36 +208,49 @@ namespace GWConquest
public Inventory Inventory; public Inventory Inventory;
public Inventory Equipment; public Inventory Equipment;
public override void Attached()
private void OnFormationChanged(NetworkBehaviourReference previousValue, NetworkBehaviourReference newValue)
{ {
Inventory = new Inventory(State, "Inventory");
Equipment = new Inventory(State, "Equipment");
State.AddCallback("Formation", () =>
Formation newFormation = newValue.GetBehaviour<Formation>();
if(newFormation != null)
{ {
if(Formation != null)
{
Formation.OnUnitAdded(this);
}
});
newFormation.OnUnitAdded(this);
}
}
State.AddCallback("UnitClass", () => {
Inventory.StorageCapacity = Class.InventorySlots;
Equipment.StorageCapacity = Class.EquipmentSlots;
private void OnUnitClassChanged(ushort oldID, ushort newID)
{
UnitClass newClass = UnitClass.FromID(newID);
Inventory.StorageCapacity = newClass.InventorySlots;
Equipment.StorageCapacity = newClass.EquipmentSlots;
if(entity.IsOwner)
{
Fuel = Class.FuelCapacity;
Food = Class.FoodCapacity;
Supplies = Class.SuppliesCapacity;
}
});
if(IsOwner)
{
Fuel = newClass.FuelCapacity;
Food = newClass.FoodCapacity;
Supplies = newClass.SuppliesCapacity;
}
}
public override void OnNetworkSpawn()
{
formation.OnValueChanged += OnFormationChanged;
unitClass.OnValueChanged += OnUnitClassChanged;
if(BoltNetwork.IsServer)
if(IsServer)
{ {
State.FlankTarget = -1;
flankTarget.Value = -1;
} }
base.OnNetworkSpawn();
}
public void InstantiateWithClass(UnitClass uc)
{
Class = uc;
gameObject.name = uc.ShortName + "_" + NetworkObjectId.ToString();
Hitpoints = uc.Hitpoints;
Shields = uc.Shields;
Morale = uc.Morale;
} }
public static Unit SpawnUnit(Zone zone, UnitClass uc, Player player) public static Unit SpawnUnit(Zone zone, UnitClass uc, Player player)
@ -221,31 +258,15 @@ namespace GWConquest
Formation playerFormation = zone.Formations.FirstOrDefault(f => f.Player == player); Formation playerFormation = zone.Formations.FirstOrDefault(f => f.Player == player);
if (playerFormation == null) if (playerFormation == null)
{ {
BoltEntity formationEntity = BoltNetwork.Instantiate(BoltPrefabs.Formation);
player.AssignControl(formationEntity);
playerFormation = formationEntity.GetComponent<Formation>();
playerFormation.gameObject.name = "Formation_" + formationEntity.NetworkId.PackedValue.ToString();
playerFormation.Player = player;
playerFormation.currentZone = zone;
playerFormation.ZoneType = uc.ZoneType;
if(playerFormation.ZoneType == ZoneType.Space)
{
Vector3 startPos = zone.planet.GetFleetRestingPosition();
playerFormation.State.FleetRestingPoint = startPos;
}
playerFormation = Formation.SpawnFormation(zone, player);
} }
BoltEntity unitEntity = BoltNetwork.Instantiate(BoltPrefabs.Unit); BoltEntity unitEntity = BoltNetwork.Instantiate(BoltPrefabs.Unit);
player.AssignControl(unitEntity); player.AssignControl(unitEntity);
Unit unit = unitEntity.GetComponent<Unit>(); Unit unit = unitEntity.GetComponent<Unit>();
unit.Class = uc;
unit.gameObject.name = uc.ShortName + "_" + unitEntity.NetworkId.PackedValue.ToString();
unit.State.Hitpoints = uc.Hitpoints;
unit.State.Shields = uc.Shields;
unit.State.Morale = uc.Morale;
unit.InstantiateWithClass(uc);
unit.Formation = playerFormation; unit.Formation = playerFormation;
playerFormation.UnitEntities.Add(unitEntity);
playerFormation.AddUnit(unit);
BoltLog.Info("Spawned unit {0} for player {1} in formation {2}", unit, player, playerFormation); BoltLog.Info("Spawned unit {0} for player {1} in formation {2}", unit, player, playerFormation);
@ -417,7 +438,7 @@ namespace GWConquest
} }
} }
public override void SimulateOwner()
public void FixedUpdate()
{ {
var battle = CurrentBattle; var battle = CurrentBattle;
if(!IsDead && battle != null && !battle.IsInPreparing) if(!IsDead && battle != null && !battle.IsInPreparing)
@ -432,7 +453,7 @@ namespace GWConquest
if (ActionCooldown <= 0) if (ActionCooldown <= 0)
{ {
State.ActionCooldown = 0;
actionCooldown.Value = 0;
if (BattleState == BattleUnitState.MovingToFlank) if (BattleState == BattleUnitState.MovingToFlank)
{ {
BattleState = BattleUnitState.OnFlank; BattleState = BattleUnitState.OnFlank;
@ -467,12 +488,12 @@ namespace GWConquest
} }
else else
{ {
State.ActionCooldown -= BoltNetwork.FrameDeltaTime;
actionCooldown.Value -= Time.fixedDeltaTime;
} }
if(ShieldsCooldown > 0) if(ShieldsCooldown > 0)
{ {
ShieldsCooldown -= BoltNetwork.FrameDeltaTime;
ShieldsCooldown -= Time.fixedDeltaTime;
if(ShieldsCooldown <= 0) if(ShieldsCooldown <= 0)
{ {
ShieldsCooldown = 0; ShieldsCooldown = 0;
@ -577,7 +598,7 @@ namespace GWConquest
} }
public int TotalFuel { public int TotalFuel {
get => Fuel + Inventory.GetItemAmount("Fuel");
get => Fuel + Inventory.GetItemAmount(ItemRegistry.kFuel);
} }
public void ConsumeTotalFuel(int amount) public void ConsumeTotalFuel(int amount)
@ -591,13 +612,13 @@ namespace GWConquest
else { else {
int diff = amount - Fuel; int diff = amount - Fuel;
Fuel = 0; Fuel = 0;
Inventory.RemoveItem("Fuel", diff);
Inventory.RemoveItem(ItemRegistry.kFuel, diff);
//Refill //Refill
int remaining = Inventory.GetItemAmount("Fuel");
int remaining = Inventory.GetItemAmount(ItemRegistry.kFuel);
int refill = Mathf.Min(remaining, Class.FuelCapacity); int refill = Mathf.Min(remaining, Class.FuelCapacity);
Fuel = refill; Fuel = refill;
Inventory.RemoveItem("Fuel", refill);
Inventory.RemoveItem(ItemRegistry.kFuel, refill);
} }
} }
} }


+ 32
- 2
Assets/GWConquest/Scripts/UnitClass.cs View File

@ -10,10 +10,13 @@ namespace GWConquest
public class UnitClass : IBuildable public class UnitClass : IBuildable
{ {
private static Dictionary<string, UnitClass> classMap; private static Dictionary<string, UnitClass> classMap;
private static UnitClass[] unitClasses;
private static ushort nextID = 0;
public static void ClearRegistry() public static void ClearRegistry()
{ {
classMap = null; classMap = null;
nextID = 0;
} }
public static void LoadClassMap() public static void LoadClassMap()
@ -29,7 +32,10 @@ namespace GWConquest
TextAsset heroDatabase = Resources.Load<TextAsset>("Database/Heroes"); TextAsset heroDatabase = Resources.Load<TextAsset>("Database/Heroes");
LoadHeroDatabase(heroDatabase); LoadHeroDatabase(heroDatabase);
GameManager.Instance.UnitClasses = classMap.Values.ToArray();
var classList = classMap.Values.ToList();
classList.Sort((uc1, uc2) => uc1.ID - uc2.ID);
unitClasses = classList.ToArray();
GameManager.Instance.UnitClasses = unitClasses;
BoltLog.Info("All unit classes loaded."); BoltLog.Info("All unit classes loaded.");
} }
@ -164,6 +170,9 @@ namespace GWConquest
unitClass.LoadTexture(); unitClass.LoadTexture();
unitClass.ID = nextID;
nextID++;
classMap.Add(unitClass.ShortName, unitClass); classMap.Add(unitClass.ShortName, unitClass);
} }
catch (Exception ex) catch (Exception ex)
@ -250,6 +259,9 @@ namespace GWConquest
unitClass.LoadTexture(); unitClass.LoadTexture();
unitClass.ID = nextID;
nextID++;
classMap.Add(unitClass.ShortName, unitClass); classMap.Add(unitClass.ShortName, unitClass);
} }
catch(Exception ex) catch(Exception ex)
@ -282,6 +294,22 @@ namespace GWConquest
} }
} }
public static UnitClass FromID(ushort id)
{
if (unitClasses == null)
{
LoadClassMap();
}
if(id < unitClasses.Length)
{
return unitClasses[id];
}
else {
Debug.LogWarningFormat("Unit class ID {0} not in list!", id);
return null;
}
}
public static IEnumerable<UnitClass> AllUnitClasses public static IEnumerable<UnitClass> AllUnitClasses
{ {
get { get {
@ -293,6 +321,7 @@ namespace GWConquest
} }
} }
public ushort ID {get; private set;}
public string FullName {get; private set;} public string FullName {get; private set;}
public string ShortName {get; private set;} public string ShortName {get; private set;}
public Sprite Sprite public Sprite Sprite
@ -413,7 +442,7 @@ namespace GWConquest
} }
} }
else { else {
if(!inventory.HasItem(cost.Item, cost.Amount))
if(!inventory.HasItem(ItemRegistry.Instance.IDFromName(cost.Item), cost.Amount))
{ {
return false; return false;
} }
@ -425,6 +454,7 @@ namespace GWConquest
public interface IBuildable public interface IBuildable
{ {
ushort ID {get;}
BuildCost BuildCost {get;} BuildCost BuildCost {get;}
float BuildTime {get;} float BuildTime {get;}
Sprite Sprite {get;} Sprite Sprite {get;}


+ 12
- 0
Assets/GWConquest/Scripts/Util.cs View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using UnityEngine.EventSystems; using UnityEngine.EventSystems;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Unity.Netcode;
namespace GWConquest namespace GWConquest
{ {
@ -311,6 +312,17 @@ namespace GWConquest
&& screenPoint.y >= -tolerance && screenPoint.y <= 1f + tolerance; && screenPoint.y >= -tolerance && screenPoint.y <= 1f + tolerance;
} }
public static T GetBehaviour<T>(this NetworkBehaviourReference reference) where T : NetworkBehaviour
{
if(reference.TryGet(out NetworkBehaviour beh))
{
return beh as T;
}
else {
return null;
}
}
} }
} }

+ 4
- 2
Assets/GWConquest/Textures/Art/FactionPreviewDominion.renderTexture View File

@ -12,12 +12,13 @@ RenderTexture:
Hash: 00000000000000000000000000000000 Hash: 00000000000000000000000000000000
m_ForcedFallbackFormat: 4 m_ForcedFallbackFormat: 4
m_DownscaleFallback: 0 m_DownscaleFallback: 0
serializedVersion: 3
m_IsAlphaChannelOptional: 0
serializedVersion: 5
m_Width: 2048 m_Width: 2048
m_Height: 2048 m_Height: 2048
m_AntiAliasing: 1 m_AntiAliasing: 1
m_MipCount: -1 m_MipCount: -1
m_DepthFormat: 2
m_DepthStencilFormat: 92
m_ColorFormat: 8 m_ColorFormat: 8
m_MipMap: 0 m_MipMap: 0
m_GenerateMips: 1 m_GenerateMips: 1
@ -35,3 +36,4 @@ RenderTexture:
m_WrapW: 1 m_WrapW: 1
m_Dimension: 2 m_Dimension: 2
m_VolumeDepth: 1 m_VolumeDepth: 1
m_ShadowSamplingMode: 2

+ 4
- 2
Assets/GWConquest/Textures/Art/FactionPreviewRepublic.renderTexture View File

@ -12,12 +12,13 @@ RenderTexture:
Hash: 00000000000000000000000000000000 Hash: 00000000000000000000000000000000
m_ForcedFallbackFormat: 4 m_ForcedFallbackFormat: 4
m_DownscaleFallback: 0 m_DownscaleFallback: 0
serializedVersion: 3
m_IsAlphaChannelOptional: 0
serializedVersion: 5
m_Width: 2048 m_Width: 2048
m_Height: 2048 m_Height: 2048
m_AntiAliasing: 1 m_AntiAliasing: 1
m_MipCount: -1 m_MipCount: -1
m_DepthFormat: 2
m_DepthStencilFormat: 92
m_ColorFormat: 8 m_ColorFormat: 8
m_MipMap: 0 m_MipMap: 0
m_GenerateMips: 1 m_GenerateMips: 1
@ -35,3 +36,4 @@ RenderTexture:
m_WrapW: 1 m_WrapW: 1
m_Dimension: 2 m_Dimension: 2
m_VolumeDepth: 1 m_VolumeDepth: 1
m_ShadowSamplingMode: 2

+ 10
- 3
Assets/GWConquest/Textures/UI/Materials/kreiswichs3.mat View File

@ -2,14 +2,18 @@
%TAG !u! tag:unity3d.com,2011: %TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000 --- !u!21 &2100000
Material: Material:
serializedVersion: 6
serializedVersion: 8
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0} m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_Name: kreiswichs3 m_Name: kreiswichs3
m_Shader: {fileID: 211, guid: 0000000000000000f000000000000000, type: 0} m_Shader: {fileID: 211, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords: _ALPHAPREMULTIPLY_ON
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords:
- _ALPHAPREMULTIPLY_ON
m_InvalidKeywords: []
m_LightmapFlags: 0 m_LightmapFlags: 0
m_EnableInstancingVariants: 0 m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0 m_DoubleSidedGI: 0
@ -17,7 +21,8 @@ Material:
stringTagMap: stringTagMap:
RenderType: Transparent RenderType: Transparent
disabledShaderPasses: disabledShaderPasses:
- ALWAYS
- GRABPASS
m_LockedProperties:
m_SavedProperties: m_SavedProperties:
serializedVersion: 3 serializedVersion: 3
m_TexEnvs: m_TexEnvs:
@ -57,6 +62,7 @@ Material:
m_Texture: {fileID: 0} m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1} m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0} m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats: m_Floats:
- _BlendOp: 0 - _BlendOp: 0
- _BumpScale: 1 - _BumpScale: 1
@ -103,3 +109,4 @@ Material:
- _ColorAddSubDiff: {r: 1, g: 0, b: 0, a: 0} - _ColorAddSubDiff: {r: 1, g: 0, b: 0, a: 0}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1} - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _SoftParticleFadeParams: {r: 0, g: 0, b: 0, a: 0} - _SoftParticleFadeParams: {r: 0, g: 0, b: 0, a: 0}
m_BuildTextureStacks: []

+ 1
- 0
Packages/manifest.json View File

@ -7,6 +7,7 @@
"com.unity.ide.rider": "3.0.24", "com.unity.ide.rider": "3.0.24",
"com.unity.ide.visualstudio": "2.0.18", "com.unity.ide.visualstudio": "2.0.18",
"com.unity.ide.vscode": "1.2.5", "com.unity.ide.vscode": "1.2.5",
"com.unity.netcode.gameobjects": "1.5.1",
"com.unity.postprocessing": "3.2.2", "com.unity.postprocessing": "3.2.2",
"com.unity.test-framework": "1.1.33", "com.unity.test-framework": "1.1.33",
"com.unity.timeline": "1.7.4", "com.unity.timeline": "1.7.4",


+ 38
- 0
Packages/packages-lock.json View File

@ -44,6 +44,16 @@
"dependencies": {}, "dependencies": {},
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
}, },
"com.unity.collections": {
"version": "1.2.4",
"depth": 2,
"source": "registry",
"dependencies": {
"com.unity.burst": "1.6.6",
"com.unity.test-framework": "1.1.31"
},
"url": "https://packages.unity.com"
},
"com.unity.ext.nunit": { "com.unity.ext.nunit": {
"version": "1.0.6", "version": "1.0.6",
"depth": 1, "depth": 1,
@ -83,6 +93,23 @@
"dependencies": {}, "dependencies": {},
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
}, },
"com.unity.netcode.gameobjects": {
"version": "1.5.1",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.nuget.mono-cecil": "1.10.1",
"com.unity.transport": "1.3.4"
},
"url": "https://packages.unity.com"
},
"com.unity.nuget.mono-cecil": {
"version": "1.11.4",
"depth": 1,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.postprocessing": { "com.unity.postprocessing": {
"version": "3.2.2", "version": "3.2.2",
"depth": 0, "depth": 0,
@ -115,6 +142,17 @@
}, },
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
}, },
"com.unity.transport": {
"version": "1.3.4",
"depth": 1,
"source": "registry",
"dependencies": {
"com.unity.collections": "1.2.4",
"com.unity.burst": "1.6.6",
"com.unity.mathematics": "1.2.6"
},
"url": "https://packages.unity.com"
},
"com.unity.ugui": { "com.unity.ugui": {
"version": "1.0.0", "version": "1.0.0",
"depth": 0, "depth": 0,


Loading…
Cancel
Save