public static bool FixCoords(ref Vector3i chunk, ref Vector3i local) { bool changed = false; if(local.x < 0) { chunk.x--; local.x += OCChunk.SIZE_X; changed = true; } if(local.y < 0) { chunk.y--; local.y += OCChunk.SIZE_Y; changed = true; } if(local.z < 0) { chunk.z--; local.z += OCChunk.SIZE_Z; changed = true; } if(local.x >= OCChunk.SIZE_X) { chunk.x++; local.x -= OCChunk.SIZE_X; changed = true; } if(local.y >= OCChunk.SIZE_Y) { chunk.y++; local.y -= OCChunk.SIZE_Y; changed = true; } if(local.z >= OCChunk.SIZE_Z) { chunk.z++; local.z -= OCChunk.SIZE_Z; changed = true; } return changed; }
private static void UpdateLight(OCMap map, Vector3i pos) { list.Clear(); foreach(Vector3i dir in Vector3i.directions) { list.Add( pos + dir ); } Scatter(map, list); }
//NOTE: this function pulls the weight of actually destroying blocks for us. It is applied to the OCActions of a character; not to blocks themselves. public void DestroyBlock(Vector3i? point) { if(point.HasValue) { OCMap map = OCMap.Instance;//(OCMap)GameObject.FindSceneObjectsOfType(typeof(OCMap)).FirstOrDefault(); //for updating goal controllers after deletion. OCBlock blockType = map.GetBlock(point.Value).block; OCGoalController[] goalControllers = (OCGoalController[])GameObject.FindObjectsOfType(typeof(OCGoalController)); //actually sets the block to null and recomputes the chunk. Debug.Log(OCLogSymbol.DEBUG + "DeleteSelectedVoxel called from CreateBlockEffect"); GameManager.world.voxels.DeleteSelectedVoxel(point.Value); //re-update goals concerned with this block type foreach(OCGoalController goalController in goalControllers) { if(goalController.GoalBlockType == blockType) { goalController.FindGoalBlockPositionInChunks(map.GetChunks()); } } blocksDestroyed++; } }
public static void RecomputeLightAtPosition(OCMap map, Vector3i pos) { OCSunLightMap lightmap = map.GetSunLightmap(); int oldSunHeight = lightmap.GetSunHeight(pos.x, pos.z); ComputeRayAtPosition(map, pos.x, pos.z); int newSunHeight = lightmap.GetSunHeight(pos.x, pos.z); if(newSunHeight < oldSunHeight) { // свет опустился // добавляем свет list.Clear(); for (int ty = newSunHeight; ty <= oldSunHeight; ty++) { pos.y = ty; lightmap.SetLight(MIN_LIGHT, pos); list.Add( pos ); } Scatter(map, list); } if(newSunHeight > oldSunHeight) { // свет поднялся // удаляем свет list.Clear(); for (int ty = oldSunHeight; ty <= newSunHeight; ty++) { pos.y = ty; list.Add( pos ); } RemoveLight(map, list); } if(newSunHeight == oldSunHeight) { if( map.GetBlock(pos).IsAlpha() ) { UpdateLight(map, pos); } else { RemoveLight(map, pos); } } }
public int DistanceSqr(Vector3i other) { int x2 = x - other.x, y2 = y - other.y, z2 = z - other.z; return (x2 * x2) + (y2 * y2) + (z2 * z2); }
//--------------------------------------------------------------------------- #region Private Member Data //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #endregion //--------------------------------------------------------------------------- #region Accessors and Mutators //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #endregion //--------------------------------------------------------------------------- #region Public Member Functions //--------------------------------------------------------------------------- public void TransferBlock(Vector3i? origin, Vector3i? destination) { if(origin.HasValue && destination.HasValue) { OCMap map = OCMap.Instance;//(OCMap)GameObject.FindSceneObjectsOfType(typeof(OCMap)).FirstOrDefault(); OCGoalController[] goalControllers = (OCGoalController[])GameObject.FindObjectsOfType(typeof(OCGoalController)); foreach(Transform battery in map.BatteriesSceneObject.transform) { if(VectorUtil.AreVectorsEqual(battery.position, new Vector3((float)origin.Value.x, (float)origin.Value.y, (float)origin.Value.z))) battery.position = new Vector3((float)destination.Value.x, (float)destination.Value.y, (float)destination.Value.z); } OCBlockData block = map.GetBlock(origin.Value); map.SetBlockAndRecompute(block, destination.Value); map.SetBlockAndRecompute(OCBlockData.CreateInstance<OCBlockData>().Init(null, origin.Value), origin.Value); foreach(OCGoalController goalController in goalControllers) { if(goalController.GoalBlockType == block.block) { goalController.FindGoalBlockPositionInChunks(map.GetChunks()); } } } }
private static void SetChunkLightDirty(OCMap map, Vector3i chunkPos) { OCChunk chunkData = map.GetChunk(chunkPos); if(chunkData == null) return; OCChunkRenderer chunk = chunkData.GetChunkRenderer(); if(chunk == null) return; chunk.SetLightDirty(); }
// generates a new spawn near initial spawn if initial spawn is in water public Vector3i DontSpawnPlayerInWater(Vector3i initialSpawn) { if (IsPlayerPositionDry(initialSpawn.x, initialSpawn.y, initialSpawn.z)) { return initialSpawn; } //find shore //bonus +10 because player shouldn't be spawned too close to shore. bool bonusset = false; int bonus = -1; Vector3i pos = initialSpawn; for (int i = 0; i < playerareasize / 4 - 5; i++) { if (IsPlayerPositionDry(pos.x, pos.y, pos.z)) { if (!bonusset) { bonus = 10; bonusset = true; } } if (bonusset && bonus-- < 0) { break; } pos.x++; int newblockheight = MapUtil.blockheight(d_Map, 0, pos.x, pos.y); pos.z = newblockheight + 1; } return pos; }
public void ShiftWorldChunks(Vector3i increment) { m_ChunkProcessor.ChunksAreBeingAdded = true; // We copy the original, because if we moved each chunk it's a // "destructive" move, possibly overwriting another chunk that also needs // to move. Chunk[, ,] copyOfOriginalChunks = CreateCopyOfOriginalChunkArray(); List<Chunk> newCunksAddedToMap = new List<Chunk>(); List<Chunk> chunksToDecorate = new List<Chunk>(); m_WorldData.MapChunkOffset = m_WorldData.MapChunkOffset - increment; //m_WorldData.MapChunkOffset.X -= increment.X; //m_WorldData.MapChunkOffset.Y -= increment.Y; for (int x = 0; x < m_WorldData.ChunksWide; x++) { for (int y = 0; y < m_WorldData.ChunksHigh; y++) { for (int z = 0; z < m_WorldData.ChunksDeep; z++) { MoveChunk(copyOfOriginalChunks[x, y, z], increment, newCunksAddedToMap, chunksToDecorate); } } } m_ChunkProcessor.AddBatchOfChunks(newCunksAddedToMap, BatchType.TerrainGeneration); m_ChunkProcessor.AddBatchOfChunks(chunksToDecorate, BatchType.Decoration); m_ChunkProcessor.ChunksAreBeingAdded = false; }
public override void Update(Server server, float dt) { int sizexchunks = server.mapsizexchunks(); int sizeychunks = server.mapsizeychunks(); int sizezchunks = server.mapsizezchunks(); for (int i = 0; i < 100; i++) { MapUtilCi.PosInt(CompressUnusedIteration, sizexchunks, sizeychunks, chunkpos); ServerChunk c = server.d_Map.GetChunkValid(chunkpos.X, chunkpos.Y, chunkpos.Z); bool stop = false; if (c != null) { var globalpos = new Vector3i(chunkpos.X * Server.chunksize, chunkpos.Y * Server.chunksize, chunkpos.Z * Server.chunksize); bool unload = true; foreach (var k in server.clients) { if (k.Value.IsBot) { // don't hold chunks in memory for bots continue; } // unload distance = view distance + 60% (prevents chunks from being unloaded too early (square loading vs. circular unloading)) int viewdist = (int)(server.chunkdrawdistance * Server.chunksize * 1.8f); if (server.DistanceSquared(server.PlayerBlockPosition(k.Value), globalpos) <= viewdist * viewdist) { //System.Console.WriteLine("No Unload: {0},{1},{2}", chunkpos.X, chunkpos.Y, chunkpos.Z); unload = false; } } if (unload) { // unload if chunk isn't seen by anyone if (c.DirtyForSaving) { // save changes to disk if necessary server.DoSaveChunk(chunkpos.X, chunkpos.Y, chunkpos.Z, c); } server.d_Map.SetChunkValid(chunkpos.X, chunkpos.Y, chunkpos.Z, null); foreach (var client in server.clients) { // mark chunks unseen for all players server.ClientSeenChunkRemove(client.Key, chunkpos.X, chunkpos.Y, chunkpos.Z); } stop = true; } } CompressUnusedIteration++; if (CompressUnusedIteration >= sizexchunks * sizeychunks * sizezchunks) { CompressUnusedIteration = 0; } if (stop) { // only unload one chunk at a time return; } } }
//--------------------------------------------------------------------------- #region Private Member Data //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #endregion //--------------------------------------------------------------------------- #region Accessors and Mutators //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #endregion //--------------------------------------------------------------------------- #region Public Member Functions //--------------------------------------------------------------------------- public static void Build(Vector3i localPos, Vector3i worldPos, OpenCog.Map.OCMap map, OpenCog.Builder.OCMeshBuilder mesh, bool onlyLight) { if(!onlyLight) { BuildCross((Vector3)localPos, worldPos, map, mesh); } BuildCrossLight(map, worldPos, mesh); }
public void ClearChunkDetails(Vector3i details) { BsonValue id = GetIDFor(details.X, details.Y, details.Z); lock (FSLock) { DBChunks.Delete(id); } }
static ComputeProgram() { int x,y,z; GL.GetInteger((GetIndexedPName)All.MaxComputeWorkGroupCount, 0, out x); GL.GetInteger((GetIndexedPName)All.MaxComputeWorkGroupCount, 1, out y); GL.GetInteger((GetIndexedPName)All.MaxComputeWorkGroupCount, 2, out z); MaximumWorkGroupSize = new Vector3i(x,y,z); }
public Block this[Vector3i Location] { get { return BlockData[Location.X, Location.Y, Location.Z]; } set { BlockData[Location.X, Location.Y, Location.Z] = value; } }
public ChunkForgetPacketOut(Vector3i cpos) { UsageType = NetUsageType.CHUNKS; ID = ServerToClientPacket.CHUNK_FORGET; Data = new byte[12]; Utilities.IntToBytes(cpos.X).CopyTo(Data, 0); Utilities.IntToBytes(cpos.Y).CopyTo(Data, 4); Utilities.IntToBytes(cpos.Z).CopyTo(Data, 8); }
/// <summary> /// Load a TileEntity's basic values (call via base() in all inheriting files) /// </summary> /// <param name="c"></param> public TileEntity(NbtCompound c) { orig = c; Pos = new Vector3i( c.Get<NbtInt>("x").Value, c.Get<NbtInt>("z").Value, c.Get<NbtInt>("y").Value); id = c.Get<NbtString>("id").Value; }
/// <summary> /// Load a TileEntity's basic values (call via base() in all inheriting files) /// </summary> /// <param name="CX">Chunk X Coordinate</param> /// <param name="CY">Chunk Y Coordinate</param> /// <param name="CS">Chunk horizontal scale</param> /// <param name="c">TileEntity's NbtCompound.</param> public TileEntity(int CX,int CY,int CS,NbtCompound c) { Pos = new Vector3i( c.Get<NbtInt>("x").Value, c.Get<NbtInt>("y").Value, c.Get<NbtInt>("z").Value); ID = (c["id"] as NbtString).Value; orig = c; }
CubeMesh CalculateRenderableCube(Cube cube, ref int visualVertexCount, ref int collisionVertexCount, Cube[,,] cubes, Vector3i gridPosition) { if (cube == null) return null; cube.cubeSize = cubeSize; cube.indexes = gridPosition; cube.chunk = this; var cubeMesh = cube.Calculate(ref visualVertexCount, ref collisionVertexCount,cubes, cubeLegend, cubeObject.colliderType, cubeObject.cubeTag); return cubeMesh; }
// TODO: May need to be re-enabled...hope not, since all blockdata that gets instantiated should get its coordinates too. // public BlockData(Block block) { // this.block = block; // direction = BlockDirection.Z_PLUS; // } // public OCBlockData() // { // } public OCBlockData Init(OpenCog.BlockSet.BaseBlockSet.OCBlock block, Vector3i globalPosition) { this.block = block; this._globalX = globalPosition.x; this._globalY = globalPosition.y; this._globalZ = globalPosition.z; direction = OCBlockDirection.Z_PLUS; return this; }
public Block this[Vector3i Location] { get { return Realm.GetBlock(Location); } set { Realm.SetBlock(Location, value); } }
public Block this[Vector3i Location] { get { return Realm.GetBlock((ChunkLocation * Size) + Location); } set { Realm.SetBlock((ChunkLocation * Size) + Location, value); } }
/// <summary> /// If the player has moved into a different chunk, we need to generate /// new world terrain /// </summary> private void CheckForWorldMove() { Vector3i newPlayerChunkPosition = CurrentPlayerChunkPosition(); if (newPlayerChunkPosition != m_PlayerChunkPosition) { Vector3i direction = (m_PlayerChunkPosition - newPlayerChunkPosition); m_PlayerChunkPosition = newPlayerChunkPosition; m_ChunkMover.ShiftWorldChunks(direction); } }
public byte GetLight(Vector3i chunkPos, Vector3i localPos, int worldY) { if(IsSunLight(chunkPos, localPos, worldY)) return OCSunLightComputer.MAX_LIGHT; Chunk3D<byte> chunk = lights.GetChunk(chunkPos); if(chunk != null) { byte light = chunk.Get(localPos); return (byte) Mathf.Max(OCSunLightComputer.MIN_LIGHT, light); } return OCSunLightComputer.MIN_LIGHT; }
public bool Decorate(Chunk chunk, Vector3i localBlockPosition, IRandom random) { if (IsAValidLocationforDecoration(localBlockPosition.X, localBlockPosition.Y, localBlockPosition.Z, random)) { CreateDecorationAt(localBlockPosition.X, localBlockPosition.Y, localBlockPosition.Z, random); return true; } return false; }
public void SendChunk(Server server, int clientid, Vector3i globalpos, Vector3i chunkpos) { ClientOnServer c = server.clients[clientid]; ServerChunk chunk = server.d_Map.GetChunk(globalpos.x, globalpos.y, globalpos.z); server.ClientSeenChunkSet(clientid, chunkpos.x, chunkpos.y, chunkpos.z, (int)server.simulationcurrentframe); //sent++; byte[] compressedchunk; if (MapUtil.IsSolidChunk(chunk.data) && chunk.data[0] == 0) { //don't send empty chunk. compressedchunk = null; } else { compressedchunk = server.CompressChunkNetwork(chunk.data); //todo! //commented because it was being sent too early, before full column was generated. //if (!c.heightmapchunksseen.ContainsKey(new Vector2i(v.x, v.y))) { byte[] heightmapchunk = Misc.UshortArrayToByteArray(server.d_Map.GetHeightmapChunk(globalpos.x, globalpos.y)); byte[] compressedHeightmapChunk = server.d_NetworkCompression.Compress(heightmapchunk); Packet_ServerHeightmapChunk p1 = new Packet_ServerHeightmapChunk() { X = globalpos.x, Y = globalpos.y, SizeX = Server.chunksize, SizeY = Server.chunksize, CompressedHeightmap = compressedHeightmapChunk, }; server.SendPacket(clientid, server.Serialize(new Packet_Server() { Id = Packet_ServerIdEnum.HeightmapChunk, HeightmapChunk = p1 })); c.heightmapchunksseen[new Vector2i(globalpos.x, globalpos.y)] = (int)server.simulationcurrentframe; } } if (compressedchunk != null) { foreach (byte[] part in Server.Parts(compressedchunk, 1024)) { Packet_ServerChunkPart p1 = new Packet_ServerChunkPart() { CompressedChunkPart = part, }; server.SendPacket(clientid, server.Serialize(new Packet_Server() { Id = Packet_ServerIdEnum.ChunkPart, ChunkPart = p1 })); } } Packet_ServerChunk p = new Packet_ServerChunk() { X = globalpos.x, Y = globalpos.y, Z = globalpos.z, SizeX = Server.chunksize, SizeY = Server.chunksize, SizeZ = Server.chunksize, }; server.SendPacket(clientid, server.Serialize(new Packet_Server() { Id = Packet_ServerIdEnum.Chunk_, Chunk_ = p })); }
public override bool Decorate(Chunk chunk, Vector3i localBlockPosition, IRandom random) { if (IsAValidLocationforDecoration(localBlockPosition.X, localBlockPosition.Y, localBlockPosition.Z, random)) { CreateGameObjectDecorationAt(chunk, localBlockPosition.X, localBlockPosition.Y - 1, localBlockPosition.Z, random); return true; } return false; }
/// <summary> /// Initializes a new instance of the <see cref="FreezingArcher.Content.Wind"/> class. /// </summary> /// <param name="globalWind">Global wind force.</param> /// <param name="fieldResolution">Wind field resolution.</param> /// <param name="defaultFieldForce">Default field force.</param> public Wind(Vector3 globalWind, Vector3i fieldResolution, Vector3 defaultFieldForce = default(Vector3)) { Global = globalWind; FieldResolution = fieldResolution; WindField = new Vector3[FieldResolution.X, FieldResolution.Y, FieldResolution.Z]; for (int x = 0; x < WindField.GetLength(0); x++) for (int y = 0; y < WindField.GetLength(1); y++) for (int z = 0; z < WindField.GetLength(2); z++) WindField[x, y, z] = defaultFieldForce; }
public void QueueRequest(Vector3i Position) { NetworkChunk Target; Vector3i ChunkCoords = Position / NetworkChunk.Size; //Only make a new request if one hasn't been made, and if one isn't being resolved. if (!Outgoing.TryGetValue(ChunkCoords, out Target) && !Incomming.TryGetValue(ChunkCoords, out Target)) { Target = new NetworkChunk(Realm, ChunkCoords); Outgoing[ChunkCoords] = Target; } }
private void GenerateLeaves(Vector3i center, Vector3i pos) { Vector3 delta = center - pos; delta.y *= 2; if( delta.sqrMagnitude > 6*6 ) return; if(!map.GetBlock(pos).IsEmpty()) return; map.SetBlock(leaves, pos); foreach(Vector3i dir in Vector3i.directions) { GenerateLeaves(center, pos+dir); } }
private bool GenerateChunk(Vector3i chunkPos) { bool reportedWater = false; bool reportedTerrain = false; bool reportedIsland = false; reportedWater = true; reportedTerrain = true; reportedIsland = true; bool generated = false; for(int z=-1; z<OpenCog.Map.OCChunk.SIZE_Z+1; z++) { for(int x=-1; x<OpenCog.Map.OCChunk.SIZE_X+1; x++) { for(int y=0; y<OpenCog.Map.OCChunk.SIZE_Y; y++) { Vector3i worldPos = OpenCog.Map.OCChunk.ToWorldPosition(chunkPos, new Vector3i(x, y, z)); if(worldPos.y <= WATER_LEVEL) { if(map.GetBlock(worldPos).IsEmpty()) map.SetBlock( water, worldPos ); if (!reportedWater) { Debug.Log("I made a water block!"); reportedWater = true; } generated = true; } int terrainHeight = GetTerrainHeight(worldPos.x, worldPos.z); if( worldPos.y <= terrainHeight ) { GenerateBlockForBaseTerrain(worldPos); if (!reportedTerrain) { Debug.Log("I made a terrain block!"); reportedTerrain = true; } generated = true; continue; } int islandHeight = GetIslandHeight(worldPos.x, worldPos.z); if( worldPos.y <= islandHeight ) { GenerateBlockForIsland(worldPos, islandHeight-worldPos.y, islandHeight); if (!reportedIsland) { Debug.Log("I made an island block!"); reportedIsland = true; } generated = true; continue; } } } } return generated; }
/// Constructs a vector by copying the supplied vector. public Vector3i(Vector3i a) { this.x = a.x; this.y = a.y; this.z = a.z; }
/// Component-wise maximum of one vector and another, returning a new vector as the result. public static Vector3i Max(Vector3i lhs, Vector3i rhs) { return(new Vector3i(Mathf.Max(lhs.x, rhs.x), Mathf.Max(lhs.y, rhs.y), Mathf.Max(lhs.z, rhs.z))); }
/// Component-wise clamping of one vector and another, returning a new vector as the result. public static Vector3i Clamp(Vector3i value, Vector3i min, Vector3i max) { return(new Vector3i(Mathf.Clamp(value.x, min.x, max.x), Mathf.Clamp(value.y, min.y, max.y), Mathf.Clamp(value.z, min.z, max.z))); }
/// Scales 'a' by 'b' and returns the result. public static Vector3i Scale(Vector3i a, Vector3i b) { return(new Vector3i(a.x * b.x, a.y * b.y, a.z * b.z)); }
/// Computes the distance between two positions. public static float Distance(Vector3i a, Vector3i b) { return(Mathf.Sqrt(DistanceSquared(a, b))); }
protected override void DoVoxelAction(VoxelSpace voxels, Transform hitTransform, Vector3 hitLocation, Vector3i index) { voxels.SetVoxel(index, new Voxel() { Exists = false }); }
/*bool isSolidSideFree(Vector3i position, int side) * { * switch (side) * { * case 0: * return !(world.IsSolid(position, this) && world.IsSolid(position + Vector3i.left, this)); * case 1: * return !(world.IsSolid(position, this) && world.IsSolid(position + Vector3i.right, this)); * case 2: * return !(world.IsSolid(position, this) && world.IsSolid(position + Vector3i.down, this)); * case 3: * return !(world.IsSolid(position, this) && world.IsSolid(position + Vector3i.up, this)); * case 4: * return !(world.IsSolid(position, this) && world.IsSolid(position + Vector3i.back, this)); * case 5: * return !(world.IsSolid(position, this) && world.IsSolid(position + Vector3i.forward, this)); * default: * return true; * } * }*/ /// <summary> /// In chunk coordinates /// </summary> public bool IsInChunk(Vector3i position) { return(position.x > -1 && position.x < chunkSize && position.y > -1 && position.y < chunkSize && position.z > -1 && position.z < chunkSize); }
public override bool CanBePlaced(Vector3i position, World world) { return(true); }
public override Block ToBlock(Chunk chunk, Vector3i position) { return(new BlockOakLog(chunk, position)); }
protected override void DrawVoxelChange(VoxelSpace space, Vector3 hitLocation, Vector3i index) { }
public override bool TryPlaceObject(Player player, Vector3i position, Quaternion rotation) { return(TryPlaceObjectOnSolidGround(player, position, rotation, StarterCampObject.DefaultDim)); }
public BCMVector3i(Vector3i v) { x = v.x; y = v.y; z = v.z; }
public int FindTypeOfVolume(ref Vector3i pos1, ref Vector3i pos2, out Vector3i lower, out Vector3i higher) { lower = new Vector3i(); higher = new Vector3i(); pos1.X = pos1.X % Shared.Voxel.World.VoxelSize.X; pos1.Z = pos1.Z % Shared.Voxel.World.VoxelSize.Z; pos2.X = pos2.X % Shared.Voxel.World.VoxelSize.X; pos2.Z = pos2.Z % Shared.Voxel.World.VoxelSize.Z; lower.X = Math.Min(pos1.X, pos2.X); lower.Y = Math.Min(pos1.Y, pos2.Y); lower.Z = Math.Min(pos1.Z, pos2.Z); higher.X = Math.Max(pos1.X, pos2.X); higher.Y = Math.Max(pos1.Y, pos2.Y) + 1; higher.Z = Math.Max(pos1.Z, pos2.Z); KeyValuePair <int, int>[] volumes = new KeyValuePair <int, int> [4]; //sometimes a delta is 0 - we add one so the volume is not 0. The value does not matter here! volumes[0] = new KeyValuePair <int, int>(0, (((higher.X - lower.X) + 1) * ((higher.Z - lower.Z) + 1))); volumes[1] = new KeyValuePair <int, int>(1, (lower.X + (Shared.Voxel.World.VoxelSize.X - higher.X) + 1) * (lower.Z + (Shared.Voxel.World.VoxelSize.Z - higher.Z) + 1)); volumes[2] = new KeyValuePair <int, int>(2, ((higher.X - lower.X) + 1) * (lower.Z + (Shared.Voxel.World.VoxelSize.Z - higher.Z) + 1)); volumes[3] = new KeyValuePair <int, int>(3, (lower.X + (Shared.Voxel.World.VoxelSize.X - higher.X) + 1) * ((higher.Z - lower.Z) + 1)); KeyValuePair <int, int> min = volumes.MinObj(kv => kv.Value); return(min.Key); }
public void AddBlockChangedEntry(Block pBlock, Vector3i pPosition, Vector3i?pSourcePosition = null) { pSourcePosition = pSourcePosition ?? pPosition; mLastCommandBlocks.Push(WorldEditBlock.CreateNew(pBlock, pPosition, pSourcePosition)); }
// Is there a correct name for this operation? public int SumAllAxis(Vector3i pVector) { return(pVector.X + pVector.Y + pVector.Z); }
private static bool IsValidSpawnPointForCorpseBlock(Vector3i location, BlockValue corpseBlock) { return(Block.list[corpseBlock.type].CanPlaceBlockAt(GetWorld(), 0, location, corpseBlock, false)); }
private static Block GetBlockAt(Vector3i location) { return(GetWorld().GetBlock(location).Block); }
void DestroyVoxels(int xPos, int yPos, int zPos, int range) { // Set up a material which we will apply to the cubes which we spawn to replace destroyed voxels. Material fakeVoxelMaterial = Resources.Load("Materials/FakeColoredCubes", typeof(Material)) as Material; Texture diffuseMap = coloredCubesVolume.GetComponent <ColoredCubesVolumeRenderer>().material.GetTexture("_DiffuseMap"); if (diffuseMap != null) { List <string> keywords = new List <string> { "DIFFUSE_TEXTURE_ON" }; fakeVoxelMaterial.shaderKeywords = keywords.ToArray(); fakeVoxelMaterial.SetTexture("_DiffuseMap", diffuseMap); } fakeVoxelMaterial.SetTexture("_NormalMap", coloredCubesVolume.GetComponent <ColoredCubesVolumeRenderer>().material.GetTexture("_NormalMap")); fakeVoxelMaterial.SetFloat("_NoiseStrength", coloredCubesVolume.GetComponent <ColoredCubesVolumeRenderer>().material.GetFloat("_NoiseStrength")); // Initialise outside the loop, but we'll use it later. Vector3 pos = new Vector3(xPos, yPos, zPos); int rangeSquared = range * range; // Later on we will be deleting some voxels, but we'll also be looking at the neighbours of a voxel. // This interaction can have some unexpected results, so it is best to first make a list of voxels we // want to delete and then delete them later in a separate pass. List <Vector3i> voxelsToDelete = new List <Vector3i>(); // Iterage over every voxel in a cubic region defined by the received position (the center) and // the range. It is quite possible that this will be hundreds or even thousands of voxels. for (int z = zPos - range; z < zPos + range; z++) { for (int y = yPos - range; y < yPos + range; y++) { for (int x = xPos - range; x < xPos + range; x++) { // Compute the distance from the current voxel to the center of our explosion. int xDistance = x - xPos; int yDistance = y - yPos; int zDistance = z - zPos; // Working with squared distances avoids costly square root operations. int distSquared = xDistance * xDistance + yDistance * yDistance + zDistance * zDistance; // We're iterating over a cubic region, but we want our explosion to be spherical. Therefore // we only further consider voxels which are within the required range of our explosion center. // The corners of the cubic region we are iterating over will fail the following test. if (distSquared < rangeSquared) { // Get the current color of the voxel QuantizedColor color = coloredCubesVolume.data.GetVoxel(x, y, z); // Check the alpha to determine whether the voxel is visible. if (color.alpha > 127) { Vector3i voxel = new Vector3i(x, y, z); voxelsToDelete.Add(voxel); if (IsSurfaceVoxel(x, y, z)) { GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube); cube.AddComponent <Rigidbody>(); cube.transform.parent = coloredCubesVolume.transform; cube.transform.localPosition = new Vector3(x, y, z); cube.transform.localRotation = Quaternion.identity; cube.transform.localScale = new Vector3(0.9f, 0.9f, 0.9f); cube.GetComponent <Renderer>().material = fakeVoxelMaterial; cube.GetComponent <Renderer>().material.SetColor("_CubeColor", (Color32)color); cube.GetComponent <Renderer>().material.SetVector("_CubePosition", new Vector4(x, y, z, 0.0f)); Vector3 explosionForce = cube.transform.position - pos; // These are basically random values found through experimentation. // They just add a bit of twist as the cubes explode which looks nice float xTorque = (x * 1436523.4f) % 56.0f; float yTorque = (y * 56143.4f) % 43.0f; float zTorque = (z * 22873.4f) % 38.0f; Vector3 up = new Vector3(0.0f, 2.0f, 0.0f); cube.GetComponent <Rigidbody>().AddTorque(xTorque, yTorque, zTorque); cube.GetComponent <Rigidbody>().AddForce((explosionForce.normalized + up) * 100.0f); // Cubes are just a temporary visual effect, and we delete them after a few seconds. float lifeTime = Random.Range(8.0f, 12.0f); Destroy(cube, lifeTime); } } } } } } foreach (Vector3i voxel in voxelsToDelete) // Loop through List with foreach { coloredCubesVolume.data.SetVoxel(voxel.x, voxel.y, voxel.z, new QuantizedColor(0, 0, 0, 0)); } }
private static bool IsStableBlock(Vector3i location) { Block block = GetBlockAt(location); return(block.StabilitySupport && (CONFIG.SPAWN_ON_SPIKES || !block.Properties.Values.ContainsKey(DAMAGE_PROPERTY))); }
protected override void DrawVoxelChange(VoxelSpace voxels, Transform hitTransform, Vector3 hitLocation, Vector3i index) { var currentVoxel = voxels.GetVoxel(index); if (currentVoxel.HasValue) { ref var displayVoxels = ref _displayGridEntity.Get <VoxelGrid>(); displayVoxels.SetVoxel(new Vector3i(0, 0, 0), currentVoxel.Value); _displayGridEntity.Set(displayVoxels); }
public bool isLoaded(Vector3i pos) { return(chunks.ContainsKey(pos)); }
public void ChangeBlock(Vector3i absolutePosition, BlockType blockType) { database.ChangeBlock(absolutePosition, blockType); UpdateFacing(database.GetBlock(absolutePosition)); }
public override bool OnEntityActivated(int _indexInBlockActivationCommands, Vector3i _tePos, EntityAlive _entityFocusing) { this.emodel.avatarController.SetBool("IsBusy", true); return(base.OnEntityActivated(_indexInBlockActivationCommands, _tePos, _entityFocusing)); }
/// <summary> /// Gets a block in this chunk and has no error checking /// </summary> /// <param name="position">In chunk or world coordinates</param> /// <returns></returns> public Block GetBlockNoError(Vector3i position) { return(blocks[position.x & chunkSizeMask, position.y & chunkSizeMask, position.z & chunkSizeMask]); }
// returns lookup byte position to sector table public static int GetTablePos(Vector3i cp) { return(4 * (Mth.Mod16(cp.x) + Mth.Mod16(cp.z) * 16 + Mth.Mod16(cp.y) * 256)); }
//public static string SaveFileName(Chunk chunk) { // return SaveLocation(World.worldName) + string.Format("{0},{1},{2}.scs", chunk.cp.x, chunk.cp.y, chunk.cp.z); //} // get region name given region coord static string RegionFileName(Vector3i rc) { return(SaveLocation(World.worldName) + string.Format("{0},{1},{2}.screg", rc.x, rc.y, rc.z)); }
static void LoadChunksFromRegion(Vector3i regionCoord, Queue <Chunk> chunks) { if (chunks.Count <= 0) { return; } string regionFile = RegionFileName(regionCoord); if (!File.Exists(regionFile)) // if no region file then all these chunks need to be generated fresh { lock (chunkLoadFailures) { while (chunks.Count > 0) { chunkLoadFailures.Enqueue(chunks.Dequeue()); } } return; } #if _DEBUG Debug.Log("loading " + chunks.Count + " chunks from region " + regionCoord); watch.Restart(); #endif FileStream stream = null; try { stream = File.Open(regionFile, FileMode.Open); // will open or create if not there int c = stream.Read(table, 0, TABLE_SIZE); Assert.IsTrue(c == TABLE_SIZE); while (chunks.Count > 0) { Chunk chunk = chunks.Dequeue(); int sectorOffset; byte sectorCount; GetTableEntry(chunk.cp, out sectorOffset, out sectorCount); if (sectorOffset == 0 && sectorCount == 0) // no entry in table { lock (chunkLoadFailures) { chunkLoadFailures.Enqueue(chunk); } continue; } // seek to start of sector stream.Seek(TABLE_SIZE + sectorOffset * SECTOR_SIZE, SeekOrigin.Begin); // read count to get length of chunk data stream.Read(fourBytes, 0, 4); reader.Start(fourBytes, 0, oneUint, 4); int bytes = (int)reader.ReadUInt(); // read from stream into byte buffer stream.Read(byteBuffer, 0, bytes); DecodeChunk(byteBuffer, bytes, chunk); lock (chunksLoaded) { chunksLoaded.Enqueue(chunk); } } } catch (Exception e) { Debug.Log(e.Message); } finally { if (stream != null) { stream.Close(); } } #if _DEBUG Debug.Log("loaded in " + watch.ElapsedMilliseconds + " ms"); #endif }
public Block GetBlock(Vector3i absolutePosition) { return(database.GetBlock(absolutePosition)); }
public override bool Stroke(Ray ray, BrickTree tree, VoxelMaterial voxelMaterial, VoxelMaterialAtlas materialAtlas, List <byte> blackList, Queue <OctreeEntry <Brick> > outChangedBricks, Bounds bounds) { // Find the brick intersected OctreeEntry <Brick> brickEntry = FirstBrickIntersected(ray, tree, blackList); // If we can't find one return if (brickEntry == null) { return(false); } Brick brick = brickEntry.entry; Vector3 brickPosition = brickEntry.bounds.min; dummyVector3.Set(brickEntry.cell.x, brickEntry.cell.y, brickEntry.cell.z); // Make sure the brick is within the legal paining bounds if (!bounds.Contains(dummyVector3)) { return(false); } // Clear the resused found queue found.Clear(); // Find which cells are intersected within the grid selector.Select(ray, brick, brickPosition, blackList, found); if (found.Count == 0) { return(false); } Vector3i firstIntersection = found.Dequeue(); Ray offsetRay = new Ray(new Vector3(ray.origin.x - brickPosition.x, ray.origin.y - brickPosition.y, ray.origin.z - brickPosition.z), ray.direction); float distance; RayEntersCellFromCell(offsetRay, firstIntersection, dummyVector3i, out distance); Vector3i adjacentLocal = dummyVector3i; Vector3i adjacentWorld = adjacentLocal + brickEntry.bounds.min; tree.SetVoxelAt(adjacentWorld.x, adjacentWorld.y, adjacentWorld.z, materialAtlas.GetMaterialId(voxelMaterial)); Vector3i cellModified = new Vector3i(adjacentWorld.x / tree.BrickDimensionX, adjacentWorld.y / tree.BrickDimensionY, adjacentWorld.z / tree.BrickDimensionZ); OctreeEntry <Brick> modified = tree.GetAt(cellModified.x, cellModified.y, cellModified.z); outChangedBricks.Enqueue(modified); if (adjacentLocal.x == 0) { modified = tree.GetAt(cellModified.x - 1, cellModified.y, cellModified.z); outChangedBricks.Enqueue(modified); } if (adjacentLocal.y == 0) { modified = tree.GetAt(cellModified.x, cellModified.y - 1, cellModified.z); outChangedBricks.Enqueue(modified); } if (adjacentLocal.z == 0) { modified = tree.GetAt(cellModified.x, cellModified.y, cellModified.z - 1); outChangedBricks.Enqueue(modified); } return(true); }
static void SaveChunksFromRegion(Vector3i regionCoord, Queue <Chunk> chunks) { if (chunks.Count <= 0) { return; } #if _DEBUG Debug.Log("saving " + chunks.Count + " chunks from region " + regionCoord); watch.Restart(); #endif #if DONT_SAVE lock (chunksSaved) { // ya all these chunks saved... uhhhuh while (chunks.Count > 0) { chunksSaved.Enqueue(chunks.Dequeue()); } } #else // check if region file exists string regionFile = RegionFileName(regionCoord); bool alreadyExisted = File.Exists(regionFile); FileStream stream = null; try { stream = File.Open(regionFile, FileMode.OpenOrCreate); // will open or create if not there if (alreadyExisted) // load lookup table if file was there already { int c = stream.Read(table, 0, TABLE_SIZE); Assert.IsTrue(c == TABLE_SIZE); } else { Array.Clear(table, 0, TABLE_SIZE); // make sure its 0s stream.Write(table, 0, TABLE_SIZE); // write table at beginning of new file (will get updated at end as well) } while (chunks.Count > 0) { Chunk chunk = chunks.Dequeue(); // get encoded chunk bytes int bytes = EncodeChunk(byteBuffer, chunk); int requiredSectors = (bytes + 4) / SECTOR_SIZE + 1; // +4 for length uint Assert.IsTrue(requiredSectors < 256); // max for 1 byte sector count // get position in lookup table int sectorOffset; // starting point of this chunk in terms of number of sectors from front byte sectorCount; // how many sectors this chunk takes up GetTableEntry(chunk.cp, out sectorOffset, out sectorCount); // if no entry in table, add one to the end if (sectorOffset == 0 && sectorCount == 0) { sectorOffset = (int)((stream.Length - TABLE_SIZE) / SECTOR_SIZE); sectorCount = (byte)requiredSectors; SetTableEntry(chunk.cp, sectorOffset, sectorCount); // append new table entry } else if (requiredSectors != sectorCount) { Assert.IsTrue(requiredSectors > 0 && sectorCount > 0); SetTableEntry(chunk.cp, sectorOffset, (byte)requiredSectors); // update table entry int endOfSectorPos = TABLE_SIZE + (sectorOffset + sectorCount) * SECTOR_SIZE; ShiftRegionData(stream, requiredSectors - sectorCount, endOfSectorPos); } writer.Start(uintBuffer); writer.Write((uint)bytes); writer.Finish(); writer.GetData(fourBytes); // add padding to end of byteBuffer int pad = SECTOR_SIZE * requiredSectors - bytes - 4; Assert.IsTrue(pad >= 0 && pad <= SECTOR_SIZE); Array.Clear(byteBuffer, bytes, pad); // seek to correct spot in file stream.Seek(TABLE_SIZE + sectorOffset * SECTOR_SIZE, SeekOrigin.Begin); long streamPos = stream.Position; // write data length followed by padded chunk data stream.Write(fourBytes, 0, 4); stream.Write(byteBuffer, 0, bytes + pad); Assert.IsTrue(stream.Position - streamPos == SECTOR_SIZE * requiredSectors); lock (chunksSaved) { chunksSaved.Enqueue(chunk); } } stream.Seek(0, SeekOrigin.Begin); stream.Write(table, 0, TABLE_SIZE); // write updated table back and close stream Assert.IsTrue((stream.Length - TABLE_SIZE) % SECTOR_SIZE == 0); } catch (Exception e) { Debug.Log(e.Message); } finally { if (stream != null) { stream.Close(); } } #if _DEBUG Debug.Log("saved in " + watch.ElapsedMilliseconds + " ms"); #endif #endif }