/// <summary> /// Initialisierung des Planeten /// </summary> /// <param name="size">Größe des Planeten in Blocks</param> /// <param name="generator">Instanz des Map-Generators</param> /// <param name="seed">Seed des Zufallsgenerators</param> public Planet(int id, int universe, Index3 size, int seed) { Id = id; Universe = universe; Size = size; Seed = seed; }
public Coordinate(int planet, Index3 block, Vector3 position) { Planet = planet; this.block = block; this.position = position; this.Normalize(); }
public Chunk(Index3 pos, int planet) { blocks = new IBlock[CHUNKSIZE_X * CHUNKSIZE_Y * CHUNKSIZE_Z]; Index = pos; Planet = planet; ChangeCounter = 0; }
public Chunk(Index3 pos, int planet) { Blocks = new ushort[CHUNKSIZE_X * CHUNKSIZE_Y * CHUNKSIZE_Z]; MetaData = new int[CHUNKSIZE_X * CHUNKSIZE_Y * CHUNKSIZE_Z]; Resources = new ushort[CHUNKSIZE_X * CHUNKSIZE_Y * CHUNKSIZE_Z][]; Index = pos; Planet = planet; ChangeCounter = 0; }
/// <summary> /// Initialisierung des Planeten /// </summary> /// <param name="id">ID des Planeten</param> /// <param name="universe">ID des Universums</param> /// <param name="size">Größe des Planeten in Zweierpotenzen Chunks</param> /// <param name="generator">Instanz des Map-Generators</param> /// <param name="seed">Seed des Zufallsgenerators</param> public Planet(int id, int universe, Index3 size, int seed) { Id = id; Universe = universe; Size = new Index3( (int)Math.Pow(2, size.X), (int)Math.Pow(2, size.Y), (int)Math.Pow(2, size.Z)); Seed = seed; }
public void Release(Index3 idx) { var flat = FlatIndex(idx.X, idx.Y, idx.Z); var chunk = _chunks[flat]; if (chunk != null) { _saveDelegate(idx, chunk); _chunks[flat] = null; } }
/// <summary> /// Setzt den Zentrums-Chunk für diesen lokalen Cache. /// </summary> /// <param name="planet">Der Planet, auf dem sich der Chunk befindet</param> /// <param name="index">Die Koordinaten an der sich der Chunk befindet</param> /// <param name="successCallback">Routine die Aufgerufen werden soll, falls das setzen erfolgreich war oder nicht</param> public void SetCenter(IPlanet planet, Index3 index, Action<bool> successCallback = null) { if (_loadingTask != null && !_loadingTask.IsCompleted) { _cancellationToken.Cancel(); _cancellationToken = new CancellationTokenSource(); _loadingTask = _loadingTask.ContinueWith(_ => InternalSetCenter(_cancellationToken.Token, planet, index, successCallback)); } else { _cancellationToken = new CancellationTokenSource(); _loadingTask = Task.Factory.StartNew(() => InternalSetCenter(_cancellationToken.Token, planet, index, successCallback)); } }
public void UpdatePosition(int i, int j, int k) { _center = new Index3(_center.X + i, _center.Y + j, _center.Z + k); if (_loadingTask != null && !_loadingTask.IsCompleted) { _cancellationToken.Cancel(); _cancellationToken = new CancellationTokenSource(); _loadingTask = _loadingTask.ContinueWith(_ => Reload(_cancellationToken.Token)); } else { _cancellationToken = new CancellationTokenSource(); _loadingTask = Task.Factory.StartNew(() => Reload(_cancellationToken.Token)); } }
/// <summary> /// Ermittelt die kürzeste Entfernung zum Ziel auf den normalisierten Achsen. /// </summary> /// <param name="destination">Ziel</param> /// <param name="size">Normalisierungsgröße</param> /// <returns>Entfernung</returns> public Index3 ShortestDistanceXYZ(Index3 destination, Index3 size) { return new Index3( ShortestDistanceX(destination.X, size.X), ShortestDistanceY(destination.Y, size.Y), ShortestDistanceZ(destination.Z, size.Z)); }
/// <summary> /// Überschreibt den Block an der angegebenen Koordinate. /// </summary> /// <param name="index">Koordinate des Blocks innerhalb des Chunks</param> /// <param name="block">Der neue Block oder null, fall der Block geleert werden soll</param> public void SetBlock(Index3 index, ushort block, int meta = 0) { SetBlock(index.X, index.Y, index.Z, block); }
public IChunk Get(Index3 idx) { return _chunks[FlatIndex(idx.X, idx.Y, idx.Z)]; }
/// <summary> /// Normalisiert die Y-Achse auf die angegebene Größe. /// </summary> /// <param name="size">3D-Größe (Y-Anzeil wird genommen)</param> public void NormalizeY(Index3 size) { NormalizeY(size.Y); }
/// <summary> /// Initialisierung /// </summary> /// <param name="value">Initialwerte (X und Y Anteil wird übernommen)</param> public Index2(Index3 value) : this(value.X, value.Y) {}
/// <summary> /// Kollisionsmethode, in der die Selektion der Blöcke vom Spieler aus geprüft wird /// </summary> /// <param name="collisionBoxes">Kollisionsboxen des Blocks</param> /// <param name="boxPosition">Die Position, wo sich die BoundingBox befindet</param> /// <param name="ray">Der Selektionsstrahl, der vom Spieler ausgeht</param> /// <param name="collisionAxis">Welche Achse von der Kollision betroffen ist</param> /// <returns>Die Entfernung zwischen der Kollision und der Kollisionsbox der Entität</returns> public static float? Intersect(BoundingBox[] collisionBoxes, Index3 boxPosition, Ray ray, out Axis? collisionAxis) { Vector3 min = new Vector3(1, 1, 1); float raylength = Player.SELECTIONRANGE * 2; float? minDistance = null; bool collided = false; foreach (var localBox in collisionBoxes) { BoundingBox box = new BoundingBox(localBox.Min + boxPosition, localBox.Max + boxPosition); float? distance = ray.Intersects(box); if (!distance.HasValue) continue; if (!minDistance.HasValue || minDistance > distance) { minDistance = distance; } Vector3 boxCorner = new Vector3( ray.Direction.X > 0 ? box.Min.X : box.Max.X, ray.Direction.Y > 0 ? box.Min.Y : box.Max.Y, ray.Direction.Z > 0 ? box.Min.Z : box.Max.Z); Vector3 n = (boxCorner - ray.Position) / (ray.Direction * raylength); min = new Vector3(Math.Min(min.X, n.X), Math.Min(min.Y, n.Y), Math.Min(min.Z, n.Z)); collided = true; } if (collided) { float max = -5f; Axis? axis = null; // Fall X if (min.X < 1f && min.X > max) { max = min.X; axis = Axis.X; } // Fall Y if (min.Y < 1f && min.Y > max) { max = min.Y; axis = Axis.Y; } // Fall Z if (min.Z < 1f && min.Z > max) { max = min.Z; axis = Axis.Z; } collisionAxis = axis; if (axis.HasValue) return max * raylength; return null; } else { collisionAxis = null; return null; } }
/// <summary> /// Überschreibt den Block an der angegebenen Koordinate. /// </summary> /// <param name="index">Koordinate des Blocks innerhalb des Chunks</param> /// <param name="block">Der neue Block oder null, fall der Block geleert werden soll</param> public void SetBlock(Index3 index, ushort block, int meta = 0) { SetBlock(index.X, index.Y, index.Z, block); }
public ChunkLoader(IChunkCache cache, int range, Index3 center) { _center = center; _maxRange = range; _cache = cache; }
public void SetBlockMeta(Index3 index, int meta) { IChunk chunk = GetChunk(index.X >> Chunk.LimitX, index.Y >> Chunk.LimitY, index.Z >> Chunk.LimitZ); if (chunk != null) chunk.SetBlockMeta(index.X, index.Y, index.Z, meta); }
public int GetBlockMeta(Index3 index, int meta) { IChunk chunk = GetChunk(index.X >> Chunk.LimitX, index.Y >> Chunk.LimitY, index.Z >> Chunk.LimitZ); if (chunk != null) return chunk.GetBlockMeta(index.X, index.Y, index.Z); return 0; }
public IChunk GetChunk(Index3 index) { return GetChunk(index.X, index.Y, index.Z); }
/// <summary> /// Normalisiert die Y-Achse auf die angegebene Größe. /// </summary> /// <param name="size">3D-Größe (Y-Anzeil wird genommen)</param> public void NormalizeY(Index3 size) => NormalizeY(size.Y);
/// <summary> /// Initialisierung /// </summary> /// <param name="index">3D-Basis</param> public Index3(Index3 index) : this(index.X, index.Y, index.Z) { }
/// <summary> /// Liefet den Block an der angegebenen Koordinate zurück. /// </summary> /// <param name="index">Koordinate des Blocks innerhalb des Chunkgs</param> /// <returns>Block oder null, falls es dort keinen Block gibt.</returns> public ushort GetBlock(Index3 index) { return GetBlock(index.X, index.Y, index.Z); }
/// <summary> /// Normalisiert den Wert von X und Y auf den angegebenen Grenzbereich. /// </summary> /// <param name="index">Der zu normalisierende Index2</param> /// <param name="size">3D Size</param> public static Index2 NormalizeXY(Index2 index,Index3 size) { index.NormalizeXY(size); return index; }
/// <summary> /// Initialisierung /// </summary> /// <param name="value">Initialwerte (X und Y Anteil wird übernommen)</param> public Index2(Index3 value) : this(value.X, value.Y) { }
/// <summary> /// Normalisiert den ChunkIndex auf die gegebenen Limits. /// </summary> /// <param name="limit"></param> public void NormalizeChunkIndexXY(Index3 limit) { Index3 index = ChunkIndex; index.NormalizeXY(limit); ChunkIndex = index; }
/// <summary> /// Prüft, ob die Kollisionsbox einer Entität mit den Kollisionsboxen eines Blocks kollidieren /// </summary> /// <param name="collisionBoxes">Kollisionsboxen des Blocks</param> /// <param name="boxPosition">Die Position, wo sich der Block befindet</param> /// <param name="player">Die Kollisionsbox einer Entität</param> /// <param name="move">Die befegungsrichtung der Entität</param> /// <param name="collisionAxis">Welche Achse von der Kollision betroffen ist</param> /// <returns>Die Entfernung zwischen der Kollision und der Kollisionsbox der Entität</returns> public static float? Intersect(BoundingBox[] collisionBoxes, Index3 boxPosition, BoundingBox player, Vector3 move, out Axis? collisionAxis) { Vector3 playerCorner = new Vector3( (move.X > 0 ? player.Max.X : player.Min.X), (move.Y > 0 ? player.Max.Y : player.Min.Y), (move.Z > 0 ? player.Max.Z : player.Min.Z)); Vector3 targetPosition = playerCorner + move; Vector3 playerMin = player.Min + move; Vector3 playerMax = player.Max + move; Vector3 min = new Vector3(1, 1, 1); bool collided = false; foreach (var localBox in collisionBoxes) { Vector3 boxMin = localBox.Min + new Vector3(boxPosition.X, boxPosition.Y, boxPosition.Z); Vector3 boxMax = localBox.Max + new Vector3(boxPosition.X, boxPosition.Y, boxPosition.Z); bool collide = playerMin.X <= boxMax.X && playerMax.X >= boxMin.X && playerMin.Y <= boxMax.Y && playerMax.Y >= boxMin.Y && playerMin.Z <= boxMax.Z && playerMax.Z >= boxMin.Z; if (!collide) continue; Vector3 boxCorner = new Vector3( move.X > 0 ? boxMin.X : boxMax.X, move.Y > 0 ? boxMin.Y : boxMax.Y, move.Z > 0 ? boxMin.Z : boxMax.Z); Vector3 n = (boxCorner - playerCorner) / move; min = new Vector3(Math.Min(min.X, n.X), Math.Min(min.Y, n.Y), Math.Min(min.Z, n.Z)); collided = true; } if (collided) { float max = 0f; Axis? axis = null; // Fall X if (min.X < 1f && min.X > max) { max = min.X; axis = Axis.X; } // Fall Y if (min.Y < 1f && min.Y > max) { max = min.Y; axis = Axis.Y; } // Fall Z if (min.Z < 1f && min.Z > max) { max = min.Z; axis = Axis.Z; } collisionAxis = axis; if (axis.HasValue) return max; return null; } else { collisionAxis = null; return null; } }
/// <summary> /// Normalisiert die X-Achse auf die angegebene Größe. /// </summary> /// <param name="size">3D-Größe (X-Anzeil wird genommen)</param> public void NormalizeX(Index3 size) => NormalizeX(size.X);
/// <summary> /// Normalisiert die X-Achse auf die angegebene Größe. /// </summary> /// <param name="size">3D-Größe (X-Anzeil wird genommen)</param> public void NormalizeX(Index3 size) { NormalizeX(size.X); }
/// <summary> /// Normalisiert den Wert von X und Y auf den angegebenen Grenzbereich. /// </summary> /// <param name="index">Der zu normalisierende Index2</param> /// <param name="size">3D Size</param> public static Index2 NormalizeXY(Index2 index, Index3 size) { index.NormalizeXY(size); return(index); }
public void EnsureLoaded(Index3 idx) { var flat = FlatIndex(idx.X, idx.Y, idx.Z); if (_chunks[flat] == null) _chunks[flat] = _loadDelegate(idx); }
/// <summary> /// Ermittelt die kürzeste Entfernung zum Ziel auf den normalisierten Achsen. /// </summary> /// <param name="destination">Ziel</param> /// <param name="size">Normalisierungsgröße</param> /// <returns>Entfernung</returns> public Index3 ShortestDistanceXY(Index3 destination, Index2 size) { return new Index3( ShortestDistanceX(destination.X, size.X), ShortestDistanceY(destination.Y, size.Y), destination.Z - Z); }
/// <summary> /// Gibt alle möglichen Flächen eines Blockes zurück /// </summary> /// <param name="pos">Position des Blockes</param> /// <param name="movevector">Bewegungsvector</param> /// <returns>Liste aller beteiligten Flächen</returns> public static IEnumerable<CollisionPlane> GetBlockCollisionPlanes(Index3 pos, Vector3 movevector) { //Ebene X if (movevector.X > 0) { yield return new CollisionPlane( new Vector3(pos.X, pos.Y, pos.Z), new Vector3(pos.X, pos.Y + 1f, pos.Z + 1f), new Vector3(-1, 0, 0)); } else if (movevector.X < 0) { yield return new CollisionPlane( new Vector3(pos.X + 1f, pos.Y, pos.Z), new Vector3(pos.X + 1f, pos.Y + 1f, pos.Z + 1f), new Vector3(1, 0, 0)); } //Ebene Y if (movevector.Y > 0) { yield return new CollisionPlane( new Vector3(pos.X, pos.Y, pos.Z), new Vector3(pos.X + 1f, pos.Y, pos.Z + 1f), new Vector3(0, -1, 0)); } else if (movevector.Y < 0) { yield return new CollisionPlane( new Vector3(pos.X , pos.Y + 1f, pos.Z), new Vector3(pos.X + 1f, pos.Y + 1f, pos.Z + 1f), new Vector3(0, 1, 0)); } //Ebene Z if (movevector.Z > 0) { yield return new CollisionPlane( new Vector3(pos.X, pos.Y , pos.Z ), new Vector3(pos.X + 1f, pos.Y + 1f , pos.Z ), new Vector3(0,0, -1)); } else if (movevector.Z < 0) { yield return new CollisionPlane( new Vector3(pos.X , pos.Y , pos.Z + 1f), new Vector3(pos.X + 1f, pos.Y +1f, pos.Z + 1f), new Vector3(0, 0, 1)); } }
/// <summary> /// Liefet den Block an der angegebenen Koordinate zurück. /// </summary> /// <param name="index">Koordinate des Blocks innerhalb des Chunkgs</param> /// <returns>Block oder null, falls es dort keinen Block gibt.</returns> public ushort GetBlock(Index3 index) { return(GetBlock(index.X, index.Y, index.Z)); }
/// <summary> /// Normalisiert die vorhandenen Parameter auf den Position-Wertebereich von [0...1] und die damit verbundene Verschiebung im Block. /// </summary> private void Normalize() { Index3 shift = new Index3( (int)Math.Floor(position.X), (int)Math.Floor(position.Y), (int)Math.Floor(position.Z)); block += shift; position = position - shift; }
/// <summary> /// Normalisiert die Z-Achse auf die angegebene Größe. /// </summary> /// <param name="size">3D-Size</param> public void NormalizeZ(Index3 size) { NormalizeZ(size.Z); }
/// <summary> /// Normalisiert die X-, Y- und Z-Achse auf die angegebene Größe. /// </summary> /// <param name="size">Maximalwert für X, Y und Z</param> public void NormalizeXYZ(Index3 size) { NormalizeXYZ(size.X, size.Y, size.Z); }
/// <summary> /// Liefert den Index des Blocks im abgeflachten Block-Array der angegebenen 3D-Koordinate zurück. Sollte die Koordinate ausserhalb /// der Chunkgrösse liegen, wird dies gewrapt. /// </summary> /// <param name="position">Die aktuelle Blockposition</param> /// <returns>Index innerhalb des flachen Arrays</returns> public static int GetFlatIndex(Index3 position) { return(((position.Z & (CHUNKSIZE_Z - 1)) << (LimitX + LimitY)) | ((position.Y & (CHUNKSIZE_Y - 1)) << LimitX) | (position.X & (CHUNKSIZE_X - 1))); }