protected void calculateAdjacency(IEnumerable<Box> boxes) { foreach (Box box in boxes) box.Adjacent = new List<Box>(); Dictionary<BoxRelationship, bool> relationships = new Dictionary<BoxRelationship, bool>(); foreach (Box box in boxes) { this.additions.Add(box); // Front face for (int x = box.X; x < box.X + box.Width; x++) { for (int y = box.Y; y < box.Y + box.Height; ) { Box adjacent = this.GetBox(x, y, box.Z + box.Depth); if (adjacent != null) { BoxRelationship relationship1 = new BoxRelationship { A = box, B = adjacent }; BoxRelationship relationship2 = new BoxRelationship { A = adjacent, B = box }; if (!relationships.ContainsKey(relationship1) && !relationships.ContainsKey(relationship2)) { relationships[relationship1] = true; box.Adjacent.Add(adjacent); adjacent.Adjacent.Add(box); } y = adjacent.Y + adjacent.Height; } else y++; } } // Back face for (int x = box.X; x < box.X + box.Width; x++) { for (int y = box.Y; y < box.Y + box.Height; ) { Box adjacent = this.GetBox(x, y, box.Z - 1); if (adjacent != null) { BoxRelationship relationship1 = new BoxRelationship { A = box, B = adjacent }; BoxRelationship relationship2 = new BoxRelationship { A = adjacent, B = box }; if (!relationships.ContainsKey(relationship1) && !relationships.ContainsKey(relationship2)) { relationships[relationship1] = true; box.Adjacent.Add(adjacent); adjacent.Adjacent.Add(box); } y = adjacent.Y + adjacent.Height; } else y++; } } // Right face for (int z = box.Z; z < box.Z + box.Depth; z++) { for (int y = box.Y; y < box.Y + box.Height; ) { Box adjacent = this.GetBox(box.X + box.Width, y, z); if (adjacent != null) { BoxRelationship relationship1 = new BoxRelationship { A = box, B = adjacent }; BoxRelationship relationship2 = new BoxRelationship { A = adjacent, B = box }; if (!relationships.ContainsKey(relationship1) && !relationships.ContainsKey(relationship2)) { relationships[relationship1] = true; box.Adjacent.Add(adjacent); adjacent.Adjacent.Add(box); } y = adjacent.Y + adjacent.Height; } else y++; } } // Left face for (int z = box.Z; z < box.Z + box.Depth; z++) { for (int y = box.Y; y < box.Y + box.Height; ) { Box adjacent = this.GetBox(box.X - 1, y, z); if (adjacent != null) { BoxRelationship relationship1 = new BoxRelationship { A = box, B = adjacent }; BoxRelationship relationship2 = new BoxRelationship { A = adjacent, B = box }; if (!relationships.ContainsKey(relationship1) && !relationships.ContainsKey(relationship2)) { relationships[relationship1] = true; box.Adjacent.Add(adjacent); adjacent.Adjacent.Add(box); } y = adjacent.Y + adjacent.Height; } else y++; } } // Top face for (int x = box.X; x < box.X + box.Width; x++) { for (int z = box.Z; z < box.Z + box.Depth; ) { Box adjacent = this.GetBox(x, box.Y + box.Height, z); if (adjacent != null) { BoxRelationship relationship1 = new BoxRelationship { A = box, B = adjacent }; BoxRelationship relationship2 = new BoxRelationship { A = adjacent, B = box }; if (!relationships.ContainsKey(relationship1) && !relationships.ContainsKey(relationship2)) { relationships[relationship1] = true; box.Adjacent.Add(adjacent); adjacent.Adjacent.Add(box); } z = adjacent.Z + adjacent.Depth; } else z++; } } // Bottom face for (int x = box.X; x < box.X + box.Width; x++) { for (int z = box.Z; z < box.Z + box.Depth; ) { Box adjacent = this.GetBox(x, box.Y - 1, z); if (adjacent != null) { BoxRelationship relationship1 = new BoxRelationship { A = box, B = adjacent }; BoxRelationship relationship2 = new BoxRelationship { A = adjacent, B = box }; if (!relationships.ContainsKey(relationship1) && !relationships.ContainsKey(relationship2)) { relationships[relationship1] = true; box.Adjacent.Add(adjacent); adjacent.Adjacent.Add(box); } z = adjacent.Z + adjacent.Depth; } else z++; } } } }
public override void InitializeProperties() { this.updateBounds(); if (Map.workThread == null) { Map.workThread = new Thread(new ThreadStart(Map.worker)); Map.workThread.Start(); this.main.Exiting += delegate(object a, EventArgs b) { Map.workThread.Abort(); }; Main m = this.main; Map.spawner = new Updater { delegate(float dt) { DynamicMapFactory factory = Factory.Get<DynamicMapFactory>(); BlockFactory blockFactory = Factory.Get<BlockFactory>(); List<SpawnGroup> spawns = null; lock (Map.spawns) { spawns = Map.spawns.ToList(); Map.spawns.Clear(); } foreach (SpawnGroup spawn in spawns) { List<DynamicMap> spawnedMaps = new List<DynamicMap>(); foreach (List<Box> island in spawn.Islands) { Box firstBox = island.First(); if (island.Count == 1 && firstBox.Width * firstBox.Height * firstBox.Depth == 1) { // Just create a temporary physics block instead of a full-blown map Coordinate coord = new Coordinate { X = firstBox.X, Y = firstBox.Y, Z = firstBox.Z }; Entity block = blockFactory.CreateAndBind(main); block.Get<Transform>().Matrix.Value = this.Transform; block.Get<Transform>().Position.Value = this.GetAbsolutePosition(coord); firstBox.Type.ApplyToBlock(block); block.Get<ModelInstance>().GetVector3Parameter("Offset").Value = this.GetRelativePosition(coord); main.Add(block); } else { Entity newMap = factory.CreateAndBind(spawn.Source.main, firstBox.X, firstBox.Y, firstBox.Z); newMap.Get<Transform>().Matrix.Value = spawn.Source.Transform; DynamicMap newMapComponent = newMap.Get<DynamicMap>(); newMapComponent.Offset.Value = spawn.Source.Offset; newMapComponent.BuildFromBoxes(island); spawn.Source.notifyEmptied(island.SelectMany(x => x.GetCoords()), newMapComponent); newMapComponent.notifyFilled(island.SelectMany(x => x.GetCoords()), spawn.Source); newMapComponent.Transform.Reset(); if (spawn.Source is DynamicMap) newMapComponent.IsAffectedByGravity.Value = ((DynamicMap)spawn.Source).IsAffectedByGravity; spawn.Source.main.Add(newMap); spawnedMaps.Add(newMapComponent); } } if (spawn.Callback != null) spawn.Callback(spawnedMaps); } } }; Map.spawner.EnabledInEditMode.Value = true; Map.spawner.EnabledWhenPaused.Value = true; this.main.AddComponent(Map.spawner); } this.Data.Get = delegate() { List<int> result = new List<int>(); lock (this.mutationLock) { List<Box> boxes = this.Chunks.Where(x => x.Data != null).SelectMany(x => x.Boxes).ToList(); bool[] modifications = this.simplify(boxes); this.simplify(boxes, modifications); this.applyChanges(boxes, modifications); boxes = this.Chunks.SelectMany(x => x.Boxes).ToList(); result.Add(boxes.Count); Dictionary<Box, int> indexLookup = new Dictionary<Box, int>(); int index = 0; foreach (Box box in boxes) { result.Add(box.X); result.Add(box.Y); result.Add(box.Z); result.Add(box.Width); result.Add(box.Height); result.Add(box.Depth); result.Add(box.Type.ID); for (int i = 0; i < 6; i++) { Surface surface = box.Surfaces[i]; result.Add(surface.MinU); result.Add(surface.MinV); result.Add(surface.MaxU); result.Add(surface.MaxV); } indexLookup.Add(box, index); index++; } Dictionary<BoxRelationship, bool> relationships = new Dictionary<BoxRelationship, bool>(); index = 0; foreach (Box box in boxes) { if (box.Adjacent == null) continue; foreach (Box adjacent in box.Adjacent) { if (box.Type.Permanent && adjacent.Type.Permanent) continue; BoxRelationship relationship1 = new BoxRelationship { A = box, B = adjacent }; BoxRelationship relationship2 = new BoxRelationship { A = adjacent, B = box }; if (!relationships.ContainsKey(relationship1) && !relationships.ContainsKey(relationship2)) { relationships[relationship1] = true; result.Add(index); result.Add(indexLookup[adjacent]); } } index++; } } return Map.serializeData(result.ToArray()); }; this.Data.Set = delegate(string value) { int[] data = Map.deserializeData(value); int boxCount = data[0]; Box[] boxes = new Box[boxCount]; const int boxDataSize = 31; for (int i = 0; i < boxCount; i++) { // Format: // x // y // z // width // height // depth // type // MinU, MinV, MaxU, MaxV for each of six surfaces int index = 1 + (i * boxDataSize); if (data[index + 6] != 0) { CellState state = WorldFactory.States[data[index + 6]]; int x = data[index], y = data[index + 1], z = data[index + 2], w = data[index + 3], h = data[index + 4], d = data[index + 5]; int chunkX = this.minX + ((x - this.minX) / this.chunkSize) * this.chunkSize, chunkY = this.minY + ((y - this.minY) / this.chunkSize) * this.chunkSize, chunkZ = this.minZ + ((z - this.minZ) / this.chunkSize) * this.chunkSize; int nextChunkX = this.minX + ((x + w - this.minX) / this.chunkSize) * this.chunkSize, nextChunkY = this.minY + ((y + h - this.minY) / this.chunkSize) * this.chunkSize, nextChunkZ = this.minZ + ((z + d - this.minZ) / this.chunkSize) * this.chunkSize; for (int ix = chunkX; ix <= nextChunkX; ix += this.chunkSize) { for (int iy = chunkY; iy <= nextChunkY; iy += this.chunkSize) { for (int iz = chunkZ; iz <= nextChunkZ; iz += this.chunkSize) { int bx = Math.Max(ix, x), by = Math.Max(iy, y), bz = Math.Max(iz, z); Box box = new Box { X = bx, Y = by, Z = bz, Width = Math.Min(x + w, ix + this.chunkSize) - bx, Height = Math.Min(y + h, iy + this.chunkSize) - by, Depth = Math.Min(z + d, iz + this.chunkSize) - bz, Type = state, Active = true, }; if (box.Width > 0 && box.Height > 0 && box.Depth > 0) { boxes[i] = box; Chunk chunk = this.GetChunk(bx, by, bz); if (chunk.DataBoxes == null) chunk.DataBoxes = new List<Box>(); chunk.DataBoxes.Add(box); box.Chunk = chunk; for (int x1 = box.X - chunk.X; x1 < box.X + box.Width - chunk.X; x1++) { for (int y1 = box.Y - chunk.Y; y1 < box.Y + box.Height - chunk.Y; y1++) { for (int z1 = box.Z - chunk.Z; z1 < box.Z + box.Depth - chunk.Z; z1++) chunk.Data[x1, y1, z1] = box; } } box.Surfaces[(int)Direction.NegativeX].W = box.X; box.Surfaces[(int)Direction.PositiveX].W = box.X + box.Width; box.Surfaces[(int)Direction.NegativeY].W = box.Y; box.Surfaces[(int)Direction.PositiveY].W = box.Y + box.Height; box.Surfaces[(int)Direction.NegativeZ].W = box.Z; box.Surfaces[(int)Direction.PositiveZ].W = box.Z + box.Depth; for (int j = 0; j < 6; j++) { int baseIndex = index + (j * 4) + 7; Surface surface = box.Surfaces[j]; surface.MinU = data[baseIndex + 0]; surface.MinV = data[baseIndex + 1]; surface.MaxU = data[baseIndex + 2]; surface.MaxV = data[baseIndex + 3]; } } } } } } } for (int i = 1 + (boxCount * boxDataSize); i < data.Length; i += 2) { Box box1 = boxes[data[i]], box2 = boxes[data[i + 1]]; if (box1 != null && box2 != null) { box1.Adjacent.Add(box2); box2.Adjacent.Add(box1); } } this.postDeserialization(); }; Map.Maps.Add(this); }