/// <summary> /// check the given chain is valid. /// </summary> /// <param name="blockchain"></param> /// <returns></returns> public static bool IsValid(Blockchain blockchain) { if (blockchain == null) { return(false); } var blocks = blockchain.Blocks; if (blocks.Count < 1) { return(false); } if (blocks[0].ToString() != BlockUtil.GenesisBlock.ToString()) { return(false); } for (var i = 0; i < blocks.Count; i++) { var block = blocks[i]; var lastblock = blocks[i - 1]; if (block.PreviousHash != lastblock.Hash || block.Hash != BlockUtil.GenerateHash(block)) { return(false); } } return(true); }
/// <summary> /// Generate all the chunks within a given sector and return the sector reference /// </summary> /// <param name="world"></param> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public Sector generateSector(World world, int x, int y) { Sector sector = new Sector(world); sector.setPosition(new Vector2I(x, y)); int dim = Sector.chunkDimension; Chunk[,] chunks = new Chunk[dim, dim]; Vector2I chunkPos = BlockUtil.SectorToChunk(new Vector2I(x, y)); for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { // Create the corresponding chunk based on its world position Chunk chunk = generateChunk(world, chunkPos.x + i, chunkPos.y + j); chunks[i, j] = chunk; } } sector.setChunks(chunks); return(sector); }
public MapHandler(World world, Vector2I startingPosition) { _activeSectors = new List <Sector>(); _generator = new ChunkGenerator(); _saving = new Queue <Sector>(); _loading = new Queue <Vector2I>(); _world = world; // Work out the bottom left corner from the starting chunk int half = (_loadedDimension - 1) / 2; Vector2I cornerSector = BlockUtil.SectorFromChunk(startingPosition) + new Vector2I(-half, -half); Debug.Log("Setting corner to " + cornerSector); // Set the starting position _position = cornerSector; // Create the initial sectors for (int i = 0; i < _loadedDimension; i++) { for (int j = 0; j < _loadedDimension; j++) { Vector2I pos = _position + new Vector2I(i, j); Sector sector = getSector(pos); _activeSectors.Add(sector); } } updatePosition(startingPosition); }
void Update() { _lastChunk = _currentChunk; Vector2I chunkPos = BlockUtil.chunkPositionFromWorld(transform.position); _currentChunk = chunkPos; // The chunk loader has moved! if (_lastChunk != _currentChunk) { //Debug.Log(String.Format("Chunk changed from {0} to {1}", _lastChunk, _currentChunk)); _world.loaderMoved(chunkPos); } }
public Chunk getChunk(Vector2I chunkPos) { Vector2I sector = BlockUtil.SectorFromChunk(chunkPos); int sectorX = Mathf.FloorToInt((float)chunkPos.x / Sector.chunkDimension); int sectorY = Mathf.FloorToInt((float)chunkPos.y / Sector.chunkDimension); int chunkX = chunkPos.x - (sectorX * Sector.chunkDimension); int chunkY = chunkPos.y - (sectorY * Sector.chunkDimension); for (int i = 0; i < _activeSectors.Count; i++) { // Has the sector been found? if (_activeSectors[i].position == new Vector2I(sectorX, sectorY)) { return(_activeSectors[i].getChunk(chunkPos.x, chunkPos.y)); } } return(null); }
private static GameObject createBlock(float x, float y, float z, int id, float addX, float addY, float addZ, float widthX, float widthY, float widthZ, Material m) { return(BlockUtil.createBlock(x, y, z, "BlockSpawner", id, addX, addY, addZ, widthX, widthY, widthZ, m)); }
public bool ContainsPoint(int2 point) => BlockUtil.ContainsPoint(point, GroupSize);
/// <summary> /// Generate the data for a corresponding chunk depending on where it should be in the world /// </summary> /// <param name="world"></param> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public Chunk generateChunk(World world, int x, int y) { Chunk chunk = new Chunk(world, new Vector2I(x, y)); int dim = Chunk.tileDimension; Tile[,,] tiles = new Tile[dim, dim, 2]; // Very simple terrain test for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { Vector2I globalPos = BlockUtil.localBlockToWorldBlock(new Vector2I(i, j), new Vector2I(x, y)); if (globalPos.y <= 21) // Flat terrain 20 blocks deep { if (globalPos.y == 21) // Varying grass / flower { if (UnityEngine.Random.Range(0, 10) < 7) { if (UnityEngine.Random.Range(0, 10) < 2) // Flowers are rarer than tallgrass { tiles[i, j, 0] = new Tile(5, 0); tiles[i, j, 1] = new Tile(0, 0); } else // Tallgrass is more common { tiles[i, j, 0] = new Tile(3, 0); tiles[i, j, 1] = new Tile(0, 0); } } else // Non-grass or flower, set air { tiles[i, j, 0] = new Tile(0, 0); tiles[i, j, 1] = new Tile(0, 0); } } else if (globalPos.y == 20) // Grass { tiles[i, j, 0] = new Tile(4, 0); tiles[i, j, 1] = new Tile(6, 0); } else if (globalPos.y < 20 && globalPos.y > 15) // dirt { tiles[i, j, 0] = new Tile(1, 0); tiles[i, j, 1] = new Tile(6, 0); } else if (globalPos.y <= 15 && globalPos.y > 11 && UnityEngine.Random.Range(0, 10) < 7) // random invariation of dirt { tiles[i, j, 0] = new Tile(1, 0); tiles[i, j, 1] = new Tile(6, 0); } else // stone { tiles[i, j, 0] = new Tile(2, 0); tiles[i, j, 1] = new Tile(10, 0); } } else // Air { tiles[i, j, 0] = new Tile(0, 0); tiles[i, j, 1] = new Tile(0, 0); } } } chunk.setData(tiles); return(chunk); /* for(int i = 0; i < dim; i++) * { * Vector2I globalPos = BlockUtil.localBlockToWorldBlock(new Vector2I(i, 0), new Vector2I(x, 0)); * float noise = Mathf.PerlinNoise((float)globalPos.x + seed, (float)globalPos.y); * * * }*/ }
protected override void OnUpdate() { if (groupSystem.IsReady == false) { return; } var map = groupSystem.BlocksMap; EntityCommandBuffer buffer = commandBufferSystem.CreateCommandBuffer(); ComponentDataFromEntity <Depth> depthLookup = GetComponentDataFromEntity <Depth>(); float time = (float)Time.ElapsedTime; float deltaTime = Time.DeltaTime; var size = groupSystem.GroupSize; NativeHashMap <int2, int> checkMap = new NativeHashMap <int2, int>(groupSystem.GroupSize.x * groupSystem.GroupSize.y, Allocator.TempJob); NativeList <int2> pointBuffer = new NativeList <int2>(groupSystem.GroupSize.x * groupSystem.GroupSize.y, Allocator.TempJob); var rand = Random.CreateFromIndex((uint)Time.ElapsedTime);; var isDrilledLookup = GetComponentDataFromEntity <IsBeingDrilled>(); var markLookup = GetComponentDataFromEntity <Mark>(); float3 origin = groupSystem.VisualOrigin; float scaleMultiplierThreshold = 0.25f; Dependency = Entities.WithReadOnly(depthLookup) .ForEach((Entity entity, ref Worker worker, ref Translation translation, ref NonUniformScale scale, ref DestinationPoint destination, ref VerticalLimit verticalLimit, ref DrillPower power, in WorkerAnimations animations) => { float drillTime = worker.Timer; bool isBouncing = power.Bounces < worker.MaxBounces; if (isBouncing == false && worker.Timer >= 1) { power.Bounces = 0; } float y = verticalLimit.Value + CurveUtil.Evaluate(ref animations.Bounce.Value.Keyframes, drillTime) * verticalLimit.FlightHeight * scale.Value.x; if (isBouncing == false) { var t = CurveUtil.Evaluate(ref animations.Move.Value.Keyframes, drillTime); float3 newPos = origin + math.lerp( new float3(destination.PreviousPoint.x, y, destination.PreviousPoint.y), new float3(destination.Value.x, y, destination.Value.y), t); translation.Value = newPos; } else { translation.Value = new float3(translation.Value.x, y, translation.Value.z); } if (worker.Timer >= 1 && isBouncing) { worker.Timer = 0; float newScale = scale.Value.x - worker.SizeLossPerHit; scale.Value = new float3(newScale, newScale, newScale); Depth depth = depthLookup[worker.CurrentBlock]; var centerMarkAmount = power.Amount * math.max(scale.Value.x, 0.1f); int2 center = destination.Value; verticalLimit.Value = -(depth.Value + centerMarkAmount); LeaveMark(size, center, buffer, centerMarkAmount, map, depthLookup, worker); if (worker.Radius > 0) { float factor = 0.8f; LeaveMark(size, new int2(center.x + 1, center.y), buffer, power.Amount * factor, map, depthLookup, worker); LeaveMark(size, new int2(center.x - 1, center.y), buffer, power.Amount * factor, map, depthLookup, worker); LeaveMark(size, new int2(center.x, center.y + 1), buffer, power.Amount * factor, map, depthLookup, worker); LeaveMark(size, new int2(center.x, center.y - 1), buffer, power.Amount * factor, map, depthLookup, worker); } if (worker.Radius > 1) { float factor = 0.6f; LeaveMark(size, new int2(center.x + 1, center.y - 1), buffer, power.Amount * factor, map, depthLookup, worker); LeaveMark(size, new int2(center.x - 1, center.y - 1), buffer, power.Amount * factor, map, depthLookup, worker); LeaveMark(size, new int2(center.x + 1, center.y + 1), buffer, power.Amount * factor, map, depthLookup, worker); LeaveMark(size, new int2(center.x - 1, center.y + 1), buffer, power.Amount * factor, map, depthLookup, worker); } if (worker.Radius > 2) { float spread = 0.4f; LeaveMark(size, new int2(center.x + 2, center.y), buffer, power.Amount * spread, map, depthLookup, worker); LeaveMark(size, new int2(center.x, center.y - 2), buffer, power.Amount * spread, map, depthLookup, worker); LeaveMark(size, new int2(center.x - 2, center.y), buffer, power.Amount * spread, map, depthLookup, worker); LeaveMark(size, new int2(center.x, center.y + 2), buffer, power.Amount * spread, map, depthLookup, worker); } if (worker.Radius > 3) { float spread = 0.2f; LeaveMark(size, new int2(center.x - 1, center.y + 2), buffer, power.Amount * spread, map, depthLookup, worker); LeaveMark(size, new int2(center.x - 2, center.y + 1), buffer, power.Amount * spread, map, depthLookup, worker); LeaveMark(size, new int2(center.x - 2, center.y - 1), buffer, power.Amount * spread, map, depthLookup, worker); LeaveMark(size, new int2(center.x - 1, center.y - 2), buffer, power.Amount * spread, map, depthLookup, worker); LeaveMark(size, new int2(center.x + 1, center.y - 2), buffer, power.Amount * spread, map, depthLookup, worker); LeaveMark(size, new int2(center.x + 2, center.y - 1), buffer, power.Amount * spread, map, depthLookup, worker); LeaveMark(size, new int2(center.x + 2, center.y + 1), buffer, power.Amount * spread, map, depthLookup, worker); LeaveMark(size, new int2(center.x + 1, center.y + 2), buffer, power.Amount * spread, map, depthLookup, worker); } if (worker.Radius > 4) { float spread = 0.1f; LeaveMark(size, new int2(center.x - 3, center.y), buffer, power.Amount * spread, map, depthLookup, worker); LeaveMark(size, new int2(center.x + 3, center.y), buffer, power.Amount * spread, map, depthLookup, worker); LeaveMark(size, new int2(center.x, center.y - 3), buffer, power.Amount * spread, map, depthLookup, worker); LeaveMark(size, new int2(center.x, center.y + 3), buffer, power.Amount * spread, map, depthLookup, worker); } power.Bounces++; if (power.Bounces >= worker.MaxBounces) { if (BlockUtil.GetClosestBlockOnSameLevel(rand, destination.Value, depthLookup, isDrilledLookup, map, checkMap, pointBuffer, size, out int2 next)) { buffer.RemoveComponent <IsBeingDrilled>(worker.CurrentBlock); destination.PreviousPoint = destination.Value; destination.Value = next; worker.CurrentBlock = map[next]; } } if (newScale <= 0.1f) { buffer.DestroyEntity(entity); buffer.RemoveComponent <IsBeingDrilled>(worker.CurrentBlock); } } float scaleMultiplier = math.max(scale.Value.x, scaleMultiplierThreshold); worker.Timer += deltaTime / worker.Frequency / scaleMultiplier; worker.Timer = math.min(1, worker.Timer); }).Schedule(Dependency); Dependency.Complete(); pointBuffer.Dispose(Dependency); checkMap.Dispose(Dependency); commandBufferSystem.AddJobHandleForProducer(Dependency); CurrentJob = Dependency; }
public void updatePosition(Vector2I chunkPosition) { // Convert chunk coordinates to sector coordinates Vector2I currentSector = BlockUtil.SectorFromChunk(chunkPosition); // Determine the min and max points of the current zone Vector2I min = _position; Vector2I max = _position + new Vector2I(_loadedDimension - 1, _loadedDimension - 1); Debug.Log("Min: " + min + ", Max: " + max + ", Current: " + currentSector); // Is the sector out of the bounds or on the edge? if (currentSector.x >= max.x || currentSector.x <= min.x || currentSector.y >= max.y || currentSector.y <= min.y) { int half = (_loadedDimension - 1) / 2; Vector2I newCorner = currentSector - new Vector2I(half, half); List <Vector2I> newPositions = new List <Vector2I>(); List <Vector2I> oldPositions = new List <Vector2I>(); List <Sector> cachedPositions = new List <Sector>(); // Find the new sectors to be part of the zone for (int i = 0; i < _loadedDimension; i++) { for (int j = 0; j < _loadedDimension; j++) { newPositions.Add(newCorner + new Vector2I(i, j)); oldPositions.Add(_position + new Vector2I(i, j)); } } int saving = 0; // Compare the old and new positions to determine which shall // remain cached and which need saving for (int i = 0; i < _activeSectors.Count; i++) { Sector sector = _activeSectors[i]; // Only sectors which are existent (to prevent un-bounded sectors from being saved) if (sector != null) { Vector2I pos = sector.position; // This sector is going to be part of the new zone if (newPositions.Contains(pos)) { cachedPositions.Add(sector); } else // This sector needs saving as it will be despawned { // Push the sector for saving queueSector(sector); saving++; } } } // Remove the cached positions from the new list for (int i = 0; i < cachedPositions.Count; i++) { for (int j = 0; j < newPositions.Count; j++) { // Do they match? Remove the new position as it doesn't need loading if (cachedPositions[i].position == newPositions[j]) { newPositions.RemoveAt(j); break; } } } // Load the desired chunks for (int i = 0; i < newPositions.Count; i++) { _loading.Enqueue(newPositions[i]); } //// A flag used to keep state for the following logical loop //bool flag = false; //int loading = 0; //int caching = 0; //// Iterate over all the new positions and determine //// which new positions need to be loaded //for (int i = 0; i < newPositions.Count; i++) //{ // Vector2I pos = newPositions[i]; // // Iterate over the cache to find the position to see if it matches // for (int j = 0; j < cachedPositions.Count; j++) // { // if (cachedPositions[j].position == pos) // { // flag = true; // break; // } // } // // The position isn't in the cache so it means it will need to be loaded // if (!flag) // { // loading++; // _loading.Enqueue(pos); // } // else // { // caching++; // } //} //Debug.Log("Enqueued " + loading + " sectors to load and caching " + caching + " / " + newPositions.Count); // Clean up the active sectors ready to re-place them _activeSectors.Clear(); // Re-add the sectors for (int i = 0; i < cachedPositions.Count; i++) { _activeSectors.Add(cachedPositions[i]); } //// Iterate over and re-position all cached sectors //for (int i = 0; i < _loadedDimension; i++) //{ // for (int j = 0; j < _loadedDimension; j++) // { // Vector2I pos = newCorner + new Vector2I(i, j); // // Search through the cache to find the specified sector // for (int k = 0; k < cachedPositions.Count; k++) // { // // The position has been found, set the sector // if (cachedPositions[k].position == pos) // { // _sectors[i, j] = cachedPositions[k]; // } // } // // The sector was not found, allocate the sector as NULL // _sectors[i, j] = null; // } //} //} _position = newCorner; } }
public Coord3 ModWrap(int m) => new Coord3(BlockUtil.ModWrap(x, m), BlockUtil.ModWrap(y, m), BlockUtil.ModWrap(z, m));