using System; using GeometryTD.Definition; using GeometryTD.UI; using UnityEngine; using UnityGameFramework.Runtime; namespace GeometryTD.CustomComponent { public class PlayerInventoryComponent : GameFrameworkComponent { private BackpackInventoryData _inventory = new BackpackInventoryData(); private long _nextInstanceId = 1; private bool _initialized; public int Gold { get { EnsureInitialized(); return _inventory.Gold; } } public void OnInit() { _inventory = CloneInventory(RepoFormUseCase.SampleInventory()); RebuildNextInstanceId(); _initialized = true; Log.Info( "PlayerInventory initialized. Gold={0}, Tower={1}, Muzzle={2}, Bearing={3}, Base={4}.", _inventory.Gold, _inventory.Towers.Count, _inventory.MuzzleComponents.Count, _inventory.BearingComponents.Count, _inventory.BaseComponents.Count); } public BackpackInventoryData GetInventorySnapshot() { EnsureInitialized(); return CloneInventory(_inventory); } public void MergeInventory(BackpackInventoryData gainedInventory) { EnsureInitialized(); if (gainedInventory == null) { return; } int gainedGold = Mathf.Max(0, gainedInventory.Gold); int gainedMuzzleCount = 0; int gainedBearingCount = 0; int gainedBaseCount = 0; int gainedTowerCount = 0; if (gainedGold > 0) { _inventory.Gold += gainedGold; } if (gainedInventory.MuzzleComponents != null) { for (int i = 0; i < gainedInventory.MuzzleComponents.Count; i++) { MuzzleCompItemData source = gainedInventory.MuzzleComponents[i]; if (source == null) { continue; } MuzzleCompItemData cloned = CloneMuzzleComp(source); cloned.InstanceId = AllocateInstanceId(); _inventory.MuzzleComponents.Add(cloned); gainedMuzzleCount++; } } if (gainedInventory.BearingComponents != null) { for (int i = 0; i < gainedInventory.BearingComponents.Count; i++) { BearingCompItemData source = gainedInventory.BearingComponents[i]; if (source == null) { continue; } BearingCompItemData cloned = CloneBearingComp(source); cloned.InstanceId = AllocateInstanceId(); _inventory.BearingComponents.Add(cloned); gainedBearingCount++; } } if (gainedInventory.BaseComponents != null) { for (int i = 0; i < gainedInventory.BaseComponents.Count; i++) { BaseCompItemData source = gainedInventory.BaseComponents[i]; if (source == null) { continue; } BaseCompItemData cloned = CloneBaseComp(source); cloned.InstanceId = AllocateInstanceId(); _inventory.BaseComponents.Add(cloned); gainedBaseCount++; } } if (gainedInventory.Towers != null) { for (int i = 0; i < gainedInventory.Towers.Count; i++) { DefenseTowerItemData source = gainedInventory.Towers[i]; if (source == null) { continue; } DefenseTowerItemData cloned = CloneTower(source); cloned.InstanceId = AllocateInstanceId(); _inventory.Towers.Add(cloned); gainedTowerCount++; } } if (gainedGold > 0 || gainedMuzzleCount > 0 || gainedBearingCount > 0 || gainedBaseCount > 0 || gainedTowerCount > 0) { Log.Info( "PlayerInventory merged reward. Gold+{0}, Tower+{1}, Muzzle+{2}, Bearing+{3}, Base+{4}.", gainedGold, gainedTowerCount, gainedMuzzleCount, gainedBearingCount, gainedBaseCount); } } public bool TryConsumeGold(int costGold) { EnsureInitialized(); int resolvedCost = Mathf.Max(0, costGold); if (resolvedCost <= 0) { return true; } if (_inventory.Gold < resolvedCost) { return false; } _inventory.Gold -= resolvedCost; return true; } public void AddGold(int gainGold) { EnsureInitialized(); int resolvedGain = Mathf.Max(0, gainGold); if (resolvedGain <= 0) { return; } _inventory.Gold += resolvedGain; } public int ReduceAllTowerEndurance(float enduranceLoss) { EnsureInitialized(); float resolvedLoss = Mathf.Max(0f, enduranceLoss); if (resolvedLoss <= 0f || _inventory.Towers == null || _inventory.Towers.Count <= 0) { return 0; } int affectedCount = 0; for (int i = 0; i < _inventory.Towers.Count; i++) { DefenseTowerItemData tower = _inventory.Towers[i]; if (tower == null) { continue; } float originalEndurance = tower.Endurance; float nextEndurance = Mathf.Clamp(originalEndurance - resolvedLoss, 0f, 100f); if (nextEndurance >= originalEndurance) { continue; } tower.Endurance = nextEndurance; affectedCount++; } return affectedCount; } private void EnsureInitialized() { if (_initialized) { return; } OnInit(); } private long AllocateInstanceId() { if (_nextInstanceId < 1) { _nextInstanceId = 1; } return _nextInstanceId++; } private void RebuildNextInstanceId() { long maxInstanceId = 0; if (_inventory.Towers != null) { for (int i = 0; i < _inventory.Towers.Count; i++) { DefenseTowerItemData item = _inventory.Towers[i]; if (item != null) { maxInstanceId = Math.Max(maxInstanceId, item.InstanceId); } } } if (_inventory.MuzzleComponents != null) { for (int i = 0; i < _inventory.MuzzleComponents.Count; i++) { MuzzleCompItemData item = _inventory.MuzzleComponents[i]; if (item != null) { maxInstanceId = Math.Max(maxInstanceId, item.InstanceId); } } } if (_inventory.BearingComponents != null) { for (int i = 0; i < _inventory.BearingComponents.Count; i++) { BearingCompItemData item = _inventory.BearingComponents[i]; if (item != null) { maxInstanceId = Math.Max(maxInstanceId, item.InstanceId); } } } if (_inventory.BaseComponents != null) { for (int i = 0; i < _inventory.BaseComponents.Count; i++) { BaseCompItemData item = _inventory.BaseComponents[i]; if (item != null) { maxInstanceId = Math.Max(maxInstanceId, item.InstanceId); } } } _nextInstanceId = Math.Max(1, maxInstanceId + 1); } private static BackpackInventoryData CloneInventory(BackpackInventoryData source) { BackpackInventoryData cloned = new BackpackInventoryData(); if (source == null) { return cloned; } cloned.Gold = Mathf.Max(0, source.Gold); if (source.MuzzleComponents != null) { for (int i = 0; i < source.MuzzleComponents.Count; i++) { MuzzleCompItemData item = source.MuzzleComponents[i]; if (item != null) { cloned.MuzzleComponents.Add(CloneMuzzleComp(item)); } } } if (source.BearingComponents != null) { for (int i = 0; i < source.BearingComponents.Count; i++) { BearingCompItemData item = source.BearingComponents[i]; if (item != null) { cloned.BearingComponents.Add(CloneBearingComp(item)); } } } if (source.BaseComponents != null) { for (int i = 0; i < source.BaseComponents.Count; i++) { BaseCompItemData item = source.BaseComponents[i]; if (item != null) { cloned.BaseComponents.Add(CloneBaseComp(item)); } } } if (source.Towers != null) { for (int i = 0; i < source.Towers.Count; i++) { DefenseTowerItemData item = source.Towers[i]; if (item != null) { cloned.Towers.Add(CloneTower(item)); } } } return cloned; } private static MuzzleCompItemData CloneMuzzleComp(MuzzleCompItemData source) { return new MuzzleCompItemData { InstanceId = source.InstanceId, ConfigId = source.ConfigId, Name = source.Name, Rarity = source.Rarity, Endurance = source.Endurance, Constraint = source.Constraint, Tags = CloneTags(source.Tags), AttackDamage = CloneIntArray(source.AttackDamage), DamageRandomRate = source.DamageRandomRate, AttackMethodType = source.AttackMethodType }; } private static BearingCompItemData CloneBearingComp(BearingCompItemData source) { return new BearingCompItemData { InstanceId = source.InstanceId, ConfigId = source.ConfigId, Name = source.Name, Rarity = source.Rarity, Endurance = source.Endurance, Constraint = source.Constraint, Tags = CloneTags(source.Tags), RotateSpeed = CloneFloatArray(source.RotateSpeed), AttackRange = CloneFloatArray(source.AttackRange) }; } private static BaseCompItemData CloneBaseComp(BaseCompItemData source) { return new BaseCompItemData { InstanceId = source.InstanceId, ConfigId = source.ConfigId, Name = source.Name, Rarity = source.Rarity, Endurance = source.Endurance, Constraint = source.Constraint, Tags = CloneTags(source.Tags), AttackSpeed = CloneFloatArray(source.AttackSpeed), AttackPropertyType = source.AttackPropertyType }; } private static DefenseTowerItemData CloneTower(DefenseTowerItemData source) { return new DefenseTowerItemData { InstanceId = source.InstanceId, Name = source.Name, Rarity = source.Rarity, Endurance = source.Endurance, MuzzleComponentInstanceId = source.MuzzleComponentInstanceId, BearingComponentInstanceId = source.BearingComponentInstanceId, BaseComponentInstanceId = source.BaseComponentInstanceId, Stats = CloneTowerStats(source.Stats) }; } private static DefenseTowerStatsData CloneTowerStats(DefenseTowerStatsData source) { if (source == null) { return new DefenseTowerStatsData(); } return new DefenseTowerStatsData { AttackDamage = source.AttackDamage, DamageRandomRate = source.DamageRandomRate, RotateSpeed = source.RotateSpeed, AttackRange = source.AttackRange, AttackSpeed = source.AttackSpeed, AttackMethodType = source.AttackMethodType, AttackPropertyType = source.AttackPropertyType, Tags = CloneTags(source.Tags) }; } private static int[] CloneIntArray(int[] source) { return source != null ? (int[])source.Clone() : Array.Empty(); } private static float[] CloneFloatArray(float[] source) { return source != null ? (float[])source.Clone() : Array.Empty(); } private static TagType[] CloneTags(TagType[] source) { return source != null ? (TagType[])source.Clone() : Array.Empty(); } } }