private static void ProcessNode(Level level, BlockCoordinates coord, Queue <BlockCoordinates> lightBfsQueue) { //Log.Debug($"Setting light on block {block.Id} with LightLevel={block.LightLevel} and BlockLight={block.Blocklight}"); ChunkColumn chunk = GetChunk(level, coord); if (chunk == null) { return; } int lightLevel = chunk.GetBlocklight(coord.X & 0x0f, coord.Y & 0xff, coord.Z & 0x0f); Test(level, coord, coord.BlockUp(), lightBfsQueue, chunk, lightLevel); Test(level, coord, coord.BlockDown(), lightBfsQueue, chunk, lightLevel); Test(level, coord, coord.BlockWest(), lightBfsQueue, chunk, lightLevel); Test(level, coord, coord.BlockEast(), lightBfsQueue, chunk, lightLevel); Test(level, coord, coord.BlockSouth(), lightBfsQueue, chunk, lightLevel); Test(level, coord, coord.BlockNorth(), lightBfsQueue, chunk, lightLevel); //SetLightLevel(level, lightBfsQueue, level.GetBlockId(coord + BlockCoordinates.Down, chunk), lightLevel); //SetLightLevel(level, lightBfsQueue, level.GetBlockId(coord + BlockCoordinates.West, chunk), lightLevel); //SetLightLevel(level, lightBfsQueue, level.GetBlockId(coord + BlockCoordinates.East, chunk), lightLevel); //SetLightLevel(level, lightBfsQueue, level.GetBlockId(coord + BlockCoordinates.South, chunk), lightLevel); //SetLightLevel(level, lightBfsQueue, level.GetBlockId(coord + BlockCoordinates.North, chunk), lightLevel); }
private static BlockCoordinates?FindRandomTargetBlock(Entity entity, int dxz, int dy, Vector3?targetDirectinon = null) { Random random = entity.Level.Random; BlockCoordinates coords = (BlockCoordinates)entity.KnownPosition; double currentWeight = double.MinValue; Block currentBlock = null; for (int i = 0; i < 10; i++) { int x = random.Next(2 * dxz + 1) - dxz; int y = random.Next(2 * dy + 1) - dy; int z = random.Next(2 * dxz + 1) - dxz; var blockCoordinates = new BlockCoordinates(x, y, z) + coords; var block = entity.Level.GetBlock(blockCoordinates); var blockDown = entity.Level.GetBlock(blockCoordinates.BlockDown()); if (blockDown.IsSolid) { double weight = CalculateBlockWeight(entity, block, blockDown); if (weight > currentWeight) { currentWeight = weight; currentBlock = block; } } } return(currentBlock?.Coordinates); }
private void ProcessNode(IBlockAccess level, ChunkColumn chunk, BlockCoordinates coordinates, Queue <BlockCoordinates> lightBfsQueue, HashSet <BlockCoordinates> lightBfSet) { //if (section.IsAllAir()) byte currentSkyLight = GetSkyLight(coordinates, chunk); int sectionIdx = coordinates.Y >> 4; ChunkBase section = chunk.GetChunk(coordinates.Y); byte maxSkyLight = currentSkyLight; if (coordinates.Y < 255) { var up = coordinates.BlockUp(); maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, up, currentSkyLight, up: true)); } if (coordinates.Y > 0) { var down = coordinates.BlockDown(); maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, down, currentSkyLight, down: true)); } var west = coordinates.BlockWest(); maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, west, currentSkyLight)); var east = coordinates.BlockEast(); maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, east, currentSkyLight)); var south = coordinates.BlockSouth(); maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, south, currentSkyLight)); var north = coordinates.BlockNorth(); maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, north, currentSkyLight)); if (IsTransparent(coordinates, section) && currentSkyLight != 15) { int diffuseLevel = GetDiffuseLevel(coordinates, section); maxSkyLight = (byte)Math.Max(currentSkyLight, maxSkyLight - diffuseLevel); if (maxSkyLight > currentSkyLight) { level.SetSkyLight(coordinates, maxSkyLight); if (!lightBfSet.Contains(coordinates)) { lightBfsQueue.Enqueue(coordinates); lightBfSet.Add(coordinates); } } } }
protected bool IsMobOnGround(Vector3 pos) { if (pos.Y - Math.Truncate(pos.Y) > 0.1) return IsMobInGround(pos); BlockCoordinates coord = pos; Block block = Level.GetBlock(coord.BlockDown()); return block.IsSolid; //return block.IsSolid && block.GetBoundingBox().Contains(GetBoundingBox().OffsetBy(new Vector3(0, -0.1f, 0))) == ContainmentType.Intersects; }
public void ResetLight(Level level, Queue <BlockCoordinates> resetQueue, Queue <BlockCoordinates> sourceQueue, BlockCoordinates coordinates) { int currentLight = level.GetSkyLight(coordinates); if (coordinates.Y < 255) { TestForSource(level, resetQueue, sourceQueue, coordinates.BlockUp(), currentLight); } if (coordinates.Y > 0) { TestForSource(level, resetQueue, sourceQueue, coordinates.BlockDown(), currentLight, true); } TestForSource(level, resetQueue, sourceQueue, coordinates.BlockWest(), currentLight); TestForSource(level, resetQueue, sourceQueue, coordinates.BlockEast(), currentLight); TestForSource(level, resetQueue, sourceQueue, coordinates.BlockNorth(), currentLight); TestForSource(level, resetQueue, sourceQueue, coordinates.BlockSouth(), currentLight); }
protected bool IsMobOnGround(Vector3 pos) { if (pos.Y - Math.Truncate(pos.Y) > 0.1) { return(IsMobInGround(pos)); } BlockCoordinates coord = pos; Block block = Level.GetBlock(coord.BlockDown()); if (block.IsSolid) { //return true; BoundingBox bbox = block.GetBoundingBox(); return(pos.Y - bbox.Max.Y < 0.01); } return(false); //return block.IsSolid && block.GetBoundingBox().Contains(GetBoundingBox().OffsetBy(new Vector3(0, -0.1f, 0))) == ContainmentType.Intersects; }
private void PositionCheck() { if (Velocity.Y < -0.1) { int distance = (int)Math.Ceiling(Velocity.Length()); BlockCoordinates check = new BlockCoordinates(KnownPosition); for (int i = 0; i < distance; i++) { if (Level.GetBlock(check).IsSolid) { _checkPosition = false; KnownPosition = check.BlockUp(); return; } check = check.BlockDown(); } } KnownPosition.X += (float)Velocity.X; KnownPosition.Y += (float)Velocity.Y; KnownPosition.Z += (float)Velocity.Z; }
public void Calculate(Level level, BlockCoordinates coordinates) { int currentLight = level.GetSkyLight(coordinates); var chunk = level.GetChunk(coordinates); var height = chunk.GetRecalatedHeight(coordinates.X & 0x0f, coordinates.Z & 0x0f); Queue <BlockCoordinates> sourceQueue = new Queue <BlockCoordinates>(); sourceQueue.Enqueue(coordinates); if (currentLight != 0) { Queue <BlockCoordinates> resetQueue = new Queue <BlockCoordinates>(); HashSet <BlockCoordinates> visits = new HashSet <BlockCoordinates>(); // Reset all lights that potentially derive from this resetQueue.Enqueue(coordinates); Queue <BlockCoordinates> deleteQueue = new Queue <BlockCoordinates>(); while (resetQueue.Count > 0) { var coord = resetQueue.Dequeue(); if (visits.Contains(coord)) { continue; } visits.Add(coord); if (coord.DistanceTo(coordinates) > 16) { continue; } ResetLight(level, resetQueue, sourceQueue, coord); if (!sourceQueue.Contains(coord)) { deleteQueue.Enqueue(coord); } } level.SetSkyLight(coordinates, 0); foreach (var delete in deleteQueue) { level.SetSkyLight(delete, 0); } } else { sourceQueue.Enqueue(coordinates); sourceQueue.Enqueue(coordinates.BlockUp()); sourceQueue.Enqueue(coordinates.BlockDown()); sourceQueue.Enqueue(coordinates.BlockWest()); sourceQueue.Enqueue(coordinates.BlockEast()); sourceQueue.Enqueue(coordinates.BlockNorth()); sourceQueue.Enqueue(coordinates.BlockSouth()); } chunk.SetHeight(coordinates.X & 0x0f, coordinates.Z & 0x0f, (short)height); // Recalc Queue <BlockCoordinates> lightBfQueue = new Queue <BlockCoordinates>(sourceQueue); HashSet <BlockCoordinates> lightBfSet = new HashSet <BlockCoordinates>(sourceQueue); SkyLightBlockAccess blockAccess = new SkyLightBlockAccess(level.WorldProvider); Calculate(blockAccess, lightBfQueue, lightBfSet); }
private bool FindLog(Level level, BlockCoordinates coord, List <BlockCoordinates> visited, int distance) { if (visited.Contains(coord)) { return(false); } var block = level.GetBlock(coord); if (block is Log) { return(true); } visited.Add(coord); if (distance >= 4) { return(false); } if (!(block is Leaves2)) { return(false); } var leaves = (Leaves2)block; if (leaves.NewLeafType != NewLeafType) { return(false); } // check down if (FindLog(level, coord.BlockDown(), visited, distance + 1)) { return(true); } // check west if (FindLog(level, coord.BlockWest(), visited, distance + 1)) { return(true); } // check east if (FindLog(level, coord.BlockEast(), visited, distance + 1)) { return(true); } // check south if (FindLog(level, coord.BlockSouth(), visited, distance + 1)) { return(true); } // check north if (FindLog(level, coord.BlockNorth(), visited, distance + 1)) { return(true); } // check up if (FindLog(level, coord.BlockUp(), visited, distance + 1)) { return(true); } return(false); }
public IEnumerable <Tile> GetNeighbors(Tile start) { if (!_blockCache.TryGetValue(start, out var block)) { block = _level.GetBlock(new BlockCoordinates(start.X, _startY, start.Y)); _blockCache.Add(start, block); } HashSet <Tile> neighbors = new HashSet <Tile>(); for (int index = 0; index < Neighbors.GetLength(0); ++index) { var item = new Tile3d(start.X + Neighbors[index, 0], start.Y + Neighbors[index, 1], block.Coordinates.Y); bool isDiagonalMove = item.X != start.X && item.Y != start.Y; if (isDiagonalMove) { // Don't allow cutting corners where there is a block Tile undiagonal = new Tile(start.X, start.Y + Neighbors[index, 1]); if (!_blockCache.TryGetValue(undiagonal, out var udblock)) { continue; } if (udblock.Coordinates.Y != block.Coordinates.Y) { continue; } } // Check for too high steps BlockCoordinates coord = new BlockCoordinates(item.X, block.Coordinates.Y, item.Y); if (_level.GetBlock(coord).IsSolid) { // Only allow diagonal movements if on same Y level if (isDiagonalMove) { continue; } // Check if we hit head if we jump or climb up to next block if (IsObstructed(block.Coordinates.BlockUp())) { continue; } if (_entity.CanClimb) { Block blockUp = _level.GetBlock(coord.BlockUp()); Block currBlockUp = _level.GetBlock(block.Coordinates.BlockUp()); // Check if we hit ceiling too bool canMove = false; for (int i = 0; i < 10; i++) { if (IsBlocked(blockUp) && !IsBlocked(currBlockUp)) { blockUp = _level.GetBlock(blockUp.Coordinates.BlockUp()); currBlockUp = _level.GetBlock(currBlockUp.Coordinates.BlockUp()); continue; } canMove = true; break; } if (!canMove) { continue; } if (IsObstructed(blockUp.Coordinates)) { continue; } if (_blockCache.TryGetValue(item, out var trash) && trash.Coordinates.Y != blockUp.Coordinates.Y) { //Log.Warn("Already had this coordinated but on different Y"); continue; } item.RealY = blockUp.Coordinates.Y; _blockCache[item] = blockUp; } else { // Check block collision box, not hit box if (_level.GetBlock(coord) is Fence) { continue; } Block blockUp = _level.GetBlock(coord.BlockUp()); if (blockUp.IsSolid) { // Can't jump. This is hardwired for 1 block jump height for all mobs. continue; } if (IsObstructed(blockUp.Coordinates)) { continue; } //TODO: There is a problem when there is a path both under and over a block. It chooses the last checked block. if (_blockCache.TryGetValue(item, out var trash) && trash.Coordinates.Y != blockUp.Coordinates.Y) { //Log.Warn("Already had this coordinated but on different Y"); continue; } item.RealY = blockUp.Coordinates.Y; _blockCache[item] = blockUp; } } else { if (IsObstructed(coord)) { continue; } var blockDown = _level.GetBlock(coord.BlockDown()); if (blockDown.IsSolid) { // Continue on same Y level if (_blockCache.TryGetValue(item, out var trash) && trash.Coordinates.Y != coord.Y) { //Log.Warn("Already had this coordinated but on different Y"); continue; } item.RealY = coord.Y; _blockCache[item] = _level.GetBlock(coord); } else { // Only allow diagonal movements if on same Y level if (isDiagonalMove) { continue; } if (_entity.CanClimb) { bool canClimb = false; blockDown = _level.GetBlock(blockDown.Coordinates.BlockDown()); for (int i = 0; i < 10; i++) { if (!blockDown.IsSolid) { blockDown = _level.GetBlock(blockDown.Coordinates.BlockDown()); continue; } canClimb = true; break; } if (!canClimb) { continue; } blockDown = _level.GetBlock(blockDown.Coordinates.BlockUp()); if (IsObstructed(blockDown.Coordinates)) { continue; } if (_blockCache.TryGetValue(item, out var trash) && trash.Coordinates.Y != blockDown.Coordinates.Y) { //Log.Warn("Already had this coordinated but on different Y"); continue; } item.RealY = blockDown.Coordinates.Y; _blockCache[item] = blockDown; } else { if (!_level.GetBlock(coord.BlockDown().BlockDown()).IsSolid) { // Will fall continue; } if (IsObstructed(blockDown.Coordinates)) { continue; } if (_blockCache.TryGetValue(item, out var trash) && trash.Coordinates.Y != blockDown.Coordinates.Y) { //Log.Warn("Already had this coordinated but on different Y"); continue; } item.RealY = blockDown.Coordinates.Y; _blockCache[item] = blockDown; } } } neighbors.Add(item); } CheckDiagonals(block, neighbors); return(neighbors); }
public bool Generate(Level level, BlockCoordinates position) { Random rand = new Random(); int height = rand.Next(3) + _minTreeHeight; bool canGrow = true; if (position.Y >= 1 && position.Y + height + 1 <= 256) { for (int y = position.Y; y <= position.Y + 1 + height; ++y) { int k = 1; if (y == position.Y) { k = 0; } if (y >= position.Y + 1 + height - 2) { k = 2; } for (int x = position.X - k; x <= position.X + k && canGrow; ++x) { for (int z = position.Z - k; z <= position.Z + k && canGrow; ++z) { if (y >= 0 && y < 256) { if (!CanGrowInto(level.GetBlock(x, y, z))) { canGrow = false; } } else { canGrow = false; } } } } if (!canGrow) { return(false); } else { Block block = level.GetBlock(position.BlockDown()); if ((block is Grass || block is Dirt || block is Farmland) && position.Y < 256 - height - 1) { level.SetBlock(new Dirt { Coordinates = position.BlockDown() }); for (int y = position.Y - 3 + height; y <= position.Y + height; ++y) { int yd = y - (position.Y + height); int ydHalf = 1 - yd / 2; for (int x = position.X - ydHalf; x <= position.X + ydHalf; ++x) { int xd = x - position.X; for (int z = position.Z - ydHalf; z <= position.Z + ydHalf; ++z) { int zd = z - position.Z; if (Math.Abs(xd) != ydHalf || Math.Abs(zd) != ydHalf || rand.Next(2) != 0 && yd != 0) { BlockCoordinates blockpos = new BlockCoordinates(x, y, z); Block material = level.GetBlock(blockpos); if (material is Air || material is Leaves || material is Leaves2) { _leave.Coordinates = blockpos; level.SetBlock(_leave); } } } } } for (int y = 0; y < height; ++y) { BlockCoordinates blockpos = position + (BlockCoordinates.Up * y); Block material = level.GetBlock(blockpos); if (material is Air || material is Leaves || material is Leaves2) { _log.Coordinates = blockpos; level.SetBlock(_log); } } return(true); } else { return(false); } } } else { return(false); } }
public void MoveForward(double speedMultiplier, Entity[] entities) { if (_jumpCooldown > 0) { _jumpCooldown--; //return; } float speedFactor = (float)(_entity.Speed * speedMultiplier * 0.7f); var level = _entity.Level; var currPosition = _entity.KnownPosition; var direction = Vector3.Normalize(_entity.GetHorizDir() * new Vector3(1, 0, 1)); bool entityCollide = false; var boundingBox = _entity.GetBoundingBox().OffsetBy(direction * speedFactor); var players = level.GetSpawnedPlayers(); foreach (var player in players) { var bbox = boundingBox + 0.15f; if (player.GetBoundingBox().Intersects(bbox)) { entityCollide = true; break; } } if (!entityCollide) { var bbox = boundingBox + 0.3f; foreach (var ent in entities) { if (ent == _entity) { continue; } if (ent.EntityId < _entity.EntityId && _entity.IsColliding(bbox, ent)) { if (_entity.Velocity == Vector3.Zero && level.Random.Next(1000) == 0) { break; } entityCollide = true; break; } } } BlockCoordinates coord = (BlockCoordinates)(currPosition + (direction * speedFactor) + (direction * (float)(_entity.Length * 0.5f))); var block = level.GetBlock(coord); var blockUp = level.GetBlock(coord.BlockUp()); var blockUpUp = level.GetBlock(coord.BlockUp().BlockUp()); var colliding = block.IsSolid || (_entity.Height > 1 && blockUp.IsSolid); if (!colliding && !entityCollide) { var blockDown = level.GetBlock(coord.BlockDown()); if (!_entity.IsOnGround && !blockDown.IsSolid) { return; } //Log.Debug($"Move forward: {block}, {(_entity.IsOnGround ? "On ground" : "not on ground")}, Position: {(Vector3) _entity.KnownPosition}"); //if (!_entity.IsOnGround) return; var velocity = direction * speedFactor; //Log.Debug($"Moving sheep ({_entity.KnownPosition.Yaw}: {velocity}, {_entity.Velocity}"); if ((_entity.Velocity * new Vector3(1, 0, 1)).Length() < velocity.Length()) { _entity.Velocity += velocity - _entity.Velocity; } else { _entity.Velocity = velocity; } } else { if (_entity.CanClimb && !entityCollide) { _entity.Velocity = new Vector3(0, 0.2f, 0); } else if (!entityCollide && !blockUp.IsSolid && !(_entity.Height > 1 && blockUpUp.IsSolid) /*&& level.Random.Next(4) != 0*/) { // Above is wrong. Checks the wrong block in the wrong way. //Log.Debug($"Block ahead: {block}, {(_entity.IsOnGround ? "jumping" : "no jump")}, Position: {(Vector3)_entity.KnownPosition}"); //_entity.Level.SetBlock(new StainedGlass() {Coordinates = block.Coordinates, Metadata = (byte) _entity.Level.Random.Next(16)}); if (_entity.IsOnGround && _jumpCooldown <= 0) { _jumpCooldown = 10; _entity.Velocity += new Vector3(0, 0.42f, 0); } } else { if (entityCollide) { //Log.Debug($"Entity ahead: {block}, stopping"); _entity.Velocity *= new Vector3(0, 1, 0); } else { //Log.Debug($"Block ahead: {block}, ignoring"); //_entity.Level.SetBlock(new StainedGlass() { Coordinates = block.Coordinates + BlockCoordinates.Down, Metadata = (byte)_entity.Level.Random.Next(16) }); _entity.Velocity *= new Vector3(0, 1, 0); } } } }