public class BlockSpawnEntityRebirth : BlockMotionSensor { private int OwnerID = -1; private float _tickRate = 10UL; private int _maxSpawned = 1; private int _numberToSpawn = 1; private int _spawnRadius = 0; private int _spawnArea = 15; private string _entityGroup = ""; private string _signText = ""; private EntityAlive entityPlaced; public override void OnBlockPlaceBefore(WorldBase _world, ref BlockPlacement.Result _bpResult, EntityAlive _ea, GameRandom _rnd) { entityPlaced = _ea; } public override void Init() { base.Init(); if (Properties.Values.ContainsKey("TickRate")) Properties.ParseFloat("TickRate", ref _tickRate); if (Properties.Values.ContainsKey("MaxSpawned")) Properties.ParseInt("MaxSpawned", ref _maxSpawned); if (Properties.Values.ContainsKey("NumberToSpawn")) Properties.ParseInt("NumberToSpawn", ref _numberToSpawn); if (Properties.Values.ContainsKey("SpawnRadius")) Properties.ParseInt("SpawnRadius", ref _spawnRadius); if (Properties.Values.ContainsKey("SpawnArea")) Properties.ParseInt("SpawnArea", ref _spawnArea); if (Properties.Values.ContainsKey("EntityGroup")) _entityGroup = Properties.Values["EntityGroup"]; if (Properties.Values.ContainsKey("Config")) _signText = Properties.Values["Config"]; } public override string GetActivationText(WorldBase _world, BlockValue _blockValue, int _clrIdx, Vector3i _blockPos, EntityAlive _entityFocusing) { return ""; } public override bool CanPlaceBlockAt(WorldBase _world, int _clrIdx, Vector3i _blockPos, BlockValue _blockValue, bool _bOmitCollideCheck = false) { EntityPlayerLocal primaryPlayer = GameManager.Instance.World.GetPrimaryPlayer(); if (primaryPlayer != null) { } if (_blockPos.y > 253) { return false; } if (!GameManager.Instance.IsEditMode() && ((World)_world).IsWithinTraderArea(_blockPos)) { return false; } Block block = _blockValue.Block; return (!block.isMultiBlock || _blockPos.y + block.multiBlockPos.dim.y < 254) && (GameManager.Instance.IsEditMode() || _bOmitCollideCheck || !this.overlapsWithOtherBlock(_world, _clrIdx, _blockPos, _blockValue)); } private bool overlapsWithOtherBlock(WorldBase _world, int _clrIdx, Vector3i _blockPos, BlockValue _blockValue) { if (!this.isMultiBlock) { int type = _world.GetBlock(_clrIdx, _blockPos).type; return type != 0 && !Block.list[type].blockMaterial.IsGroundCover && !_world.IsWater(_blockPos); } byte rotation = _blockValue.rotation; for (int i = this.multiBlockPos.Length - 1; i >= 0; i--) { Vector3i pos = _blockPos + this.multiBlockPos.Get(i, _blockValue.type, (int)rotation); int type2 = _world.GetBlock(_clrIdx, pos).type; if (type2 != 0 && !Block.list[type2].blockMaterial.IsGroundCover && !_world.IsWater(pos)) { return true; } } return false; } public override void OnBlockAdded(WorldBase _world, Chunk _chunk, Vector3i _blockPos, BlockValue _blockValue) { //Log.Out("BlockSpawnEntityRebirth-OnBlockAdded _blockValue.rotation: " + _blockValue.rotation); //Log.Out("BlockSpawnEntityRebirth-OnBlockAdded 1"); base.OnBlockAdded(_world, _chunk, _blockPos, _blockValue); if (!SingletonMonoBehaviour.Instance.IsServer) return; if (GameManager.Instance.IsEditMode()) return; //Log.Out("BlockSpawnEntityRebirth-OnBlockAdded 2"); var entityId = -1; var text = RebirthUtilities.GetValueFromKey(_signText, "ec"); if (string.IsNullOrEmpty(text)) { //Log.Out("BlockSpawnEntityRebirth-OnBlockAdded 3"); var group = RebirthUtilities.GetValueFromKey(_signText, "eg"); if (string.IsNullOrEmpty(group)) { //Log.Out("BlockSpawnEntityRebirth-OnBlockAdded 4"); if (string.IsNullOrEmpty(_entityGroup)) { //Log.Out("BlockSpawnEntityRebirth-OnBlockAdded 5"); return; } group = _entityGroup; } var ClassID = 0; entityId = EntityGroups.GetRandomFromGroup(group, ref ClassID); if (entityId == 0) // Invalid group. { //Log.Out("BlockSpawnEntityRebirth-OnBlockAdded 6"); return; } } else { //Log.Out("BlockSpawnEntityRebirth-OnBlockAdded 7"); entityId = text.GetHashCode(); } // Match the rotation, and create the stub for the entity var entityCreationData = new EntityCreationData(); entityCreationData.id = -1; entityCreationData.entityClass = entityId; entityCreationData.pos = _blockPos.ToVector3() + new Vector3(0.5f, 0.25f, 0.5f); //Log.Out("BlockSpawnEntityRebirth-OnBlockAdded entityCreationData.rot.Y: " + entityCreationData.rot.y); // We need to check if this is a block entity or not, and match the rotation of the entity to the block, in case its a model preview. var rotation = new Vector3(0f, (float)(45f * (_blockValue.rotation & 3)), 0f); //Log.Out("BlockSpawnEntityRebirth-OnBlockAdded flRotY: " + flRotY); var blockEntity = _chunk.GetBlockEntity(_blockPos); if (blockEntity != null && blockEntity.bHasTransform) { //Log.Out("BlockSpawnEntityRebirth-OnBlockAdded 8"); //Log.Out("BlockSpawnEntityRebirth-OnBlockAdded blockEntity != null"); rotation = blockEntity.transform.rotation.eulerAngles; } entityCreationData.rot = rotation; _chunk.AddEntityStub(entityCreationData); //Log.Out("BlockSpawnEntityRebirth-OnBlockAdded entityCreationData.rot.Y 2: " + entityCreationData.rot.y); // We'll use the Meta value as the spawn counter. _blockValue.meta = 0; GameManager.Instance.World.SetBlockRPC(_blockPos, _blockValue); // Set up the tick delay to be pretty short, as we'll just destroy the block anyway. _world.GetWBT().AddScheduledBlockUpdate(0, _blockPos, blockID, (ulong)1UL); } private void DestroySelf(Vector3i _blockPos, BlockValue _blockValue) { var keep = RebirthUtilities.GetValueFromKey(_signText, "keep"); if (string.IsNullOrEmpty(keep)) DamageBlock(GameManager.Instance.World, 0, _blockPos, _blockValue, Block.list[_blockValue.type].MaxDamage, -1, null, false); else GameManager.Instance.World.GetWBT().AddScheduledBlockUpdate(0, _blockPos, blockID, (ulong)10000UL); } public void ApplySignData(EntityAlive entity, Vector3i _blockPos) { // Read the sign for expected values. var Task = RebirthUtilities.GetValueFromKey(_signText, "task"); var Buff = RebirthUtilities.GetValueFromKey(_signText, "buff"); var PathingCode = RebirthUtilities.GetValueFromKey(_signText, "pc"); var setLeader = RebirthUtilities.GetValueFromKey(_signText, "leader"); if (Task.ToLower() == "stay") { //Log.Out("BlockSpawnEntityRebirth-ApplySignData SET TO STAY"); entity.Buffs.SetCustomVar("CurrentOrder", (int)EntityUtilities.Orders.Stay); } if (Task.ToLower() == "wander") { entity.Buffs.AddBuff("buffOrderWander"); } if (Task.ToLower() == "guard") { entity.Buffs.AddBuff("buffOrderGuard"); } if (Task.ToLower() == "follow") { //Log.Out("BlockSpawnEntityRebirth-ApplySignData SET TO FOLLOW"); entity.Buffs.SetCustomVar("CurrentOrder", (int)EntityUtilities.Orders.Follow); } // Set up the pathing cube if available if (!string.IsNullOrEmpty(PathingCode)) { if (StringParsers.TryParseFloat(PathingCode, out var pathingCode)) entity.Buffs.SetCustomVar("PathingCode", pathingCode); } // We are using the tile entity to transfer the owner ID from the client to the player. var tileEntity = GameManager.Instance.World.GetTileEntity(0, _blockPos) as TileEntityPoweredTrigger; if (tileEntity != null) { var persistentPlayerList = GameManager.Instance.GetPersistentPlayerList(); var playerData = persistentPlayerList.GetPlayerData(tileEntity.GetOwner()); if (playerData != null) OwnerID = playerData.EntityId; // Set up ownership, but only after the entity is spawned. if (OwnerID > 0 && !string.IsNullOrEmpty(setLeader)) { /*EntityUtilities.SetLeaderAndOwner(entity.entityId, (int)OwnerID, false); //npc.currentOrder = (int)EntityUtilities.Orders.Follow; EntityPlayer player = entity.world.GetEntity(OwnerID) as EntityPlayer; if (player != null) { float NPCMode = player.Buffs.GetCustomVar("varNPCModMode"); if (NPCMode == 0) { entity.Buffs.AddBuff("buffNPCModFullControlMode"); } else { entity.Buffs.AddBuff("buffNPCModThreatControlMode"); } } RebirthManager.AddHire((int)OwnerID, entity.entityId, entity.EntityName, entity.EntityClass.entityClassName, entity.position, entity.rotation, new Vector3(0, 0, 0), new Vector3(0, 0, 0), 0, 0, 0, true ); */ } } } public override bool UpdateTick(WorldBase _world, int _clrIdx, Vector3i _blockPos, BlockValue _blockValue, bool _bRandomTick, ulong _ticksIfLoaded, GameRandom _rnd) { Vector3 myVector = new Vector3(1, 2, 1); if (SingletonMonoBehaviour.Instance.IsServer) { //Log.Out("BlockSpawnEntityRebirth-UpdateTick 1"); if (_blockValue.meta >= _maxSpawned) { //Log.Out("BlockSpawnEntityRebirth-UpdateTick 2"); DestroySelf(_blockPos, _blockValue); return false; } var chunkCluster = _world.ChunkClusters[_clrIdx]; if (chunkCluster == null) { //Log.Out("BlockSpawnEntityRebirth-UpdateTick 3"); return false; } if ((Chunk)chunkCluster.GetChunkFromWorldPos(_blockPos) == null) { //Log.Out("BlockSpawnEntityRebirth-UpdateTick 4"); return false; } var entityId = -1; var text = RebirthUtilities.GetValueFromKey(_signText, "ec"); if (string.IsNullOrEmpty(text)) { //Log.Out("BlockSpawnEntityRebirth-UpdateTick 5"); var group = RebirthUtilities.GetValueFromKey(_signText, "eg"); if (string.IsNullOrEmpty(group)) { //Log.Out("BlockSpawnEntityRebirth-UpdateTick 6"); if (string.IsNullOrEmpty(_entityGroup)) { //Log.Out("BlockSpawnEntityRebirth-UpdateTick 7"); DestroySelf(_blockPos, _blockValue); return false; } group = _entityGroup; } var ClassID = 0; entityId = EntityGroups.GetRandomFromGroup(group, ref ClassID); if (entityId == 0) // Invalid group. { //Log.Out("BlockSpawnEntityRebirth-UpdateTick 8"); // Destroy the block after creating the entity. DestroySelf(_blockPos, _blockValue); return false; } } else { //Log.Out("BlockSpawnEntityRebirth-UpdateTick 9"); entityId = text.GetHashCode(); } // Match the rotation of the block for the entity, so it faces in the same direction. var transformPos = _blockPos.ToVector3() + new Vector3(0.5f, 0.25f, 0.5f); if (_spawnRadius > 0) { //Log.Out("BlockSpawnEntityRebirth-UpdateTick 10"); var areaSize = new Vector3(_spawnArea, _spawnArea, _spawnArea); int x; int y; int z; if (!GameManager.Instance.World.FindRandomSpawnPointNearPosition(_blockPos, 15, out x, out y, out z, areaSize, true)) { //Log.Out("BlockSpawnEntityRebirth-UpdateTick 11"); return true; } transformPos.x = x; transformPos.y = y; transformPos.z = z; } // We need to check if this is a block entity or not, and match the rotation of the entity to the block, in case its a model preview. var rotation = new Vector3(0f, (float)(45f * (_blockValue.rotation & 3)), 0f); var blockEntity = ((Chunk)_world.GetChunkFromWorldPos(_blockPos)).GetBlockEntity(_blockPos); if (blockEntity != null && blockEntity.bHasTransform) { //Log.Out("BlockSpawnEntityRebirth-UpdateTick 12"); rotation = blockEntity.transform.rotation.eulerAngles; } var entity = EntityFactory.CreateEntity(entityId, transformPos, rotation) as EntityAlive; if (entity == null) { //Log.Out($"No entity created: {_signText}"); return false; } entity.SetSpawnerSource(EnumSpawnerSource.StaticSpawner); GameManager.Instance.World.SpawnEntityInWorld(entity); if (entity is EntityAliveV2) { ApplySignData(entity as EntityAlive, _blockPos); } /*var tileEntity = GameManager.Instance.World.GetTileEntity(0, _blockPos) as TileEntityPoweredTrigger; if (tileEntity != null) { //Log.Out("BlockSpawnEntityRebirth-UpdateTick 13"); var persistentPlayerList = GameManager.Instance.GetPersistentPlayerList(); var playerData = persistentPlayerList.GetPlayerData(tileEntity.GetOwner()); if (playerData != null) { //Log.Out("BlockSpawnEntityRebirth-UpdateTick 14"); //entity.Buffs.SetCustomVar("Owner", playerData.EntityId); //entity.Buffs.SetCustomVar("Leader", playerData.EntityId); //entity.Buffs.SetCustomVar("$FR_NPC_Stay", 1); } }*/ _blockValue.meta++; GameManager.Instance.World.SetBlockRPC(_blockPos, _blockValue); } //Log.Out("BlockSpawnEntityRebirth-UpdateTick 15"); DestroySelf(_blockPos, _blockValue); return true; } }