using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MinecraftClient.Mapping
{
///
/// Represents a Minecraft World
///
public class World
{
///
/// The chunks contained into the Minecraft world
///
private Dictionary> chunks = new Dictionary>();
///
/// Read, set or unload the specified chunk column
///
/// ChunkColumn X
/// ChunkColumn Y
/// chunk at the given location
public ChunkColumn this[int chunkX, int chunkZ]
{
get
{
//Read a chunk
if (chunks.ContainsKey(chunkX))
if (chunks[chunkX].ContainsKey(chunkZ))
return chunks[chunkX][chunkZ];
return null;
}
set
{
if (value != null)
{
//Update a chunk column
if (!chunks.ContainsKey(chunkX))
chunks[chunkX] = new Dictionary();
chunks[chunkX][chunkZ] = value;
}
else
{
//Unload a chunk column
if (chunks.ContainsKey(chunkX))
{
if (chunks[chunkX].ContainsKey(chunkZ))
{
chunks[chunkX].Remove(chunkZ);
if (chunks[chunkX].Count == 0)
chunks.Remove(chunkX);
}
}
}
}
}
///
/// Get chunk column at the specified location
///
/// Location to retrieve chunk column
/// The chunk column
public ChunkColumn GetChunkColumn(Location location)
{
return this[location.ChunkX, location.ChunkZ];
}
///
/// Get block at the specified location
///
/// Location to retrieve block from
/// Block at specified location or Air if the location is not loaded
public Block GetBlock(Location location)
{
ChunkColumn column = GetChunkColumn(location);
if (column != null)
{
Chunk chunk = column.GetChunk(location);
if (chunk != null)
return chunk.GetBlock(location);
}
return new Block(0); //Air
}
///
/// Look for a block around the specified location
///
/// Start location
/// Block type
/// Search radius - larger is slower: O^3 complexity
/// Block matching the specified block type
public List FindBlock(Location from, Material block, int radius)
{
return FindBlock(from, block, radius, radius, radius);
}
///
/// Look for a block around the specified location
///
/// Start location
/// Block type
/// Search radius on the X axis
/// Search radius on the Y axis
/// Search radius on the Z axis
/// Block matching the specified block type
public List FindBlock(Location from, Material block, int radiusx, int radiusy, int radiusz)
{
Location minPoint = new Location(from.X - radiusx, from.Y - radiusy, from.Z - radiusz);
Location maxPoint = new Location(from.X + radiusx, from.Y + radiusy, from.Z + radiusz);
List list = new List { };
for (double x = minPoint.X; x <= maxPoint.X; x++)
{
for (double y = minPoint.Y; y <= maxPoint.Y; y++)
{
for (double z = minPoint.Z; z <= maxPoint.Z; z++)
{
Location doneloc = new Location(x, y, z);
Block doneblock = GetBlock(doneloc);
Material blockType = GetBlock(doneloc).Type;
if (blockType == block)
{
list.Add(doneloc);
}
}
}
}
return list;
}
///
/// Set block at the specified location
///
/// Location to set block to
/// Block to set
public void SetBlock(Location location, Block block)
{
ChunkColumn column = this[location.ChunkX, location.ChunkZ];
if (column != null)
{
Chunk chunk = column[location.ChunkY];
if (chunk == null)
column[location.ChunkY] = chunk = new Chunk();
chunk[location.ChunkBlockX, location.ChunkBlockY, location.ChunkBlockZ] = block;
}
}
///
/// Clear all terrain data from the world
///
public void Clear()
{
chunks = new Dictionary>();
}
///
/// Get the location of block of the entity is looking
///
/// Location of the entity
/// Yaw of the entity
/// Pitch of the entity
/// Location of the block or empty Location if no block was found
public Location GetLookingBlockLocation(Location location, double yaw, double pitch)
{
double rotX = (Math.PI / 180) * yaw;
double rotY = (Math.PI / 180) * pitch;
double x = -Math.Cos(rotY) * Math.Sin(rotX);
double y = -Math.Sin(rotY);
double z = Math.Cos(rotY) * Math.Cos(rotX);
Location vector = new Location(x, y, z);
for (int i = 0; i < 5; i++)
{
Location newVector = vector * i;
Location blockLocation = location.EyesLocation() + new Location(newVector.X, newVector.Y, newVector.Z);
blockLocation.X = Math.Floor(blockLocation.X);
blockLocation.Y = Math.Floor(blockLocation.Y);
blockLocation.Z = Math.Floor(blockLocation.Z);
Block b = GetBlock(blockLocation);
if (b.Type != Material.Air)
{
return blockLocation;
}
}
return new Location();
}
}
}