namespace Harmony.BlockSpawnEntityPatches { [HarmonyPatch(typeof(BlockSpawnEntity), "UpdateTick")] public class UpdateTickPatch { const float _maxDist = 2f; public static bool Prefix(BlockSpawnEntity __instance, ref bool __result, WorldBase _world, int _clrIdx, Vector3i _blockPos, BlockValue _blockValue, bool _bRandomTick, ulong _ticksIfLoaded, GameRandom _rnd) { //Log.Out($"BlockSpawnEntity::UpdateTick Prefix _blockValue: {_blockValue.Block.GetBlockName()}, pos: {_blockPos}, spawnClasses len: {__instance.spawnClasses.Length}"); __result = false; if (!SingletonMonoBehaviour.Instance.IsServer) return false; if (__instance.spawnClasses.Length == 0) { Log.Error($"Harmony-BlockSpawnEntity:Block definition '{_blockValue.Block.GetBlockName()}' missing property SpawnClass values in entityclasses.xml"); return false; } if (!GameManager.Instance.IsEditMode()) { string className = __instance.spawnClasses[_blockValue.meta % __instance.spawnClasses.Length]; //Log.Warning($"BlockSpawnEntityPatches-UpdateTick className: " + className); //Log.Warning($"BlockSpawnEntityPatches-UpdateTick Contains: " + className.ToLower().Contains("tradermercenary_poi")); bool flag1 = _blockValue.Block.blockName == "spawnTraderRebirth" && (className.ToLower() != "briston_poi_fr" && !className.ToLower().Contains("tradermercenary_poi")); bool flag2 = _blockValue.Block.blockName == "spawnCustomTraderRebirth" && !className.ToLower().Contains("poppy_poi_"); bool flag3 = _blockValue.Block.blockName == "spawnCustomTraderRebirth" && className.ToLower().Contains("poppy_poi_"); //Log.Warning($"BlockSpawnEntityPatches-UpdateTick flag1: " + flag1); //Log.Warning($"BlockSpawnEntityPatches-UpdateTick flag2: " + flag2); //Log.Warning($"BlockSpawnEntityPatches-UpdateTick flag3: " + flag3); if (RebirthUtilities.ScenarioSkip() && (flag1 || flag2) || !RebirthUtilities.ScenarioSkip() && (flag3) ) { //Log.Warning($"BlockSpawnEntityPatches-UpdateTick SKIP"); _world.GetWBT().AddScheduledBlockUpdate(0, _blockPos, __instance.blockID, 320uL); return false; } var entities = GameManager.Instance.World.GetEntitiesInBounds(null, new Bounds(_blockPos.ToVector3(), Vector3.one * 25f)); int eClassID = EntityClass.FromString(className); var matchedIDs = entities.FindAll(e => e.entityClass == eClassID); if (matchedIDs.Count == 0) { ChunkCluster chunkCluster = _world.ChunkClusters[_clrIdx]; if (chunkCluster == null || (Chunk)chunkCluster.GetChunkFromWorldPos(_blockPos) == null) return false; Vector3 transformPos = _blockPos.ToVector3() + new Vector3(0.5f, 0.25f, 0.5f); Vector3 rotation = new Vector3(0f, 90 * (_blockValue.rotation & 3), 0f); Entity entity = EntityFactory.CreateEntity(eClassID, transformPos, rotation); entity.SetSpawnerSource(EnumSpawnerSource.StaticSpawner); GameManager.Instance.World.SpawnEntityInWorld(entity); //Log.Warning($"Harmony-BlockSpawnEntity:Spawn New Trader entity: {entity}"); } else if (matchedIDs.Count == 1) { var trader = matchedIDs[0]; if (Vector3.Distance(_blockPos.ToVector3(), trader.position) > _maxDist) { //Log.Warning($"Harmony-BlockSpawnEntity:Repositioning Trader {_blockValue.Block.GetBlockName()}"); trader.SetPosition(_blockPos.ToVector3() + new Vector3(0.5f, 0.25f, 0.5f)); trader.SetRotation(new Vector3(0f, 90 * (_blockValue.rotation & 3), 0f)); } } else if (matchedIDs.Count >= 2) { //Log.Warning($"Harmony-BlockSpawnEntity:Found extra traders: {className} {matchedIDs.Count}"); for (int i = matchedIDs.Count - 1; i >= 0; i--) { var trader = matchedIDs[i]; var dist = Vector3.Distance(_blockPos.ToVector3(), trader.position); //Log.Warning($" Trader: {trader}, pos: {trader.position}, distance: {dist}"); if (dist > _maxDist) { //Log.Warning($"Harmony-BlockSpawnEntity:Unloading extra EntityTrader: {trader}, distance from post: {dist}"); trader.MarkToUnload(); matchedIDs.RemoveAt(i); } } if (matchedIDs.Count > 1) { //Log.Error($"Harmony-BlockSpawnEntity:Found an extra trader within the max distance."); // hope it doesn't happen } } } _world.GetWBT().AddScheduledBlockUpdate(0, _blockPos, __instance.blockID, 320uL); // the base Block class simply returns false return false; // base.UpdateTick(_world, _clrIdx, _blockPos, _blockValue, _bRandomTick, _ticksIfLoaded, _rnd); } } }