public VoxelInfo( Index setIndex, Index setAdjacentIndex, Chunk setChunk ) { this.index = setIndex; this.adjacentIndex = setAdjacentIndex; this.chunk = setChunk; }
public void Update() { // don't load chunks if engine isn't initialized yet if (!Engine.Initialized || !ChunkManager.Initialized) { return; } // don't load chunks if multiplayer is enabled but the connection isn't established yet if (Engine.EnableMultiplayer) { if (!Network.isClient && !Network.isServer) { return; } } // track which chunk we're currently in. If it's different from previous frame, spawn chunks at current position. currentPos = Engine.PositionToChunkIndex (transform.position); if (currentPos.IsEqual(LastPos) == false) { ChunkManager.SpawnChunks(currentPos.x, currentPos.y, currentPos.z); // (Multiplayer) update server position if (Engine.EnableMultiplayer && Engine.MultiplayerTrackPosition && Engine.UniblocksNetwork != null) { UniblocksClient.UpdatePlayerPosition (currentPos); } } LastPos = currentPos; }
// ==== maintenance =========================================================================================== public void Awake() { // chunk initialization (load/generate data, set position, etc.) // Set variables ChunkIndex = new Index (transform.position); SideLength = Engine.ChunkSideLength; SquaredSideLength = SideLength * SideLength; NeighborChunks = new Chunk [6]; // 0 = up, 1 = down, 2 = right, 3 = left, 4 = forward, 5 = back MeshCreator = GetComponent<ChunkMeshCreator>(); Fresh = true; // Register chunk ChunkManager.RegisterChunk (this); // Clear the voxel data VoxelData = new ushort[SideLength*SideLength*SideLength]; // Set actual position transform.position = ChunkIndex.ToVector3() * SideLength; // multiply by scale transform.position = new Vector3 (transform.position.x * transform.localScale.x, transform.position.y * transform.localScale.y, transform.position.z * transform.localScale.z); // Grab voxel data if (Engine.EnableMultiplayer && !Network.isServer) { StartCoroutine (RequestVoxelData()); // if multiplayer, get data from server } else if (Engine.SaveVoxelData && TryLoadVoxelData() == true ) { // data is loaded through TryLoadVoxelData() } else { GenerateVoxelData(); } }
public void Update() { // check if chunk is not null GameObject chunkObject = Engine.PositionToChunk (transform.position); if (chunkObject == null) return; // get the voxelInfo from the transform's position Chunk chunk = chunkObject.GetComponent<Chunk>(); Index voxelIndex = chunk.PositionToVoxelIndex (transform.position); VoxelInfo voxelInfo = new VoxelInfo (voxelIndex, chunk); // create a local copy of the collision voxel so we can call functions on it GameObject voxelObject = Instantiate ( Engine.GetVoxelGameObject (voxelInfo.GetVoxel()) ) as GameObject; VoxelEvents events = voxelObject.GetComponent<VoxelEvents>(); if (events != null ) { // OnEnter if ( chunk != LastChunk || voxelIndex.IsEqual(LastIndex) == false) { events.OnBlockEnter (this.gameObject, voxelInfo); } // OnStay else { events.OnBlockStay(this.gameObject, voxelInfo); } } LastChunk = chunk; LastIndex = voxelIndex; Destroy(voxelObject); }
public override void OnBlockDestroy( VoxelInfo voxelInfo ) { // if the block above is tall grass, destroy it Index indexAbove = new Index (voxelInfo.index.x, voxelInfo.index.y+1, voxelInfo.index.z); if ( voxelInfo.chunk.GetVoxel(indexAbove) == 8 ) { voxelInfo.chunk.SetVoxel(indexAbove, 0, true); } }
public static Chunk GetChunkComponent(Index index) { string indexString = index.ToString(); if ( ChunkManager.Chunks.ContainsKey (indexString) ) { return ChunkManager.Chunks [indexString]; } else { return null; } }
public override void OnBlockPlace( VoxelInfo voxelInfo ) { // if the block below is grass, change it to dirt Index indexBelow = new Index (voxelInfo.index.x, voxelInfo.index.y-1, voxelInfo.index.z); if ( voxelInfo.GetVoxelType ().VTransparency == Transparency.solid && voxelInfo.chunk.GetVoxel(indexBelow) == 2) { voxelInfo.chunk.SetVoxel(indexBelow, 1, true); } }
public static GameObject GetChunk(Index index) { Chunk chunk = ChunkManager.GetChunkComponent (index); if (chunk == null) { return null; } else { return chunk.gameObject; } }
public bool IsEqual( Index to ) { if (to == null) { return false; } if (this.x == to.x && this.y == to.y && this.z == to.z) { return true; } else return false; }
public static bool Compare( Index a, Index b ) { if (b == null) { return false; } if (a.x == b.x && a.y == b.y && a.z == b.z) { return true; } else return false; }
public void ReceiveChangeBlock( NetworkPlayer sender, int x, int y, int z, int chunkx, int chunky, int chunkz, int data ) { // receives a change sent by other client or server GameObject chunkObject = ChunkManager.GetChunk (chunkx,chunky,chunkz); if (chunkObject != null) { // convert back to VoxelInfo Index voxelIndex = new Index (x,y,z); VoxelInfo info = new VoxelInfo (voxelIndex, chunkObject.GetComponent<Chunk>()); // apply change Voxel.ChangeBlockMultiplayer (info, (ushort)data, sender); } }
public override void OnBlockPlace( VoxelInfo voxelInfo ) { // switch to dirt if the block above isn't 0 Index adjacentIndex = voxelInfo.chunk.GetAdjacentIndex (voxelInfo.index, Direction.up); if ( voxelInfo.chunk.GetVoxel(adjacentIndex) != 0 ) { voxelInfo.chunk.SetVoxel(voxelInfo.index, 1, true); } // if the block below is grass, change it to dirt Index indexBelow = new Index (voxelInfo.index.x, voxelInfo.index.y-1, voxelInfo.index.z); if ( voxelInfo.GetVoxelType ().VTransparency == Transparency.solid && voxelInfo.chunk.GetVoxel(indexBelow) == 2) { voxelInfo.chunk.SetVoxel(indexBelow, 1, true); } }
public void Update() { // track which chunk we're currently in. If it's different from previous frame, spawn chunks at current position. currentPos = Engine.PositionToChunkIndex (transform.position); if (currentPos.IsEqual(LastPos) == false) { ChunkManager.SpawnChunks(currentPos.x, currentPos.y, currentPos.z); // (Multiplayer) update server position if (Engine.EnableMultiplayer && Engine.MultiplayerTrackPosition && Engine.UniblocksNetwork != null) { UniblocksClient.UpdatePlayerPosition (currentPos); } } LastPos = currentPos; }
private static string GetRegionPath(Index regionIndex) { return Engine.WorldPath + ( regionIndex.ToString() + ",.region"); }
private static bool LoadRegionData(Index regionIndex) { // loads the region data into memory if file exists and it's not already loaded, returns true if data exists (and is loaded), else false string indexString = regionIndex.ToString(); if (LoadedRegions.ContainsKey(indexString) == false) { // if not loaded // load data if region file exists string regionPath = GetRegionPath (regionIndex); if (File.Exists (regionPath)) { StreamReader reader = new StreamReader (regionPath); string[] regionData = reader.ReadToEnd().Split((char)ushort.MaxValue); reader.Close(); LoadedRegions[indexString] = regionData; return true; } else { return false; // return false if region file doesn't exist } } return true; // return true if data is already loaded }
private static Index GetParentRegion( Index index ) { // returns the index of the region containing a specific chunk Index newIndex = new Index(index.x, index.y, index.z); if (index.x < 0) newIndex.x -= 9; if (index.y < 0) newIndex.y -= 9; if (index.z < 0) newIndex.z -= 9; int x = newIndex.x / 10; int y = newIndex.y / 10; int z = newIndex.z / 10; return new Index (x,y,z); }
private static string[] GetRegionData(Index regionIndex) { // loads region data and from file returns it, or returns null if region file is not found if (LoadRegionData(regionIndex) == true) { return LoadedRegions[regionIndex.ToString()]; } else { return null; } }
private static void CreateRegionFile(Index index) { // creates an empty region file Directory.CreateDirectory (Engine.WorldPath); StreamWriter writer = new StreamWriter (GetRegionPath(index)); for (int i=0; i<999; i++) { writer.Write ((char)ushort.MaxValue); } writer.Flush(); writer.Close(); }
private static int GetChunkRegionIndex( Index index ) { // returns the 1d index of a chunk's data in the region file Index newIndex = new Index (index.x, index.y, index.z); if (newIndex.x < 0) newIndex.x = -newIndex.x - 1; if (newIndex.y < 0) newIndex.y = -newIndex.y - 1; if (newIndex.z < 0) newIndex.z = -newIndex.z - 1; int flatIndex = (newIndex.z * 100) + (newIndex.y * 10) + newIndex.x; while (flatIndex > 999) { flatIndex -= 1000; } return flatIndex; }
GameObject DoSpawnChunk(Index index) { GameObject chunkObject = Instantiate(ChunkObject, index.ToVector3(), transform.rotation) as GameObject; Chunk chunk = chunkObject.GetComponent<Chunk>(); AddChunkToUpdateQueue (chunk); return chunkObject; }
public static Index PositionToChunkIndex( Vector3 position ) { Index chunkIndex = new Index (Mathf.RoundToInt(position.x / Engine.ChunkScale.x) / Engine.ChunkSideLength, Mathf.RoundToInt(position.y / Engine.ChunkScale.y) / Engine.ChunkSideLength, Mathf.RoundToInt(position.z / Engine.ChunkScale.z) / Engine.ChunkSideLength); return chunkIndex; }
bool IsWithinRange( NetworkPlayer player, Index chunkIndex ) { // checks if the player is within the range of the chunk if ( Mathf.Abs ( PlayerPositions [player].x - chunkIndex.x ) > PlayerChunkSpawnDistances[player] ) { return false; } if ( Mathf.Abs ( PlayerPositions [player].y - chunkIndex.y ) > PlayerChunkSpawnDistances[player] ) { return false; } if ( Mathf.Abs ( PlayerPositions [player].z - chunkIndex.z ) > PlayerChunkSpawnDistances[player] ) { return false; } return true; }
private string GetChunkData(Index index) { // returns the chunk data (from memory or from file), or an empty string if data can't be found // try to load from TempChunkData string indexString = index.ToString(); if (TempChunkData.ContainsKey (indexString)) { return TempChunkData[indexString]; } // try to load from region, return empty if not found int regionIndex = GetChunkRegionIndex (index); string[] regionData = GetRegionData (GetParentRegion(index)); if (regionData == null) { return ""; } return regionData[regionIndex]; }
public static GameObject SpawnChunk( Index index ) { // spawns a single chunk (only if it's not already spawned) GameObject chunk = ChunkManager.GetChunk (index); if (chunk == null) { return Engine.ChunkManagerInstance.DoSpawnChunk(index); } else return chunk; }
public void UpdatePlayerPosition( NetworkPlayer player, int chunkx, int chunky, int chunkz ) { // sent by client PlayerPositions [player] = new Index (chunkx, chunky, chunkz); if (EnableDebugLog) Debug.Log ("UniblocksServer: Updated player position. Player "+player.ToString() + ", position: " + new Vector3(chunkx,chunky,chunkz).ToString()); }
public static GameObject SpawnChunkFromServer( Index index ) { // spawns a chunk and disables mesh generation and enables timeout (used by the server in multiplayer) GameObject chunk = ChunkManager.GetChunk (index); if (chunk == null) { chunk = Engine.ChunkManagerInstance.DoSpawnChunk(index); Chunk chunkComponent =chunk.GetComponent<Chunk>(); chunkComponent.EnableTimeout = true; chunkComponent.DisableMesh = true; return chunk; } else return chunk; // don't disable mesh generation and don't enable timeout for chunks that are already spawned }
private void TrySpawnChunks( int x, int y, int z ) { if (Done == true) { // if we're not spawning chunks at the moment, just spawn them normally StartSpawnChunks (x,y,z); } else { // if we are spawning chunks already, flag to spawn again once the previous round is finished using the last requested position as origin. LastRequest = new Index(x,y,z); SpawnQueue = 1; StopSpawning = true; ChunkUpdateQueue.Clear (); } }
private void TrySpawnChunks( Index index ) { TrySpawnChunks (index.x, index.y, index.z); }
private void WriteChunkData(Index index, string data) { // writes the chunk data to the TempChunkData dictionary TempChunkData[index.ToString()] = data; }
public static void SpawnChunks( Index index ) { Engine.ChunkManagerInstance.TrySpawnChunks (index.x, index.y, index.z); }