void GenerateGrid() { int spawnedStores = 0; GridData data = GridData.GetInstance(); while (spawnedStores < storeCount) { int x = UnityEngine.Random.Range(0, BoardWidth); int y = UnityEngine.Random.Range(0, BoardWidth); EntityInfo cellValue; data.gridStatus.TryGetValue(GridData.ConvertToHash(x, y), out cellValue); if (cellValue.type != (int)Tiles.Store) { cellValue = new EntityInfo { type = (int)Tiles.Store }; data.gridStatus.TryAdd(GridData.ConvertToHash(x, y), cellValue); Instantiate(StorePrefab, new Vector3(x, 2, y), Quaternion.identity); spawnedStores++; } } // FIX: This could maybe be parallelized? for (int i = 0; i < rockSpawnAttempts; i++) { TrySpawnRock(); } }
// rock spawner from the original sim // except currently spawns cubes rather // than rectangles void TrySpawnRock() { GridData data = GridData.GetInstance(); int width = UnityEngine.Random.Range(0, 4); int height = UnityEngine.Random.Range(0, 4); int rockX = UnityEngine.Random.Range(0, BoardWidth - width); int rockY = UnityEngine.Random.Range(0, BoardWidth - height); RectInt rect = new RectInt(rockX, rockY, width, height); bool blocked = false; for (int x = rockX; x <= rockX + width; x++) { for (int y = rockY; y <= rockY + height; y++) { EntityInfo tileValue; if (data.gridStatus.TryGetValue(GridData.ConvertToHash(x, y), out tileValue)) { blocked = true; break; } } if (blocked) { break; } } if (blocked == false) { //TODO: Combine rocks into groups for (int x = rockX; x <= rockX + width; x++) { for (int y = rockY; y <= rockY + height; y++) { // get some new rock entities and add them to an array // so we can find them later Entity tmp = entityManager.Instantiate(rockEntity); EntityInfo info = new EntityInfo { type = (int)Tiles.Rock, specificEntity = tmp }; data.gridStatus.TryAdd(GridData.ConvertToHash(x, y), info); //Debug.Log("entity info is: " + x + " " + y + " index: " + entityIndex + " " + tmp.Index); entityManager.SetComponentData(tmp, new Translation() { Value = new Unity.Mathematics.float3(x, height * 0.25f, y) }); } } } }
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { var translations = chunk.GetNativeArray(TranslationTypeHandle); var entityIntents = chunk.GetNativeArray(EntityInfoHandle); var entities = chunk.GetNativeArray(EntityType); for (var i = 0; i < chunk.Count; i++) { Tiles state = (Tiles)entityIntents[i].type; switch (state) { case Tiles.Rock: //Debug.Log("destroying rock"); // destroy rock addRemoveTags.Enqueue(new TagInfo { shouldRemove = 0, entity = entityIntents[i].specificEntity, type = Tags.Disable }); // remove perform task and add needs task tags addRemoveTags.Enqueue(new TagInfo { shouldRemove = 0, entity = entities[i], type = Tags.NeedsTask }); addRemoveTags.Enqueue(new TagInfo { shouldRemove = 1, entity = entities[i], type = Tags.PerformTask }); break; case Tiles.Till: float tillBlockHeight = 0.25f; EntityInfo tillInfo = new EntityInfo { type = (int)Tiles.Till }; if ( grid.TryAdd(GridData.ConvertToHash((int)translations[i].Value.x, (int)translations[i].Value.z), tillInfo)) { float3 pos = new float3((int)translations[i].Value.x, tillBlockHeight, (int)translations[i].Value.z); changes.Enqueue(new float2((int)pos.x, (int)pos.z)); } // add needs task and remove perform task tags addRemoveTags.Enqueue(new TagInfo { shouldRemove = 0, entity = entities[i], type = Tags.NeedsTask }); addRemoveTags.Enqueue(new TagInfo { shouldRemove = 1, entity = entities[i], type = Tags.PerformTask }); break; case Tiles.Plant: // since the plant needs to be instantiated and then cached // into the hash table it's done in the main thread // add needs task and remove perform task tags addRemoveTags.Enqueue(new TagInfo { shouldRemove = 0, entity = entities[i], type = Tags.NeedsTask }); addRemoveTags.Enqueue(new TagInfo { shouldRemove = 1, entity = entities[i], type = Tags.PerformTask }); break; case Tiles.Harvest: EntityInfo harvestInfo = new EntityInfo { type = (int)Tiles.Till }; if (plantInfo.HasComponent(entityIntents[i].specificEntity)) { PlantComponent plant = plantInfo[entityIntents[i].specificEntity]; if (plant.reserveIndex == entities[i].Index && grid.TryAdd( GridData.ConvertToHash((int)translations[i].Value.x, (int)translations[i].Value.z), harvestInfo)) { //UnityEngine.Debug.Log("harvesting : " + entityIntents[i].specificEntity.Index); // plant needs to follow the farmer PlantComponent plantData2 = new PlantComponent { timeGrown = plantGrowthMax, state = (int)PlantState.Following, farmerToFollow = entities[i], reserveIndex = plant.reserveIndex }; setInfo.Enqueue(new ComponentSetInfo { entity = entityIntents[i].specificEntity, plantComponent = plantData2 }); } else if (plant.reserveIndex != entities[i].Index) { entityIntents[i] = new EntityInfo { specificEntity = entityIntents[i].specificEntity, type = (short)Tiles.None }; } } else { entityIntents[i] = new EntityInfo { specificEntity = entityIntents[i].specificEntity, type = (short)Tiles.None }; } // remove perform task and add needs task addRemoveTags.Enqueue(new TagInfo { shouldRemove = 0, entity = entities[i], type = Tags.NeedsTask }); addRemoveTags.Enqueue(new TagInfo { shouldRemove = 1, entity = entities[i], type = Tags.PerformTask }); break; case Tiles.Store: // multiple entities can try to delete this plant at the store // the single threaded job at the end takes care of this // we need to remove the plant from the farmer PlantComponent plantData = new PlantComponent { timeGrown = plantGrowthMax, state = (int)PlantState.Deleted }; setInfo.Enqueue(new ComponentSetInfo { entity = entityIntents[i].specificEntity, plantComponent = plantData }); // remove perform task and add needs task tags addRemoveTags.Enqueue(new TagInfo { shouldRemove = 0, entity = entities[i], type = Tags.NeedsTask }); addRemoveTags.Enqueue(new TagInfo { shouldRemove = 1, entity = entities[i], type = Tags.PerformTask }); // and actually sell stuff here unsafe { Interlocked.Increment(ref ((int *)plantsSold.GetUnsafePtr())[0]); } break; default: break; } } }
// randomly determines a task and then finds the right tiles that // will help the task occur public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { var translations = chunk.GetNativeArray(TranslationTypeHandle); var movements = chunk.GetNativeArray(MovementTypeHandle); var entityIntents = chunk.GetNativeArray(EntityInfoHandle); var entities = chunk.GetNativeArray(EntityType); for (var i = 0; i < chunk.Count; i++) { // // determine what the task for this entity is // Tiles taskValue = (Tiles)(randArray[(nextIndex + entities[i].Index) % randArray.Length] % 4) + 1; nextIndex++; if (entityIntents[i].type == (int)Tiles.Harvest) { // we just harvested and now need to get the plant // to the store taskValue = Tiles.Store; } // // look for the best tile for performing that task // float2 pos = new float2(translations[i].Value.x, translations[i].Value.z); float2 foundLocation; switch (taskValue) { case Tiles.Rock: foundLocation = GridData.Search(randArray, nextIndex, gridHashMap, pos, radiusForSearch, (int)taskValue, gridSize, gridSize); nextIndex++; break; case Tiles.Till: // default is currently Till foundLocation = GridData.Search(randArray, nextIndex, gridHashMap, pos, radiusForSearch, 0, gridSize, gridSize); nextIndex++; if (foundLocation.x == -1) { foundLocation = GridData.Search(randArray, nextIndex, gridHashMap, pos, radiusForSearch * 3, 0, gridSize, gridSize); nextIndex++; } break; case Tiles.Plant: // need to search for tilled soil foundLocation = GridData.Search(randArray, nextIndex, gridHashMap, pos, radiusForSearch, (int)Tiles.Till, gridSize, gridSize); nextIndex++; if (foundLocation.x == -1) { foundLocation = GridData.Search(randArray, nextIndex, gridHashMap, pos, radiusForSearch * 3, (int)Tiles.Till, gridSize, gridSize); nextIndex++; } break; case Tiles.Harvest: // searches for the plants to go harvest them foundLocation = GridData.FindMaturePlant(randArray, nextIndex, gridHashMap, pos, radiusForSearch, (int)Tiles.Plant, gridSize, gridSize, ref IsPlantType, plantGrowthMax); nextIndex++; if (foundLocation.x == -1) { foundLocation = GridData.FindMaturePlant(randArray, nextIndex, gridHashMap, pos, radiusForSearch * 3, (int)Tiles.Plant, gridSize, gridSize, ref IsPlantType, plantGrowthMax); nextIndex++; } break; default: // searches for the stores to go and sell a plant foundLocation = GridData.Search(randArray, nextIndex, gridHashMap, pos, radiusForSearch, (int)Tiles.Store, gridSize, gridSize); nextIndex++; // no store close by if (foundLocation.x == -1) { // need to find somewhere to get rid of the plant foundLocation = GridData.Search(randArray, nextIndex, gridHashMap, pos, gridSize, (int)Tiles.Store, gridSize, gridSize); nextIndex++; } break; } //UnityEngine.Debug.Log("finding new task : " + taskValue + " for entity " + entities[i].Index + // " found " + foundLocation.x); // // If a tile was found, set up the data for the task // if there's a rock in the way, then just go break the rock // if (foundLocation.x != -1 && foundLocation.y != -1) { float2 findMiddle = MovementSystem.FindMiddlePos(pos, foundLocation); var rockPos = GridData.FindTheRock(gridHashMap, pos, findMiddle, foundLocation, gridSize, gridSize); //Debug.Log(index + " Start: " + pos.x + " " + pos.y + " middle : " + findMiddle.x + " " + findMiddle.y + " target pos : " + // foundLocation.x + " " + foundLocation.y + " " + rockPos + " intention: " + taskValue); if ((int)rockPos.x != -1 && (int)rockPos.y != -1) { // we found a rock so go mine it on the path // if rock position on an x or y direction then don't change the middle // otherwise re-find the middle if ((int)rockPos.x == (int)pos.x || (int)rockPos.y == (int)pos.y) { findMiddle = MovementSystem.FindMiddlePos(pos, rockPos); } //Debug.Log("Updated rock position to: " + rockPos + "Actor is now chasing a rock"); rockPos = new float2(rockPos.x + 0.5f, rockPos.y + 0.5f); var data = new MovementComponent { startPos = pos, speed = 2, targetPos = rockPos, middlePos = findMiddle, }; movements[i] = data; // if we are on the way to the store then destroy the plant and // mine the rock if (taskValue == Tiles.Store) { // destroy the plant as there's a rock in the way or no place to take it //UnityEngine.Debug.Log("plant should be destroyed on farmer"); PlantComponent plantInfo = new PlantComponent { timeGrown = plantGrowthMax, state = (int)PlantState.Deleted, }; setInfo.Enqueue(new ComponentSetInfo { entity = entityIntents[i].specificEntity, plantComponent = plantInfo }); } // get the index into the array of rocks so that we can find it // to destroy it EntityInfo fullRockData = GridData.getFullHashValue(gridHashMap, (int)rockPos.x, (int)rockPos.y); entityIntents[i] = fullRockData; //Debug.Log("rock task happening : " + rockEntityIndex + " " + tmp.Index); // remove needs task and add moving tag addRemoveTags.Enqueue(new TagInfo { shouldRemove = 1, entity = entities[i], type = Tags.NeedsTask }); addRemoveTags.Enqueue(new TagInfo { shouldRemove = 0, entity = entities[i], type = Tags.Moving }); int key = GridData.ConvertToHash((int)rockPos.x, (int)rockPos.y); removals.Enqueue(new RemovalInfo { key = key, requestingEntity = entities[i] }); } else { foundLocation = new float2(foundLocation.x + 0.5f, foundLocation.y + 0.5f); var data = new MovementComponent { startPos = pos, speed = 2, targetPos = foundLocation, middlePos = findMiddle, }; movements[i] = data; //Debug.Log("doing a task and about to move: " + pos.x + " " + pos.y + // " target is : " + data.targetPos.x + " " + data.targetPos.y); //Debug.Log("rock value: " + rockPos); // remove needs task and add moving tag addRemoveTags.Enqueue(new TagInfo { shouldRemove = 1, entity = entities[i], type = Tags.NeedsTask }); addRemoveTags.Enqueue(new TagInfo { shouldRemove = 0, entity = entities[i], type = Tags.Moving }); int key; switch (taskValue) { case Tiles.Rock: key = GridData.ConvertToHash((int)foundLocation.x, (int)foundLocation.y); // get the index into the array of rocks so that we can find it // to destroy it EntityInfo fullRockData = GridData.getFullHashValue(gridHashMap, (int)rockPos.x, (int)rockPos.y); //Debug.Log("rock task happening : " + rockEntityIndex + " " + tmp.Index); entityIntents[i] = fullRockData; // remove the rock from the hash so that nobody else tries to get it removals.Enqueue(new RemovalInfo { key = key, requestingEntity = entities[i] }); break; case Tiles.Till: EntityInfo tillData = new EntityInfo { type = (int)Tiles.Till }; entityIntents[i] = tillData; break; case Tiles.Plant: key = GridData.ConvertToHash((int)foundLocation.x, (int)foundLocation.y); removals.Enqueue(new RemovalInfo { key = key, requestingEntity = entities[i] }); EntityInfo plantData = new EntityInfo { type = (int)Tiles.Plant }; entityIntents[i] = plantData; break; case Tiles.Harvest: key = GridData.ConvertToHash((int)foundLocation.x, (int)foundLocation.y); EntityInfo fullData = GridData.getFullHashValue(gridHashMap, (int)foundLocation.x, (int)foundLocation.y); // check to make sure plant is grown before harvesting // if it's not then find something else to do PlantComponent plantInfo = IsPlantType[fullData.specificEntity]; if (plantInfo.timeGrown >= plantGrowthMax) { removals.Enqueue(new RemovalInfo { key = key, requestingEntity = entities[i] }); EntityInfo harvestData = new EntityInfo { type = (int)Tiles.Harvest, specificEntity = fullData.specificEntity }; entityIntents[i] = harvestData; //Debug.Log("plant ready to harvest at : " + fullData.specificEntity.Index + " " + index + " " + // foundLocation.x + " " + foundLocation.y); } else { // not ready to harvest, try something else // add needs task and remove moving tag addRemoveTags.Enqueue(new TagInfo { shouldRemove = 0, entity = entities[i], type = Tags.NeedsTask }); addRemoveTags.Enqueue(new TagInfo { shouldRemove = 1, entity = entities[i], type = Tags.Moving }); } break; case Tiles.Store: EntityInfo storeInfo = new EntityInfo { type = (int)Tiles.Store, specificEntity = entityIntents[i].specificEntity }; entityIntents[i] = storeInfo; //Debug.Log("plant going to the store " + foundLocation.x + " " + foundLocation.y + " " + entityIntent.specificEntity.Index); break; default: break; } } } else { // no tile was found for the task, so this method // will run again and hopefully pick another task next time // Debug.Log("location wasn't found - find another task"); } } }