///// PUBLIC FUNCTIONS /// <summary> /// Initilize this chunk controller for it's provided level. /// </summary> public void initialize() { if (chunkObjectPrefab == null) { Debug.LogError("UnityLevelController Missing chunk prefab, can't work"); } else if (level == null) { Debug.LogError("No level provided by world. Did you hook this level controller up to the world controller?"); } else { chunkControllerActivationQueue = new ConcurrentQueue <UnityChunkController>(); loadedChunkLocations = new ConcurrentBag <Vector3>(); chunkControllerPool = new UnityChunkController[Level <IVoxelStorage> .MeshedChunkDiameter * Level <IVoxelStorage> .MeshedChunkDiameter * level.chunkBounds.y]; isLoaded = true; for (int index = 0; index < chunkControllerPool.Length; index++) { // for each chunk we want to be able to render at once, create a new pooled gameobject for it with the prefab that has a unitu chunk controller on it GameObject chunkObject = Instantiate(chunkObjectPrefab); chunkObject.transform.parent = gameObject.transform; UnityChunkController chunkController = chunkObject.GetComponent <UnityChunkController>(); if (chunkController == null) { Debug.LogError($"No chunk controller on {chunkObject.name}"); } else { chunkControllerPool[index] = chunkController; chunkController.levelController = this; chunkObject.SetActive(false); } } } }
/// <summary> /// Get notifications from other observers, EX: /// block breaking and placing /// player chunk location changes /// </summary> /// <param name="event">The event to notify this observer of</param> /// <param name="origin">(optional) the source of the event</param> public void notifyOf(IEvent @event, IObserver origin = null) { // ignore events if we have no level to control if (!isLoaded || level == null) { return; } switch (@event) { // when a player spawns in the level case Player.SpawnEvent pse: level.initializeAround(pse.spawnLocation.toChunkLocation()); break; // When the player moves to a new chunk, adjust the loaded level focus case Player.ChangeChunkLocationEvent pccle: level.adjustFocusTo(pccle.newChunkLocation); break; // when the level finishes loading a chunk's mesh. Render it in world case Level <VoxelDictionary> .ChunkMeshGenerationFinishedEvent lcmgfe: UnityChunkController unusedChunkController = getUnusedChunkController(); if (unusedChunkController == null) { Debug.LogError($"No free chunk controller found for {lcmgfe.chunkLocation.ToString()}"); } else { IVoxelChunk chunk = level.getChunk(lcmgfe.chunkLocation, true); if (unusedChunkController.setChunkToRender(chunk, lcmgfe.chunkLocation.vec3)) { chunkControllerActivationQueue.Enqueue(unusedChunkController); } } break; case Level <VoxelDictionary> .ChunkDataLoadingFinishedEvent lcdlfe: loadedChunkLocations.Add(lcdlfe.chunkLocation.vec3); break; // ignore other events default: return; } }