feat: Introduce new services and refactor existing code for better structure

- Added ISpriteCacheService, IStaticDataService, and ITextService interfaces for improved service management.
- Implemented RunContracts for managing run states and node execution contexts.
- Created EnemyTagStatusRuntime to handle enemy status effects and their application.
- Refactored ShopPriceRuleService to utilize static data service for shop prices.
- Enhanced InventoryTowerEnduranceUtility to manage tower endurance reduction.
- Updated EventFormUseCase to work with new EventOptionExecutionContext.
- Removed unused dictionary loading code from ProcedurePreload.
- Cleaned up various utility classes and ensured consistent naming conventions.
- Updated tests to reflect changes in context and service usage.
This commit is contained in:
SepComet 2026-05-13 22:18:47 +08:00
parent 9fc0ef2216
commit 7106e0adbe
45 changed files with 590 additions and 426 deletions

View File

@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using GameFramework.DataTable; using GameFramework.DataTable;
using GeometryTD.Core;
using GeometryTD.CustomEvent; using GeometryTD.CustomEvent;
using GeometryTD.DataTable; using GeometryTD.DataTable;
using GeometryTD.Definition; using GeometryTD.Definition;
@ -79,7 +80,7 @@ namespace GeometryTD.CustomComponent
return; return;
} }
_eventFormUseCase.BindEvent(_activeEvent, _activeContext); _eventFormUseCase.BindEvent(_activeEvent, CreateEventOptionExecutionContext(_activeContext));
GameEntry.UIRouter.OpenUI(UIFormType.EventForm); GameEntry.UIRouter.OpenUI(UIFormType.EventForm);
GameEntry.Event.Fire( GameEntry.Event.Fire(
this, this,
@ -236,5 +237,12 @@ namespace GeometryTD.CustomComponent
return seed; return seed;
} }
} }
private static EventOptionExecutionContext CreateEventOptionExecutionContext(RunNodeExecutionContext context)
{
return new EventOptionExecutionContext(
context?.RunSeed ?? 0,
context?.SequenceIndex ?? -1);
}
} }
} }

View File

@ -123,7 +123,7 @@ namespace GeometryTD.CustomComponent
private int ResolveRandomPrice(RarityType rarity, Random random) private int ResolveRandomPrice(RarityType rarity, Random random)
{ {
return ShopPriceRuleService.ResolveRandomBuyPrice(_shopPriceRows, rarity, random); return ShopPriceRuleService.ResolveRandomBuyPrice(rarity, random);
} }
private static IconAreaContext BuildIconAreaContext(TowerCompItemData item) private static IconAreaContext BuildIconAreaContext(TowerCompItemData item)

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using GeometryTD.Core;
using GeometryTD.CustomUtility; using GeometryTD.CustomUtility;
using GeometryTD.Definition; using GeometryTD.Definition;
using UnityEngine; using UnityEngine;
@ -42,108 +43,4 @@ namespace GeometryTD.CustomComponent
enduranceLoss); enduranceLoss);
} }
} }
public static class InventoryTowerEnduranceUtility
{
public static int ReduceTowerEndurance(
BackpackInventoryData inventory,
IReadOnlyList<long> towerInstanceIds,
float enduranceLoss)
{
float resolvedLoss = Mathf.Max(0f, enduranceLoss);
if (inventory?.Towers == null ||
inventory.Towers.Count <= 0 ||
resolvedLoss <= 0f ||
towerInstanceIds == null ||
towerInstanceIds.Count <= 0)
{
return 0;
}
Dictionary<long, MuzzleCompItemData> muzzleMap = BuildComponentMap(inventory.MuzzleComponents);
Dictionary<long, BearingCompItemData> bearingMap = BuildComponentMap(inventory.BearingComponents);
Dictionary<long, BaseCompItemData> baseMap = BuildComponentMap(inventory.BaseComponents);
HashSet<long> processedTowerIds = new HashSet<long>();
int affectedCount = 0;
for (int i = 0; i < towerInstanceIds.Count; i++)
{
long towerInstanceId = towerInstanceIds[i];
if (towerInstanceId <= 0 || !processedTowerIds.Add(towerInstanceId))
{
continue;
}
if (!InventoryParticipantUtility.TryGetTowerById(inventory, towerInstanceId, out TowerItemData tower) ||
tower == null)
{
continue;
}
bool towerAffected = false;
if (muzzleMap.TryGetValue(tower.MuzzleComponentInstanceId, out MuzzleCompItemData muzzleComp))
{
towerAffected |= TryReduceComponentEndurance(muzzleComp, resolvedLoss);
}
if (bearingMap.TryGetValue(tower.BearingComponentInstanceId, out BearingCompItemData bearingComp))
{
towerAffected |= TryReduceComponentEndurance(bearingComp, resolvedLoss);
}
if (baseMap.TryGetValue(tower.BaseComponentInstanceId, out BaseCompItemData baseComp))
{
towerAffected |= TryReduceComponentEndurance(baseComp, resolvedLoss);
}
if (towerAffected)
{
affectedCount++;
}
}
return affectedCount;
}
private static bool TryReduceComponentEndurance(TowerCompItemData component, float enduranceLoss)
{
if (component == null)
{
return false;
}
float originalEndurance = component.Endurance;
float nextEndurance = Mathf.Clamp(originalEndurance - Mathf.Max(0f, enduranceLoss), 0f, 100f);
if (nextEndurance >= originalEndurance)
{
return false;
}
component.Endurance = nextEndurance;
return true;
}
private static Dictionary<long, TComp> BuildComponentMap<TComp>(List<TComp> components)
where TComp : TowerCompItemData
{
Dictionary<long, TComp> map = new Dictionary<long, TComp>();
if (components == null || components.Count <= 0)
{
return map;
}
for (int i = 0; i < components.Count; i++)
{
TComp component = components[i];
if (component == null || component.InstanceId <= 0)
{
continue;
}
map[component.InstanceId] = component;
}
return map;
}
}
} }

View File

@ -1,7 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using GameFramework.DataTable;
using GeometryTD.CustomUtility; using GeometryTD.CustomUtility;
using GeometryTD.DataTable;
using GeometryTD.Definition; using GeometryTD.Definition;
using UnityEngine; using UnityEngine;
@ -41,16 +39,13 @@ namespace GeometryTD.CustomComponent
{ {
private readonly PlayerInventoryQueryModel _queryModel; private readonly PlayerInventoryQueryModel _queryModel;
private readonly PlayerInventoryCommandModel _commandModel; private readonly PlayerInventoryCommandModel _commandModel;
private IDataTable<DRShopPrice> _shopPriceTable;
public PlayerInventoryTradeService( public PlayerInventoryTradeService(
PlayerInventoryQueryModel queryModel, PlayerInventoryQueryModel queryModel,
PlayerInventoryCommandModel commandModel, PlayerInventoryCommandModel commandModel)
IDataTable<DRShopPrice> shopPriceTable = null)
{ {
_queryModel = queryModel; _queryModel = queryModel;
_commandModel = commandModel; _commandModel = commandModel;
_shopPriceTable = shopPriceTable;
} }
public bool TryPurchaseComponent(TowerCompItemData item, int price) public bool TryPurchaseComponent(TowerCompItemData item, int price)
@ -179,7 +174,7 @@ namespace GeometryTD.CustomComponent
}; };
} }
if (!ShopPriceRuleService.TryResolveTowerSalePrice(tower, inventory, out int towerPrice, EnsureShopPriceTable())) if (!ShopPriceRuleService.TryResolveTowerSalePrice(tower, inventory, out int towerPrice))
{ {
return new PlayerInventorySaleCandidate return new PlayerInventorySaleCandidate
{ {
@ -249,7 +244,7 @@ namespace GeometryTD.CustomComponent
ItemId = component.InstanceId, ItemId = component.InstanceId,
IsSellable = true, IsSellable = true,
IsTower = false, IsTower = false,
Price = ShopPriceRuleService.ResolveComponentSalePrice(component, EnsureShopPriceTable()), Price = ShopPriceRuleService.ResolveComponentSalePrice(component),
FailureReason = PlayerInventorySaleFailureReason.None FailureReason = PlayerInventorySaleFailureReason.None
}; };
} }
@ -390,11 +385,5 @@ namespace GeometryTD.CustomComponent
return inventory; return inventory;
} }
private IDataTable<DRShopPrice> EnsureShopPriceTable()
{
_shopPriceTable ??= GameEntry.DataTable.GetDataTable<DRShopPrice>();
return _shopPriceTable;
}
} }
} }

View File

@ -2,9 +2,7 @@
"name": "GeometryTD.Core", "name": "GeometryTD.Core",
"rootNamespace": "GeometryTD.Core", "rootNamespace": "GeometryTD.Core",
"references": [ "references": [
"GUID:363c5eb08ff8e6a439b85e37b8c20d96", "GUID:363c5eb08ff8e6a439b85e37b8c20d96"
"GUID:75469ad4d38634e559750d17036d5f7c",
"GUID:6055be8ebefd69e48b49212b09b47b2f"
], ],
"includePlatforms": [], "includePlatforms": [],
"excludePlatforms": [], "excludePlatforms": [],

View File

@ -1,12 +1,21 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using GeometryTD.CustomComponent;
using GeometryTD.Core;
using GeometryTD.Procedure;
using UnityEngine; using UnityEngine;
namespace GeometryTD.Core namespace GeometryTD.Core
{ {
public sealed class EventOptionExecutionContext
{
public EventOptionExecutionContext(int runSeed, int sequenceIndex)
{
RunSeed = runSeed;
SequenceIndex = sequenceIndex;
}
public int RunSeed { get; }
public int SequenceIndex { get; }
}
public sealed class EventOptionExecutor public sealed class EventOptionExecutor
{ {
public EventOptionAvailability EvaluateOption(EventOption option, BackpackInventoryData inventory) public EventOptionAvailability EvaluateOption(EventOption option, BackpackInventoryData inventory)
@ -37,7 +46,7 @@ namespace GeometryTD.Core
public EventOptionExecutionResult Execute( public EventOptionExecutionResult Execute(
EventItem eventItem, EventItem eventItem,
int optionIndex, int optionIndex,
RunNodeExecutionContext context, EventOptionExecutionContext context,
BackpackInventoryData workingInventory) BackpackInventoryData workingInventory)
{ {
if (eventItem == null || workingInventory == null) if (eventItem == null || workingInventory == null)
@ -72,7 +81,7 @@ namespace GeometryTD.Core
EventEffectBase[] effects, EventEffectBase[] effects,
EventItem eventItem, EventItem eventItem,
int optionIndex, int optionIndex,
RunNodeExecutionContext context, EventOptionExecutionContext context,
BackpackInventoryData workingInventory, BackpackInventoryData workingInventory,
bool isRewardPhase) bool isRewardPhase)
{ {
@ -143,7 +152,7 @@ namespace GeometryTD.Core
RemoveRandomCompsParam param, RemoveRandomCompsParam param,
int eventId, int eventId,
int optionIndex, int optionIndex,
RunNodeExecutionContext context, EventOptionExecutionContext context,
BackpackInventoryData workingInventory, BackpackInventoryData workingInventory,
int effectIndex) int effectIndex)
{ {
@ -171,7 +180,7 @@ namespace GeometryTD.Core
AddRandomCompsParam param, AddRandomCompsParam param,
int eventId, int eventId,
int optionIndex, int optionIndex,
RunNodeExecutionContext context, EventOptionExecutionContext context,
BackpackInventoryData workingInventory, BackpackInventoryData workingInventory,
int effectIndex) int effectIndex)
{ {
@ -181,12 +190,12 @@ namespace GeometryTD.Core
return; return;
} }
if (GameEntry.InventoryGeneration == null) if (CoreServiceHub.InventoryGeneration == null)
{ {
throw new InvalidOperationException("Event component generation requires InventoryGenerationComponent."); throw new InvalidOperationException("Event component generation requires InventoryGenerationComponent.");
} }
IReadOnlyList<TowerCompItemData> generatedComponents = GameEntry.InventoryGeneration.BuildEventRewardComponents( IReadOnlyList<TowerCompItemData> generatedComponents = CoreServiceHub.InventoryGeneration.BuildEventRewardComponents(
addCount, addCount,
param.MinRarity, param.MinRarity,
param.MaxRarity, param.MaxRarity,
@ -205,7 +214,7 @@ namespace GeometryTD.Core
DamageRandomTowerEnduranceParam param, DamageRandomTowerEnduranceParam param,
int eventId, int eventId,
int optionIndex, int optionIndex,
RunNodeExecutionContext context, EventOptionExecutionContext context,
BackpackInventoryData workingInventory, BackpackInventoryData workingInventory,
int effectIndex) int effectIndex)
{ {
@ -272,7 +281,7 @@ namespace GeometryTD.Core
} }
} }
private static bool RollProbability(int eventId, int optionIndex, RunNodeExecutionContext context, float probability) private static bool RollProbability(int eventId, int optionIndex, EventOptionExecutionContext context, float probability)
{ {
float clampedProbability = Mathf.Clamp01(probability); float clampedProbability = Mathf.Clamp01(probability);
if (clampedProbability >= 1f) if (clampedProbability >= 1f)
@ -290,7 +299,7 @@ namespace GeometryTD.Core
} }
private static System.Random CreateRandom( private static System.Random CreateRandom(
RunNodeExecutionContext context, EventOptionExecutionContext context,
int eventId, int eventId,
int optionIndex, int optionIndex,
int effectIndex, int effectIndex,

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9aeb92ccac2068f489dcbd0200417463
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,31 @@
using System;
namespace GeometryTD.Core
{
public static class CoreServiceHub
{
public static IPlayerInventoryManager PlayerInventory { get; private set; }
public static IInventoryGenerationManager InventoryGeneration { get; private set; }
public static IEventFlowManager EventFlow { get; private set; }
public static ISpriteCacheService SpriteCache { get; private set; }
public static IStaticDataService StaticData { get; private set; }
public static ITextService TextService { get; private set; }
public static void Bind(
IPlayerInventoryManager playerInventory,
IInventoryGenerationManager inventoryGeneration,
IEventFlowManager eventFlow,
ISpriteCacheService spriteCache,
IStaticDataService staticData,
ITextService textService)
{
PlayerInventory = playerInventory ?? throw new ArgumentNullException(nameof(playerInventory));
InventoryGeneration = inventoryGeneration ?? throw new
ArgumentNullException(nameof(inventoryGeneration));
EventFlow = eventFlow ?? throw new ArgumentNullException(nameof(eventFlow));
SpriteCache = spriteCache ?? throw new ArgumentNullException(nameof(spriteCache));
StaticData = staticData ?? throw new ArgumentNullException(nameof(staticData));
TextService = textService ?? throw new ArgumentNullException(nameof(textService));
}
}
}

View File

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

View File

@ -0,0 +1,7 @@
namespace GeometryTD.Core
{
public interface IEventFlowManager
{
void EndEvent();
}
}

View File

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

View File

@ -0,0 +1,17 @@
using System.Collections.Generic;
namespace GeometryTD.Core
{
public interface IInventoryGenerationManager
{
IReadOnlyList<TowerCompItemData> BuildEventRewardComponents(
int count,
RarityType minRarity,
RarityType maxRarity,
int runSeed,
int sequenceIndex,
int eventId,
int optionIndex,
int effectIndex);
}
}

View File

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

View File

@ -0,0 +1,8 @@
namespace GeometryTD.Core
{
public interface IPlayerInventoryManager
{
BackpackInventoryData GetInventorySnapshot();
void ReplaceInventorySnapshot(BackpackInventoryData snapshot);
}
}

View File

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

View File

@ -0,0 +1,11 @@
using System;
using UnityEngine;
namespace GeometryTD.Core
{
public interface ISpriteCacheService
{
void Get(string key, Action<Sprite> callback);
}
}

View File

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

View File

@ -0,0 +1,12 @@
namespace GeometryTD.Core
{
public interface IStaticDataService
{
DRLevel GetLevel(int id);
DRTag GetTag(int id);
DRShopPrice[] GetAllShopPrices();
DRBearingComp[] GetAllBearingComps();
DRBaseComp[] GetAllBaseComps();
DRMuzzleComp[] GetAllMuzzleComps();
}
}

View File

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

View File

@ -0,0 +1,7 @@
namespace GeometryTD.Core
{
public interface ITextService
{
string Get(string key, params object[] args);
}
}

View File

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

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f9d6ff9eff8570b4a96f296f9b107baa
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,150 @@
using System;
using System.Collections.Generic;
namespace GeometryTD.Core
{
public enum RunNodeType
{
None = 0,
Combat = 1,
Event = 2,
Shop = 3,
BossCombat = 4
}
public enum RunNodeCompletionStatus
{
None = 0,
Completed = 1,
Exception = 2
}
[Serializable]
public sealed class RunItemState
{
public int ItemId { get; set; }
public int StackCount { get; set; }
public RunItemState Clone()
{
return new RunItemState
{
ItemId = ItemId,
StackCount = StackCount
};
}
}
[Serializable]
public sealed class RunNodeExecutionContext
{
public string RunId { get; set; }
public int RunSeed { get; set; }
public int NodeId { get; set; }
public RunNodeType NodeType { get; set; }
public int SequenceIndex { get; set; }
public LevelThemeType ThemeType { get; set; }
public int ThemeStageIndex { get; set; }
public List<LevelThemeType> CurrentThemePool { get; set; } = new List<LevelThemeType>();
public List<LevelThemeType> ThemeHistory { get; set; } = new List<LevelThemeType>();
public int CurrentNodeContinueChallengeLayer { get; set; }
public List<RunItemState> RunItems { get; set; } = new List<RunItemState>();
public RunNodeExecutionContext Clone()
{
return new RunNodeExecutionContext
{
RunId = RunId,
RunSeed = RunSeed,
NodeId = NodeId,
NodeType = NodeType,
SequenceIndex = SequenceIndex,
ThemeType = ThemeType,
ThemeStageIndex = ThemeStageIndex,
CurrentThemePool = RunStateCloneUtility.CloneThemeList(CurrentThemePool),
ThemeHistory = RunStateCloneUtility.CloneThemeList(ThemeHistory),
CurrentNodeContinueChallengeLayer = CurrentNodeContinueChallengeLayer,
RunItems = RunStateCloneUtility.CloneRunItems(RunItems)
};
}
public RunNodeCompletionSnapshot CreateCompletionSnapshot(BackpackInventoryData inventorySnapshot)
{
return new RunNodeCompletionSnapshot
{
InventorySnapshot = InventoryCloneUtility.CloneInventory(inventorySnapshot),
ThemeType = ThemeType,
ThemeStageIndex = ThemeStageIndex,
CurrentThemePool = RunStateCloneUtility.CloneThemeList(CurrentThemePool),
ThemeHistory = RunStateCloneUtility.CloneThemeList(ThemeHistory),
CurrentNodeContinueChallengeLayer = CurrentNodeContinueChallengeLayer,
RunItems = RunStateCloneUtility.CloneRunItems(RunItems)
};
}
}
[Serializable]
public sealed class RunNodeCompletionSnapshot
{
public BackpackInventoryData InventorySnapshot { get; set; }
public LevelThemeType ThemeType { get; set; }
public int ThemeStageIndex { get; set; }
public List<LevelThemeType> CurrentThemePool { get; set; } = new List<LevelThemeType>();
public List<LevelThemeType> ThemeHistory { get; set; } = new List<LevelThemeType>();
public int CurrentNodeContinueChallengeLayer { get; set; }
public List<RunItemState> RunItems { get; set; } = new List<RunItemState>();
public RunNodeCompletionSnapshot Clone()
{
return new RunNodeCompletionSnapshot
{
InventorySnapshot = InventoryCloneUtility.CloneInventory(InventorySnapshot),
ThemeType = ThemeType,
ThemeStageIndex = ThemeStageIndex,
CurrentThemePool = RunStateCloneUtility.CloneThemeList(CurrentThemePool),
ThemeHistory = RunStateCloneUtility.CloneThemeList(ThemeHistory),
CurrentNodeContinueChallengeLayer = CurrentNodeContinueChallengeLayer,
RunItems = RunStateCloneUtility.CloneRunItems(RunItems)
};
}
}
public static class RunStateCloneUtility
{
public static List<LevelThemeType> CloneThemeList(IReadOnlyList<LevelThemeType> source)
{
List<LevelThemeType> cloned = new List<LevelThemeType>();
if (source == null)
{
return cloned;
}
for (int i = 0; i < source.Count; i++)
{
cloned.Add(source[i]);
}
return cloned;
}
public static List<RunItemState> CloneRunItems(IReadOnlyList<RunItemState> source)
{
List<RunItemState> cloned = new List<RunItemState>();
if (source == null)
{
return cloned;
}
for (int i = 0; i < source.Count; i++)
{
RunItemState item = source[i];
if (item != null)
{
cloned.Add(item.Clone());
}
}
return cloned;
}
}
}

View File

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

View File

@ -1,9 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using GeometryTD.Definition; using GeometryTD.Core;
using UnityEngine; using UnityEngine;
namespace GeometryTD.Entity namespace GeometryTD.Core
{ {
public sealed class EnemyTagStatusRuntime public sealed class EnemyTagStatusRuntime
{ {

View File

@ -1,5 +1,4 @@
using System; using System;
using GeometryTD.Entity;
namespace GeometryTD.Core namespace GeometryTD.Core
{ {

View File

@ -1,5 +1,4 @@
using System; using System;
using GeometryTD.Entity;
using UnityEngine; using UnityEngine;
namespace GeometryTD.Core namespace GeometryTD.Core

View File

@ -1,5 +1,4 @@
using System; using System;
using GeometryTD.Entity;
namespace GeometryTD.Core namespace GeometryTD.Core
{ {

View File

@ -1,5 +1,4 @@
using System; using System;
using GeometryTD.Entity;
using UnityEngine; using UnityEngine;
namespace GeometryTD.Core namespace GeometryTD.Core

View File

@ -13,17 +13,10 @@ namespace GeometryTD.Core
return string.Empty; return string.Empty;
} }
if (GameEntry.DataTable != null) DRTag tagRow = CoreServiceHub.StaticData.GetTag((int)tagType);
if (tagRow != null && !string.IsNullOrWhiteSpace(tagRow.Name))
{ {
var tagTable = GameEntry.DataTable.GetDataTable<DRTag>(); return tagRow.Name;
if (tagTable != null)
{
DRTag tagRow = tagTable.GetDataRow((int)tagType);
if (tagRow != null && !string.IsNullOrWhiteSpace(tagRow.Name))
{
return tagRow.Name;
}
}
} }
return tagType.ToString(); return tagType.ToString();

View File

@ -1,6 +1,5 @@
using GameFramework; using GameFramework;
using GameFramework.Event; using GameFramework.Event;
using GeometryTD.Procedure;
namespace GeometryTD.Core namespace GeometryTD.Core
{ {

View File

@ -1,6 +1,5 @@
using GameFramework; using GameFramework;
using GameFramework.Event; using GameFramework.Event;
using GeometryTD.Procedure;
namespace GeometryTD.Core namespace GeometryTD.Core
{ {

View File

@ -50,8 +50,6 @@ namespace GeometryTD.Procedure
GameEntry.Event.Subscribe(LoadConfigFailureEventArgs.EventId, OnLoadConfigFailure); GameEntry.Event.Subscribe(LoadConfigFailureEventArgs.EventId, OnLoadConfigFailure);
GameEntry.Event.Subscribe(LoadDataTableSuccessEventArgs.EventId, OnLoadDataTableSuccess); GameEntry.Event.Subscribe(LoadDataTableSuccessEventArgs.EventId, OnLoadDataTableSuccess);
GameEntry.Event.Subscribe(LoadDataTableFailureEventArgs.EventId, OnLoadDataTableFailure); GameEntry.Event.Subscribe(LoadDataTableFailureEventArgs.EventId, OnLoadDataTableFailure);
GameEntry.Event.Subscribe(LoadDictionarySuccessEventArgs.EventId, OnLoadDictionarySuccess);
GameEntry.Event.Subscribe(LoadDictionaryFailureEventArgs.EventId, OnLoadDictionaryFailure);
_loadedFlag.Clear(); _loadedFlag.Clear();
@ -64,8 +62,6 @@ namespace GeometryTD.Procedure
GameEntry.Event.Unsubscribe(LoadConfigFailureEventArgs.EventId, OnLoadConfigFailure); GameEntry.Event.Unsubscribe(LoadConfigFailureEventArgs.EventId, OnLoadConfigFailure);
GameEntry.Event.Unsubscribe(LoadDataTableSuccessEventArgs.EventId, OnLoadDataTableSuccess); GameEntry.Event.Unsubscribe(LoadDataTableSuccessEventArgs.EventId, OnLoadDataTableSuccess);
GameEntry.Event.Unsubscribe(LoadDataTableFailureEventArgs.EventId, OnLoadDataTableFailure); GameEntry.Event.Unsubscribe(LoadDataTableFailureEventArgs.EventId, OnLoadDataTableFailure);
GameEntry.Event.Unsubscribe(LoadDictionarySuccessEventArgs.EventId, OnLoadDictionarySuccess);
GameEntry.Event.Unsubscribe(LoadDictionaryFailureEventArgs.EventId, OnLoadDictionaryFailure);
base.OnLeave(procedureOwner, isShutdown); base.OnLeave(procedureOwner, isShutdown);
} }
@ -97,9 +93,6 @@ namespace GeometryTD.Procedure
LoadDataTable(dataTableName); LoadDataTable(dataTableName);
} }
// Preload dictionaries
//LoadDictionary("Default");
// Preload fonts // Preload fonts
LoadFont("MainFont"); LoadFont("MainFont");
LoadTMPFont("MainTMPFont"); LoadTMPFont("MainTMPFont");
@ -119,13 +112,6 @@ namespace GeometryTD.Procedure
GameEntry.DataTable.LoadDataTable(dataTableName, dataTableAssetName, this); GameEntry.DataTable.LoadDataTable(dataTableName, dataTableAssetName, this);
} }
private void LoadDictionary(string dictionaryName)
{
string dictionaryAssetName = AssetUtility.GetDictionaryAsset(dictionaryName, false);
_loadedFlag.Add(dictionaryAssetName, false);
GameEntry.Localization.ReadData(dictionaryAssetName, this);
}
private void LoadFont(string fontName) private void LoadFont(string fontName)
{ {
_loadedFlag.Add(Utility.Text.Format("Font.{0}", fontName), false); _loadedFlag.Add(Utility.Text.Format("Font.{0}", fontName), false);
@ -209,29 +195,5 @@ namespace GeometryTD.Procedure
Log.Error("Can not load data table '{0}' from '{1}' with error message '{2}'.", ne.DataTableAssetName, Log.Error("Can not load data table '{0}' from '{1}' with error message '{2}'.", ne.DataTableAssetName,
ne.DataTableAssetName, ne.ErrorMessage); ne.DataTableAssetName, ne.ErrorMessage);
} }
private void OnLoadDictionarySuccess(object sender, GameEventArgs e)
{
LoadDictionarySuccessEventArgs ne = (LoadDictionarySuccessEventArgs)e;
if (ne.UserData != this)
{
return;
}
_loadedFlag[ne.DictionaryAssetName] = true;
Log.Info("Load dictionary '{0}' OK.", ne.DictionaryAssetName);
}
private void OnLoadDictionaryFailure(object sender, GameEventArgs e)
{
LoadDictionaryFailureEventArgs ne = (LoadDictionaryFailureEventArgs)e;
if (ne.UserData != this)
{
return;
}
Log.Error("Can not load dictionary '{0}' from '{1}' with error message '{2}'.", ne.DictionaryAssetName,
ne.DictionaryAssetName, ne.ErrorMessage);
}
} }
} }

View File

@ -1,20 +1,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using GeometryTD.CustomUtility; using GeometryTD.Core;
using GeometryTD.Definition;
using GeometryTD.Factory; using GeometryTD.Factory;
namespace GeometryTD.Procedure namespace GeometryTD.Procedure
{ {
public enum RunNodeType
{
None = 0,
Combat = 1,
Event = 2,
Shop = 3,
BossCombat = 4
}
public enum RunNodeStatus public enum RunNodeStatus
{ {
Locked = 0, Locked = 0,
@ -24,13 +14,6 @@ namespace GeometryTD.Procedure
Skipped = 4 Skipped = 4
} }
public enum RunNodeCompletionStatus
{
None = 0,
Completed = 1,
Exception = 2
}
[Serializable] [Serializable]
public sealed class RunNodeSeed public sealed class RunNodeSeed
{ {
@ -65,96 +48,6 @@ namespace GeometryTD.Procedure
} }
} }
[Serializable]
public sealed class RunItemState
{
public int ItemId { get; set; }
public int StackCount { get; set; }
internal RunItemState Clone()
{
return new RunItemState
{
ItemId = ItemId,
StackCount = StackCount
};
}
}
[Serializable]
public sealed class RunNodeExecutionContext
{
public string RunId { get; set; }
public int RunSeed { get; set; }
public int NodeId { get; set; }
public RunNodeType NodeType { get; set; }
public int SequenceIndex { get; set; }
public LevelThemeType ThemeType { get; set; }
public int ThemeStageIndex { get; set; }
public List<LevelThemeType> CurrentThemePool { get; set; } = new List<LevelThemeType>();
public List<LevelThemeType> ThemeHistory { get; set; } = new List<LevelThemeType>();
public int CurrentNodeContinueChallengeLayer { get; set; }
public List<RunItemState> RunItems { get; set; } = new List<RunItemState>();
internal RunNodeExecutionContext Clone()
{
return new RunNodeExecutionContext
{
RunId = RunId,
RunSeed = RunSeed,
NodeId = NodeId,
NodeType = NodeType,
SequenceIndex = SequenceIndex,
ThemeType = ThemeType,
ThemeStageIndex = ThemeStageIndex,
CurrentThemePool = RunStateCloneUtility.CloneThemeList(CurrentThemePool),
ThemeHistory = RunStateCloneUtility.CloneThemeList(ThemeHistory),
CurrentNodeContinueChallengeLayer = CurrentNodeContinueChallengeLayer,
RunItems = RunStateCloneUtility.CloneRunItems(RunItems)
};
}
public RunNodeCompletionSnapshot CreateCompletionSnapshot(BackpackInventoryData inventorySnapshot)
{
return new RunNodeCompletionSnapshot
{
InventorySnapshot = InventoryCloneUtility.CloneInventory(inventorySnapshot),
ThemeType = ThemeType,
ThemeStageIndex = ThemeStageIndex,
CurrentThemePool = RunStateCloneUtility.CloneThemeList(CurrentThemePool),
ThemeHistory = RunStateCloneUtility.CloneThemeList(ThemeHistory),
CurrentNodeContinueChallengeLayer = CurrentNodeContinueChallengeLayer,
RunItems = RunStateCloneUtility.CloneRunItems(RunItems)
};
}
}
[Serializable]
public sealed class RunNodeCompletionSnapshot
{
public BackpackInventoryData InventorySnapshot { get; set; }
public LevelThemeType ThemeType { get; set; }
public int ThemeStageIndex { get; set; }
public List<LevelThemeType> CurrentThemePool { get; set; } = new List<LevelThemeType>();
public List<LevelThemeType> ThemeHistory { get; set; } = new List<LevelThemeType>();
public int CurrentNodeContinueChallengeLayer { get; set; }
public List<RunItemState> RunItems { get; set; } = new List<RunItemState>();
internal RunNodeCompletionSnapshot Clone()
{
return new RunNodeCompletionSnapshot
{
InventorySnapshot = InventoryCloneUtility.CloneInventory(InventorySnapshot),
ThemeType = ThemeType,
ThemeStageIndex = ThemeStageIndex,
CurrentThemePool = RunStateCloneUtility.CloneThemeList(CurrentThemePool),
ThemeHistory = RunStateCloneUtility.CloneThemeList(ThemeHistory),
CurrentNodeContinueChallengeLayer = CurrentNodeContinueChallengeLayer,
RunItems = RunStateCloneUtility.CloneRunItems(RunItems)
};
}
}
[Serializable] [Serializable]
public sealed class RunState public sealed class RunState
{ {
@ -314,42 +207,4 @@ namespace GeometryTD.Procedure
} }
} }
internal static class RunStateCloneUtility
{
internal static List<LevelThemeType> CloneThemeList(IReadOnlyList<LevelThemeType> source)
{
List<LevelThemeType> cloned = new List<LevelThemeType>();
if (source == null)
{
return cloned;
}
for (int i = 0; i < source.Count; i++)
{
cloned.Add(source[i]);
}
return cloned;
}
internal static List<RunItemState> CloneRunItems(IReadOnlyList<RunItemState> source)
{
List<RunItemState> cloned = new List<RunItemState>();
if (source == null)
{
return cloned;
}
for (int i = 0; i < source.Count; i++)
{
RunItemState item = source[i];
if (item != null)
{
cloned.Add(item.Clone());
}
}
return cloned;
}
}
} }

View File

@ -1,5 +1,5 @@
using GeometryTD.Core;
using GeometryTD.Definition; using GeometryTD.Definition;
using GeometryTD.Procedure;
using UnityGameFramework.Runtime; using UnityGameFramework.Runtime;
namespace GeometryTD.UI namespace GeometryTD.UI
@ -7,15 +7,15 @@ namespace GeometryTD.UI
public class EventFormUseCase : IUIUseCase public class EventFormUseCase : IUIUseCase
{ {
private EventItem _currentEvent; private EventItem _currentEvent;
private RunNodeExecutionContext _currentContext; private EventOptionExecutionContext _currentContext;
private readonly EventOptionExecutor _executor = new EventOptionExecutor(); private readonly EventOptionExecutor _executor = new EventOptionExecutor();
public void BindEvent( public void BindEvent(
EventItem eventItem, EventItem eventItem,
RunNodeExecutionContext context) EventOptionExecutionContext context)
{ {
_currentEvent = eventItem; _currentEvent = eventItem;
_currentContext = context != null ? context.Clone() : null; _currentContext = context;
} }
public void Clear() public void Clear()

View File

@ -15,12 +15,6 @@ namespace GeometryTD.Core
return Utility.Text.Format("Assets/GameMain/DataTables/{0}.{1}", assetName, fromBytes ? "bytes" : "txt"); return Utility.Text.Format("Assets/GameMain/DataTables/{0}.{1}", assetName, fromBytes ? "bytes" : "txt");
} }
public static string GetDictionaryAsset(string assetName, bool fromBytes)
{
return Utility.Text.Format("Assets/GameMain/Localization/{0}/Dictionaries/{1}.{2}",
GameEntry.Localization.Language, assetName, fromBytes ? "bytes" : "xml");
}
public static string GetFontAsset(string assetName) public static string GetFontAsset(string assetName)
{ {
return Utility.Text.Format("Assets/GameMain/Fonts/{0}.ttf", assetName); return Utility.Text.Format("Assets/GameMain/Fonts/{0}.ttf", assetName);

View File

@ -121,7 +121,7 @@ namespace GeometryTD.Core
private static void TryRefreshRangesFromDataTables() private static void TryRefreshRangesFromDataTables()
{ {
if (GameEntry.DataTable == null) if (CoreServiceHub.StaticData == null)
{ {
return; return;
} }
@ -154,13 +154,7 @@ namespace GeometryTD.Core
attackDamageRange = _attackDamageRange; attackDamageRange = _attackDamageRange;
damageRandomRateRange = _damageRandomRateRange; damageRandomRateRange = _damageRandomRateRange;
IDataTable<DRMuzzleComp> dataTable = GameEntry.DataTable.GetDataTable<DRMuzzleComp>(); DRMuzzleComp[] rows = CoreServiceHub.StaticData.GetAllMuzzleComps();
if (dataTable == null || dataTable.Count <= 0)
{
return false;
}
DRMuzzleComp[] rows = dataTable.GetAllDataRows();
if (rows == null || rows.Length <= 0) if (rows == null || rows.Length <= 0)
{ {
return false; return false;
@ -201,13 +195,7 @@ namespace GeometryTD.Core
rotateSpeedRange = _rotateSpeedRange; rotateSpeedRange = _rotateSpeedRange;
attackRangeRange = _attackRangeRange; attackRangeRange = _attackRangeRange;
IDataTable<DRBearingComp> dataTable = GameEntry.DataTable.GetDataTable<DRBearingComp>(); DRBearingComp[] rows = CoreServiceHub.StaticData.GetAllBearingComps();
if (dataTable == null || dataTable.Count <= 0)
{
return false;
}
DRBearingComp[] rows = dataTable.GetAllDataRows();
if (rows == null || rows.Length <= 0) if (rows == null || rows.Length <= 0)
{ {
return false; return false;
@ -246,13 +234,7 @@ namespace GeometryTD.Core
{ {
attackSpeedRange = _attackSpeedRange; attackSpeedRange = _attackSpeedRange;
IDataTable<DRBaseComp> dataTable = GameEntry.DataTable.GetDataTable<DRBaseComp>(); DRBaseComp[] rows = CoreServiceHub.StaticData.GetAllBaseComps();
if (dataTable == null || dataTable.Count <= 0)
{
return false;
}
DRBaseComp[] rows = dataTable.GetAllDataRows();
if (rows == null || rows.Length <= 0) if (rows == null || rows.Length <= 0)
{ {
return false; return false;

View File

@ -0,0 +1,109 @@
using System.Collections.Generic;
using UnityEngine;
namespace GeometryTD.Core
{
public static class InventoryTowerEnduranceUtility
{
public static int ReduceTowerEndurance(
BackpackInventoryData inventory,
IReadOnlyList<long> towerInstanceIds,
float enduranceLoss)
{
float resolvedLoss = Mathf.Max(0f, enduranceLoss);
if (inventory?.Towers == null ||
inventory.Towers.Count <= 0 ||
resolvedLoss <= 0f ||
towerInstanceIds == null ||
towerInstanceIds.Count <= 0)
{
return 0;
}
Dictionary<long, MuzzleCompItemData> muzzleMap = BuildComponentMap(inventory.MuzzleComponents);
Dictionary<long, BearingCompItemData> bearingMap = BuildComponentMap(inventory.BearingComponents);
Dictionary<long, BaseCompItemData> baseMap = BuildComponentMap(inventory.BaseComponents);
HashSet<long> processedTowerIds = new HashSet<long>();
int affectedCount = 0;
for (int i = 0; i < towerInstanceIds.Count; i++)
{
long towerInstanceId = towerInstanceIds[i];
if (towerInstanceId <= 0 || !processedTowerIds.Add(towerInstanceId))
{
continue;
}
if (!InventoryParticipantUtility.TryGetTowerById(inventory, towerInstanceId, out TowerItemData tower) ||
tower == null)
{
continue;
}
bool towerAffected = false;
if (muzzleMap.TryGetValue(tower.MuzzleComponentInstanceId, out MuzzleCompItemData muzzleComp))
{
towerAffected |= TryReduceComponentEndurance(muzzleComp, resolvedLoss);
}
if (bearingMap.TryGetValue(tower.BearingComponentInstanceId, out BearingCompItemData bearingComp))
{
towerAffected |= TryReduceComponentEndurance(bearingComp, resolvedLoss);
}
if (baseMap.TryGetValue(tower.BaseComponentInstanceId, out BaseCompItemData baseComp))
{
towerAffected |= TryReduceComponentEndurance(baseComp, resolvedLoss);
}
if (towerAffected)
{
affectedCount++;
}
}
return affectedCount;
}
private static bool TryReduceComponentEndurance(TowerCompItemData component, float enduranceLoss)
{
if (component == null)
{
return false;
}
float originalEndurance = component.Endurance;
float nextEndurance = Mathf.Clamp(originalEndurance - Mathf.Max(0f, enduranceLoss), 0f, 100f);
if (nextEndurance >= originalEndurance)
{
return false;
}
component.Endurance = nextEndurance;
return true;
}
private static Dictionary<long, TComp> BuildComponentMap<TComp>(List<TComp> components)
where TComp : TowerCompItemData
{
Dictionary<long, TComp> map = new Dictionary<long, TComp>();
if (components == null || components.Count <= 0)
{
return map;
}
for (int i = 0; i < components.Count; i++)
{
TComp component = components[i];
if (component == null || component.InstanceId <= 0)
{
continue;
}
map[component.InstanceId] = component;
}
return map;
}
}
}

View File

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

View File

@ -1,7 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using GameFramework.DataTable;
using GeometryTD.Core;
using UnityEngine; using UnityEngine;
using Random = System.Random; using Random = System.Random;
@ -9,9 +7,11 @@ namespace GeometryTD.Core
{ {
public static class ShopPriceRuleService public static class ShopPriceRuleService
{ {
public static int ResolveRandomBuyPrice(IReadOnlyList<DRShopPrice> shopPriceRows, RarityType rarity, Random random) private static Dictionary<RarityType, DRShopPrice> _shopPriceByRarity;
public static int ResolveRandomBuyPrice(RarityType rarity, Random random)
{ {
if (!TryFindPriceRow(shopPriceRows, rarity, out DRShopPrice row) || row == null) if (!TryFindPriceRow(rarity, out DRShopPrice row) || row == null)
{ {
return 0; return 0;
} }
@ -21,21 +21,20 @@ namespace GeometryTD.Core
return random != null ? random.Next(min, max + 1) : min; return random != null ? random.Next(min, max + 1) : min;
} }
public static int ResolveComponentSalePrice(TowerCompItemData component, IDataTable<DRShopPrice> shopPriceTable = null) public static int ResolveComponentSalePrice(TowerCompItemData component)
{ {
if (component == null) if (component == null)
{ {
return 0; return 0;
} }
return ResolveBasePrice(component.Rarity, shopPriceTable); return ResolveBasePrice(component.Rarity);
} }
public static bool TryResolveTowerSalePrice( public static bool TryResolveTowerSalePrice(
TowerItemData tower, TowerItemData tower,
BackpackInventoryData inventory, BackpackInventoryData inventory,
out int price, out int price)
IDataTable<DRShopPrice> shopPriceTable = null)
{ {
price = 0; price = 0;
if (tower == null || inventory == null) if (tower == null || inventory == null)
@ -50,22 +49,15 @@ namespace GeometryTD.Core
return false; return false;
} }
price = ResolveComponentSalePrice(muzzleComp, shopPriceTable) + price = ResolveComponentSalePrice(muzzleComp) +
ResolveComponentSalePrice(bearingComp, shopPriceTable) + ResolveComponentSalePrice(bearingComp) +
ResolveComponentSalePrice(baseComp, shopPriceTable); ResolveComponentSalePrice(baseComp);
return price > 0; return price > 0;
} }
public static int ResolveBasePrice(RarityType rarity, IDataTable<DRShopPrice> shopPriceTable = null) public static int ResolveBasePrice(RarityType rarity)
{ {
IDataTable<DRShopPrice> resolvedTable = shopPriceTable ?? GameEntry.DataTable.GetDataTable<DRShopPrice>(); if (!TryFindPriceRow(rarity, out DRShopPrice row) || row == null)
if (resolvedTable == null)
{
return 0;
}
DRShopPrice[] rows = resolvedTable.GetAllDataRows();
if (!TryFindPriceRow(rows, rarity, out DRShopPrice row) || row == null)
{ {
return 0; return 0;
} }
@ -75,25 +67,49 @@ namespace GeometryTD.Core
return Mathf.RoundToInt((min + max) * 0.5f); return Mathf.RoundToInt((min + max) * 0.5f);
} }
private static bool TryFindPriceRow(IReadOnlyList<DRShopPrice> rows, RarityType rarity, out DRShopPrice result) public static void ClearCache()
{ {
result = null; _shopPriceByRarity = null;
if (rows == null) }
private static bool TryFindPriceRow(RarityType rarity, out DRShopPrice result)
{
EnsureShopPriceCache();
if (_shopPriceByRarity == null)
{ {
result = null;
return false; return false;
} }
for (int i = 0; i < rows.Count; i++) return _shopPriceByRarity.TryGetValue(rarity, out result);
}
private static void EnsureShopPriceCache()
{
if (_shopPriceByRarity != null)
{ {
DRShopPrice row = rows[i]; return;
if (row != null && row.Rarity == rarity)
{
result = row;
return true;
}
} }
return false; DRShopPrice[] rows = CoreServiceHub.StaticData?.GetAllShopPrices();
if (rows == null)
{
return;
}
Dictionary<RarityType, DRShopPrice> shopPriceByRarity = new Dictionary<RarityType, DRShopPrice>();
for (int i = 0; i < rows.Length; i++)
{
DRShopPrice row = rows[i];
if (row == null)
{
continue;
}
shopPriceByRarity[row.Rarity] = row;
}
_shopPriceByRarity = shopPriceByRarity;
} }
private static bool TryGetComponentById<TComp>(IReadOnlyList<TComp> components, long instanceId, out TComp result) private static bool TryGetComponentById<TComp>(IReadOnlyList<TComp> components, long instanceId, out TComp result)

View File

@ -13,9 +13,9 @@ namespace GeometryTD.Core
private static Sprite _muzzleSprite; private static Sprite _muzzleSprite;
private static Sprite _bearingSprite; private static Sprite _bearingSprite;
private static Sprite _baseSprite; private static Sprite _baseSprite;
private static bool s_RequestedMuzzle; private static bool _requestedMuzzle;
private static bool s_RequestedBearing; private static bool _requestedBearing;
private static bool s_RequestedBase; private static bool _requestedBase;
public static Sprite ResolveTowerIconSprite( public static Sprite ResolveTowerIconSprite(
TowerItemData tower, TowerItemData tower,
@ -103,27 +103,22 @@ namespace GeometryTD.Core
private static void EnsureBaseSpritesRequested() private static void EnsureBaseSpritesRequested()
{ {
if (GameEntry.SpriteCache == null) if (!_requestedMuzzle)
{ {
return; _requestedMuzzle = true;
CoreServiceHub.SpriteCache.Get(MuzzleAssetName, sprite => { _muzzleSprite = sprite; });
} }
if (!s_RequestedMuzzle) if (!_requestedBearing)
{ {
s_RequestedMuzzle = true; _requestedBearing = true;
GameEntry.SpriteCache.GetSprite(MuzzleAssetName, sprite => { _muzzleSprite = sprite; }); CoreServiceHub.SpriteCache.Get(BearingAssetName, sprite => { _bearingSprite = sprite; });
} }
if (!s_RequestedBearing) if (!_requestedBase)
{ {
s_RequestedBearing = true; _requestedBase = true;
GameEntry.SpriteCache.GetSprite(BearingAssetName, sprite => { _bearingSprite = sprite; }); CoreServiceHub.SpriteCache.Get(BaseAssetName, sprite => { _baseSprite = sprite; });
}
if (!s_RequestedBase)
{
s_RequestedBase = true;
GameEntry.SpriteCache.GetSprite(BaseAssetName, sprite => { _baseSprite = sprite; });
} }
} }
} }

View File

@ -194,7 +194,7 @@ namespace GeometryTD.Tests.EditMode
new AddRandomCompsEffect(new AddRandomCompsParam(2, RarityType.Blue)) new AddRandomCompsEffect(new AddRandomCompsParam(2, RarityType.Blue))
}) })
}); });
RunNodeExecutionContext context = CreateContext(); EventOptionExecutionContext context = CreateContext();
BackpackInventoryData firstInventory = new BackpackInventoryData(); BackpackInventoryData firstInventory = new BackpackInventoryData();
BackpackInventoryData secondInventory = new BackpackInventoryData(); BackpackInventoryData secondInventory = new BackpackInventoryData();
@ -407,7 +407,7 @@ namespace GeometryTD.Tests.EditMode
BindingFlags.Instance | BindingFlags.NonPublic); BindingFlags.Instance | BindingFlags.NonPublic);
Assert.That(method, Is.Not.Null); Assert.That(method, Is.Not.Null);
RunNodeExecutionContext context = CreateContext(); RunNodeExecutionContext context = CreateRunNodeContext();
EventItem first = (EventItem)method.Invoke(component, new object[] { context }); EventItem first = (EventItem)method.Invoke(component, new object[] { context });
EventItem second = (EventItem)method.Invoke(component, new object[] { context }); EventItem second = (EventItem)method.Invoke(component, new object[] { context });
@ -437,7 +437,14 @@ namespace GeometryTD.Tests.EditMode
SetStaticInventoryGeneration(component); SetStaticInventoryGeneration(component);
} }
private static RunNodeExecutionContext CreateContext() private static EventOptionExecutionContext CreateContext()
{
return new EventOptionExecutionContext(
runSeed: 12345,
sequenceIndex: 3);
}
private static RunNodeExecutionContext CreateRunNodeContext()
{ {
return new RunNodeExecutionContext return new RunNodeExecutionContext
{ {

View File

@ -10,7 +10,7 @@
"GeometryTD.Gameplay" "GeometryTD.Gameplay"
], ],
"includePlatforms": [ "includePlatforms": [
"Editor" "Android"
], ],
"excludePlatforms": [], "excludePlatforms": [],
"allowUnsafeCode": false, "allowUnsafeCode": false,

View File

@ -1,7 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using CustomComponent;
using GeometryTD.CustomComponent;
using GeometryTD.Core; using GeometryTD.Core;
using GeometryTD.Factory; using GeometryTD.Factory;
using GeometryTD.Procedure; using GeometryTD.Procedure;