public static Vector3 DFtoUnityTileCenter(DFCoord input) { Vector3 result = DFtoUnityCoord(input); result.y += tileHeight / 2; return(result); }
public void CopySliceTo(DFCoord newSliceOrigin, DFCoord newSliceSize, MapDataStore target) { if (newSliceSize != target.SliceSize) { throw new UnityException("Mismatched slice sizes"); } var localNewSliceOrigin = WorldToLocalSpace(newSliceOrigin); if (!InSliceBoundsLocal(localNewSliceOrigin) || !InSliceBoundsLocal(localNewSliceOrigin + newSliceSize - new DFCoord(1, 1, 1))) { throw new UnityException("Can't slice outside of our slice bounds"); } for (int x = 0; x < newSliceSize.x; x++) { for (int y = 0; y < newSliceSize.y; y++) { for (int z = 0; z < newSliceSize.z; z++) { //pre-calculate it before we copy, because afterwards we won't have contextual data. if (tiles[localNewSliceOrigin.x + x, localNewSliceOrigin.y + y, localNewSliceOrigin.z + z].shape == TiletypeShape.RAMP) { tiles[localNewSliceOrigin.x + x, localNewSliceOrigin.y + y, localNewSliceOrigin.z + z].CalculateRampType(); } target.tiles[x, y, z] = tiles[localNewSliceOrigin.x + x, localNewSliceOrigin.y + y, localNewSliceOrigin.z + z]; target.tiles[x, y, z].container = target; target.tilesPresent[target.PresentIndex(x, y, z)] = tilesPresent[PresentIndex(localNewSliceOrigin.x + x, localNewSliceOrigin.y + y, localNewSliceOrigin.z + z)]; } } } target.SliceOrigin = newSliceOrigin; }
public void StoreTiles(RemoteFortressReader.MapBlock block) { bool setTiles = block.tiles.Count > 0; bool setLiquids = block.water.Count > 0 || block.magma.Count > 0; if (!setTiles && !setLiquids) { return; } for (int xx = 0; xx < 16; xx++) { for (int yy = 0; yy < 16; yy++) { DFCoord worldCoord = new DFCoord(block.map_x + xx, block.map_y + yy, block.map_z); DFCoord localCoord = WorldToLocalSpace(worldCoord); int netIndex = xx + (yy * 16); tilesPresent[PresentIndex(localCoord.x, localCoord.y, localCoord.z)] = true; if (setTiles) { tiles[localCoord.x, localCoord.y, localCoord.z].tileType = block.tiles[netIndex]; tiles[localCoord.x, localCoord.y, localCoord.z].material = block.materials[netIndex]; tiles[localCoord.x, localCoord.y, localCoord.z].base_material = block.base_materials[netIndex]; tiles[localCoord.x, localCoord.y, localCoord.z].layer_material = block.layer_materials[netIndex]; tiles[localCoord.x, localCoord.y, localCoord.z].vein_material = block.vein_materials[netIndex]; tiles[localCoord.x, localCoord.y, localCoord.z].construction_item = block.construction_items[netIndex]; } if (setLiquids) { tiles[localCoord.x, localCoord.y, localCoord.z].waterLevel = block.water[netIndex]; tiles[localCoord.x, localCoord.y, localCoord.z].magmaLevel = block.magma[netIndex]; } } } }
public void CopySliceTo(DFCoord newSliceOrigin, DFCoord newSliceSize, MapDataStore target) { if (newSliceSize != target.SliceSize) { throw new UnityException("Mismatched slice sizes"); } var localNewSliceOrigin = WorldToLocalSpace(newSliceOrigin); if (!InSliceBoundsLocal(localNewSliceOrigin) || !InSliceBoundsLocal(localNewSliceOrigin + newSliceSize - new DFCoord(1, 1, 1))) { throw new UnityException("Can't slice outside of our slice bounds"); } target.SliceOrigin = newSliceOrigin; for (int x = target.MinCoord.x; x < target.MaxCoord.x; x++) { for (int y = target.MinCoord.y; y < target.MaxCoord.y; y++) { for (int z = target.MinCoord.z; z < target.MaxCoord.z; z++) { if (this[x, y, z] == null) { target[x, y, z] = null; continue; } //pre-calculate it before we copy, because afterwards we won't have contextual data. if (this[x, y, z].shape == TiletypeShape.RAMP) { this[x, y, z].CalculateRampType(); } target[x, y, z] = this[x, y, z]; } } } }
public MapDataStore CopySlice(DFCoord newSliceOrigin, DFCoord newSliceSize) { MapDataStore target = new MapDataStore(newSliceOrigin, newSliceSize); CopySliceTo(newSliceOrigin, newSliceSize, target); return(target); }
public List <FlowInfo> this[DFCoord pos] { set { flowMap[pos] = value; dirty = true; } }
public static Vector3 DFtoUnityBottomCorner(DFCoord input) { Vector3 result = DFtoUnityCoord(input); result.x -= tileWidth / 2; result.z -= tileWidth / 2; return(result); }
private void Update() { if (DFConnection.Instance.EmbarkMapPosition != lastMapPos) { lastMapPos = DFConnection.Instance.EmbarkMapPosition; ClearAllBuildings(); } }
public void Update() { if (fortOrigin != DFConnection.Instance.EmbarkMapPosition) { fortOrigin = DFConnection.Instance.EmbarkMapPosition; GenerateMesh(); } }
// Enqueue a block for meshing; inclde public bool Enqueue(DFCoord targetLocation, bool tiles, bool liquids) { if (!GameMap.IsBlockCorner(targetLocation)) { throw new UnityException("Can't enqueue non-block-corners"); } if (!tiles && !liquids) { throw new UnityException("Why mesh something without tiles or liquids?"); } UnityEngine.Profiling.Profiler.BeginSample("BlockMesher.Enqueue"); // Using our object pool MapDataStore targetDataStore = AllocateBlockStore(); // Copy data if (!MapDataStore.Main.CopySliceTo(targetLocation, MapDataStore.BLOCK_SIZE, targetDataStore)) { UnityEngine.Profiling.Profiler.EndSample(); return(true); //it's empty, but it isn't a failure condition. } // In case we displace another block update Request redundant; lock (requestQueue) { // Will be { tiles: false, liquids: false, data: null } if we don't have anything queued redundant = requestQueue[targetLocation]; //if there's no existing queue member, don't add more than needed. if (redundant.data == null) { if (requestQueue.Count >= 16) { UnityEngine.Profiling.Profiler.EndSample(); return(false); } } Request meshRequest = new Request(); // If either request wanted liquids, do liquids; // If either request wanted tiles, do tiles. meshRequest.liquids = liquids || redundant.liquids; meshRequest.tiles = tiles || redundant.tiles; meshRequest.data = targetDataStore; requestQueue.EnqueueAndDisplace(targetLocation, meshRequest); } if (redundant.data != null) { lock (recycledBlocks) { // Object pooling! recycledBlocks.Push(redundant.data); } } UnityEngine.Profiling.Profiler.EndSample(); return(true); }
public void SendJumpCommand(DFCoord direction) { MoveCommandParams command = new MoveCommandParams(); command.direction = direction; if (jumpCommands.Count < jumpCommands.Capacity) { jumpCommands.Enqueue(command); } }
public void UpdateCenter(Vector3 pos) { DFCoord dfPos = UnityToDFCoord(pos); posXTile = dfPos.x; posYTile = dfPos.y; if (posZ != dfPos.z + 1) { posZ = dfPos.z + 1; } }
public void SendMoveCommand(DFCoord direction) { MoveCommandParams command = new MoveCommandParams { direction = direction }; if (moveCommands.Count < moveCommands.Capacity) { moveCommands.Enqueue(command); } }
/// <summary> /// Since tiles aren't updated as often as regular flows, they need to be in a separate list. /// </summary> /// <param name="pos"></param> /// <param name="flows"></param> public void SetTileFlows(DFCoord pos, List <FlowInfo> flows) { if (flows == null || flows.Count == 0) { tileFlowMap.Remove(pos); } else { tileFlowMap[pos] = flows; } dirty = true; }
public static BuildingInstance GetBuildingInfo(DFCoord pos) { if (Instance == null) { return(null); } if (!Instance.buildingInfoMap.ContainsKey(pos)) { return(null); } return(Instance.buildingInfoMap[pos]); }
void DebugHighlightRegion(DFCoord a, DFCoord b, Color color) { highlightLineMaterial.SetPass(0); Vector3 aVec = GameMap.DFtoUnityBottomCorner(a); Vector3 bVec = GameMap.DFtoUnityBottomCorner(b); Vector3 lowC = new Vector3( Mathf.Min(aVec.x, bVec.x), Mathf.Min(aVec.y, bVec.y), Mathf.Min(aVec.z, bVec.z) ); Vector3 upC = new Vector3( Mathf.Max(aVec.x, bVec.x) + GameMap.tileWidth, Mathf.Max(aVec.y, bVec.y) + GameMap.tileHeight, Mathf.Max(aVec.z, bVec.z) + GameMap.tileWidth ); // Bottom square GL.Begin(GL.LINES); GL.Color(color); GL.Vertex3(lowC.x, lowC.y, lowC.z); GL.Vertex3(lowC.x, lowC.y, upC.z); GL.Vertex3(lowC.x, lowC.y, upC.z); GL.Vertex3(upC.x, lowC.y, upC.z); GL.Vertex3(upC.x, lowC.y, upC.z); GL.Vertex3(upC.x, lowC.y, lowC.z); GL.Vertex3(upC.x, lowC.y, lowC.z); GL.Vertex3(lowC.x, lowC.y, lowC.z); // Vertical lines GL.Vertex3(lowC.x, lowC.y, lowC.z); GL.Vertex3(lowC.x, upC.y, lowC.z); GL.Vertex3(lowC.x, lowC.y, upC.z); GL.Vertex3(lowC.x, upC.y, upC.z); GL.Vertex3(upC.x, lowC.y, upC.z); GL.Vertex3(upC.x, upC.y, upC.z); GL.Vertex3(upC.x, lowC.y, lowC.z); GL.Vertex3(upC.x, upC.y, lowC.z); // Upper square GL.Vertex3(lowC.x, upC.y, lowC.z); GL.Vertex3(lowC.x, upC.y, upC.z); GL.Vertex3(lowC.x, upC.y, upC.z); GL.Vertex3(upC.x, upC.y, upC.z); GL.Vertex3(upC.x, upC.y, upC.z); GL.Vertex3(upC.x, upC.y, lowC.z); GL.Vertex3(upC.x, upC.y, lowC.z); GL.Vertex3(lowC.x, upC.y, lowC.z); GL.End(); }
public Tile?this[DFCoord coord] { get { DFCoord local = WorldToLocalSpace(coord); if (InSliceBoundsLocal(local.x, local.y, local.z) && tilesPresent[PresentIndex(local.x, local.y, local.z)]) { return(tiles[local.x, local.y, local.z]); } else { return(null); } } }
public Tile(MapDataStore container, DFCoord position) { this.container = container; this.position = position; tileType = default(int); material = default(MatPairStruct); base_material = default(MatPairStruct); layer_material = default(MatPairStruct); vein_material = default(MatPairStruct); construction_item = default(MatPairStruct); waterLevel = default(int); magmaLevel = default(int); rampType = 0; }
public Tile this[DFCoord coord] { get { DFCoord local = WorldToLocalSpace(coord); if (InSliceBoundsLocal(local.x, local.y, local.z)) { return(_tiles[local.x, local.y, local.z]); } else { return(null); } } private set { DFCoord local = WorldToLocalSpace(coord); if (InSliceBoundsLocal(local.x, local.y, local.z)) { if (value == null) { _tiles[local.x, local.y, local.z] = value; } else if (value.container == null) { value.container = this; _tiles[local.x, local.y, local.z] = value; } else if (value.container != this) { if (_tiles[local.x, local.y, local.z] == null) { _tiles[local.x, local.y, local.z] = new Tile(value); } else { _tiles[local.x, local.y, local.z].CopyFrom(value); } Tile tile = _tiles[local.x, local.y, local.z]; tile.container = this; tile.position = coord; } else { _tiles[local.x, local.y, local.z] = value; } } } }
public void InitOrModifyTile(DFCoord coord, int?tileType = null, MatPairStruct?material = null, MatPairStruct?base_material = null, MatPairStruct?layer_material = null, MatPairStruct?vein_material = null, int?waterLevel = null, int?magmaLevel = null, MatPairStruct?construction_item = null, int?rampType = null, BuildingStruct?buildingType = null, MatPairStruct?buildingMaterial = null, DFCoord2d?buildingLocalPos = null, BuildingDirection?buildingDirection = null, bool?hidden = null, byte?trunkPercent = null, DFCoord?positionOnTree = null, TileDigDesignation?digDesignation = null, List <Spatter> spatters = null) { if (!InSliceBounds(coord)) { throw new UnityException("Can't modify tile outside of slice"); } if (this[coord] == null) { this[coord] = new Tile(this, coord); } this[coord].Modify( tileType, material, base_material, layer_material, vein_material, waterLevel, magmaLevel, construction_item, rampType, buildingType, buildingMaterial, buildingLocalPos, buildingDirection, hidden, trunkPercent, positionOnTree, digDesignation, spatters ); }
public MapDataStore(DFCoord origin, DFCoord sliceSize) { if (sliceSize.x < 0 || sliceSize.x > MapSize.x || sliceSize.y < 0 || sliceSize.y > MapSize.y || sliceSize.z < 0 || sliceSize.z > MapSize.z) { throw new UnityException("Can't have a map slice outside the map!"); } if (sliceSize.x < 1 || sliceSize.y < 1 || sliceSize.z < 1) { throw new UnityException("Can't make map slice without any tiles"); } SliceSize = sliceSize; tiles = new Tile[SliceSize.x, SliceSize.y, SliceSize.z]; tilesPresent = new BitArray(PresentIndex(SliceSize.x-1, SliceSize.y-1, SliceSize.z-1)+1); Reset(); }
public void SetLiquidLevel(DFCoord coord, int liquidIndex, int liquidLevel) { switch (liquidIndex) { case WATER_INDEX: InitOrModifyTile(coord, waterLevel: liquidLevel); return; case MAGMA_INDEX: InitOrModifyTile(coord, magmaLevel: liquidLevel); return; default: throw new UnityException("No liquid with index " + liquidIndex); } }
static void Box(List <DFCoord> coordList, Vector3 start, Vector3 end) { DFCoord dfStart = new DFCoord(Mathf.FloorToInt(start.x), Mathf.FloorToInt(start.y), Mathf.FloorToInt(start.z)); DFCoord dfEnd = new DFCoord(Mathf.FloorToInt(end.x), Mathf.FloorToInt(end.y), Mathf.FloorToInt(end.z)); for (int x = Mathf.Min(dfStart.x, dfEnd.x); x <= Mathf.Max(dfStart.x, dfEnd.x); x++) { for (int y = Mathf.Min(dfStart.y, dfEnd.y); y <= Mathf.Max(dfStart.y, dfEnd.y); y++) { for (int z = Mathf.Min(dfStart.z, dfEnd.z); z <= Mathf.Max(dfStart.z, dfEnd.z); z++) { coordList.Add(new DFCoord(x, y, z)); } } } }
public MapDataStore(DFCoord origin, DFCoord sliceSize) { if (sliceSize.x < 0 || sliceSize.x > MapSize.x || sliceSize.y < 0 || sliceSize.y > MapSize.y || sliceSize.z < 0 || sliceSize.z > MapSize.z) { throw new UnityException("Can't have a map slice outside the map!"); } if (sliceSize.x < 1 || sliceSize.y < 1 || sliceSize.z < 1) { Debug.Log("Can't make map slice without any tiles, making a minimal sized one instead."); sliceSize.x = 16; sliceSize.y = 16; sliceSize.z = 1; } SliceSize = sliceSize; tiles = new Tile[SliceSize.x, SliceSize.y, SliceSize.z]; Reset(); }
public MapDataStore(DFCoord origin, DFCoord sliceSize) { if (sliceSize.x < 0 || sliceSize.x > MapSize.x || sliceSize.y < 0 || sliceSize.y > MapSize.y || sliceSize.z < 0 || sliceSize.z > MapSize.z) { throw new UnityException("Can't have a map slice outside the map!"); } if (sliceSize.x < 1 || sliceSize.y < 1 || sliceSize.z < 1) { throw new UnityException("Can't make map slice without any tiles"); } SliceSize = sliceSize; tiles = new Tile[SliceSize.x, SliceSize.y, SliceSize.z]; tilesPresent = new BitArray(PresentIndex(SliceSize.x - 1, SliceSize.y - 1, SliceSize.z - 1) + 1); Reset(); }
public void CopyFromRemote(WorldMap remoteMap, WorldMap mainMap) { if (remoteMap == null) { Debug.Log("Didn't get world map!"); return; } width = remoteMap.world_width; height = remoteMap.world_height; worldNameEnglish = remoteMap.name_english; embarkTileOffset = new Vector3((remoteMap.map_x * 16), 0, -(remoteMap.map_y * 16)); regionOrigin = new DFCoord(remoteMap.map_x * 16, remoteMap.map_y * 16, 0); SetPosition(mainMap); InitArrays(); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { int index = y * width + x; elevation[x, y] = remoteMap.elevation[index]; if (remoteMap.water_elevation != null && remoteMap.water_elevation.Count > index) { water_elevation[x, y] = remoteMap.water_elevation[index]; } else { water_elevation[x, y] = 99; } rainfall[x, y] = remoteMap.rainfall[index]; vegetation[x, y] = remoteMap.vegetation[index]; temperature[x, y] = remoteMap.temperature[index]; evilness[x, y] = remoteMap.evilness[index]; drainage[x, y] = remoteMap.drainage[index]; volcanism[x, y] = remoteMap.volcanism[index]; savagery[x, y] = remoteMap.savagery[index]; salinity[x, y] = remoteMap.salinity[index]; if (remoteMap.river_tiles != null && remoteMap.river_tiles.Count > index) { rivers[x, y] = remoteMap.river_tiles[index]; } } } GenerateMesh(); }
public MapDataStore(DFCoord origin, DFCoord sliceSize) { if (sliceSize.x < 0 || sliceSize.x > MapSize.x || sliceSize.y < 0 || sliceSize.y > MapSize.y || sliceSize.z < 0 || sliceSize.z > MapSize.z) { throw new UnityException("Can't have a map slice outside the map!"); } if (sliceSize.x < 1 || sliceSize.y < 1 || sliceSize.z < 1) { Debug.Log("Can't make map slice without any tiles, making a minimal sized one instead."); sliceSize.x = 16; sliceSize.y = 16; sliceSize.z = 1; } SliceSize = sliceSize; _tiles = new Tile[SliceSize.x + 2, SliceSize.y + 2, SliceSize.z + 2]; //add two so we get edges. Reset(); }
private void InitMap() { mapSize = DFConnection.Instance.EmbarkMapSize; if (texture != null) { texture.Release(); } texture = new RenderTexture(mapSize.x * 16 * multiSample, mapSize.y * 16 * multiSample, 24); texture.useMipMap = true; texture.autoGenerateMips = true; rawImage.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, mapSize.x * 16); rawImage.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, mapSize.y * 16); rawImage.texture = texture; cam.targetTexture = texture; float nearPlane = (mapSize.y * 8 * GameMap.tileWidth) / Mathf.Tan(cam.fieldOfView * 0.5f * Mathf.Deg2Rad); cam.farClipPlane = nearPlane + ((GameSettings.Instance.rendering.drawRangeDown + 1) * GameMap.tileHeight); cam.nearClipPlane = nearPlane; }
//// Does about what you'd think it does. //void Start() //{ // enabled = false; // DFConnection.RegisterConnectionCallback(this.OnConnectToDF); //} //void OnConnectToDF() //{ // enabled = true; // CopyFromRemote(DFConnection.Instance.NetWorldMap, DFConnection.Instance.NetMapInfo); //} bool IsInCoords(DFCoord min, DFCoord max, int x, int y) { if (x < min.x) { return(false); } if (y < min.y) { return(false); } if (x >= max.x) { return(false); } if (y >= max.y) { return(false); } return(true); }
private DFCoord2d GetRotatedLocalCoord(DFCoord worldCoord, BuildingInstance building) { switch (building.direction) { case BuildingDirection.NORTH: return(new DFCoord2d(worldCoord.x - building.pos_x_min, worldCoord.y - building.pos_y_min)); case BuildingDirection.EAST: return(new DFCoord2d(worldCoord.y - building.pos_y_min, building.pos_x_max - worldCoord.x)); case BuildingDirection.SOUTH: return(new DFCoord2d(building.pos_x_max - worldCoord.x, building.pos_y_max - worldCoord.y)); case BuildingDirection.WEST: return(new DFCoord2d(building.pos_y_max - worldCoord.y, worldCoord.x - building.pos_x_min)); default: return(new DFCoord2d(worldCoord.x - building.pos_x_min, worldCoord.y - building.pos_y_min)); } }
public void InitOrModifyTile(DFCoord coord, int?tileType = null, MatPairStruct?material = null, MatPairStruct?base_material = null, MatPairStruct?layer_material = null, MatPairStruct?vein_material = null, int?waterLevel = null, int?magmaLevel = null, MatPairStruct?construction_item = null, int?rampType = null) { DFCoord local = WorldToLocalSpace(coord); if (!InSliceBoundsLocal(local.x, local.y, local.z)) { throw new UnityException("Can't modify tile outside of slice"); } tilesPresent[PresentIndex(local.x, local.y, local.z)] = true; tiles[local.x, local.y, local.z].Modify(tileType, material, base_material, layer_material, vein_material, waterLevel, magmaLevel, construction_item, rampType); }
public int GetLiquidLevel(DFCoord coord, int liquidIndex) { var tile = this[coord]; if (tile == null) { return(0); } switch (liquidIndex) { case WATER_INDEX: return(tile.Value.waterLevel); case MAGMA_INDEX: return(tile.Value.magmaLevel); default: throw new UnityException("No liquid with index " + liquidIndex); } }
public Tile? this[DFCoord coord] { get { DFCoord local = WorldToLocalSpace(coord); if (InSliceBoundsLocal(local.x, local.y, local.z) && tilesPresent[PresentIndex(local.x, local.y, local.z)]) { return tiles[local.x, local.y, local.z]; } else { return null; } } }
//// Does about what you'd think it does. //void Start() //{ // enabled = false; // DFConnection.RegisterConnectionCallback(this.OnConnectToDF); //} //void OnConnectToDF() //{ // enabled = true; // CopyFromRemote(DFConnection.Instance.NetWorldMap, DFConnection.Instance.NetMapInfo); //} bool IsInCoords(DFCoord min, DFCoord max, int x, int y) { if (x < min.x) return false; if (y < min.y) return false; if (x >= max.x) return false; if (y >= max.y) return false; return true; }
// Helpers public DFCoord WorldToLocalSpace(DFCoord coord) { return coord - SliceOrigin; }
public void SetLiquidLevel(DFCoord coord, int liquidIndex, int liquidLevel) { switch (liquidIndex) { case WATER_INDEX: InitOrModifyTile(coord, waterLevel: liquidLevel); return; case MAGMA_INDEX: InitOrModifyTile(coord, magmaLevel: liquidLevel); return; default: throw new UnityException("No liquid with index "+liquidIndex); } }
public bool InSliceBounds(DFCoord loc) { return InSliceBoundsLocal(WorldToLocalSpace(loc)); }
public int GetLiquidLevel(DFCoord coord, int liquidIndex) { var tile = this[coord]; if (tile == null) return 0; switch (liquidIndex) { case WATER_INDEX: return tile.Value.waterLevel; case MAGMA_INDEX: return tile.Value.magmaLevel; default: throw new UnityException("No liquid with index "+liquidIndex); } }
public MapDataStore CopySlice(DFCoord newSliceOrigin, DFCoord newSliceSize) { MapDataStore target = new MapDataStore(newSliceOrigin, newSliceSize); CopySliceTo(newSliceOrigin, newSliceSize, target); return target; }
private DFCoord2d GetRotatedLocalCoord(DFCoord worldCoord, BuildingInstance building) { switch (building.direction) { case BuildingDirection.NORTH: return new DFCoord2d(worldCoord.x - building.pos_x_min, worldCoord.y - building.pos_y_min); case BuildingDirection.EAST: return new DFCoord2d(worldCoord.y - building.pos_y_min, building.pos_x_max - worldCoord.x); case BuildingDirection.SOUTH: return new DFCoord2d(building.pos_x_max - worldCoord.x, building.pos_y_max - worldCoord.y); case BuildingDirection.WEST: return new DFCoord2d(building.pos_y_max - worldCoord.y, worldCoord.x - building.pos_x_min); default: return new DFCoord2d(worldCoord.x - building.pos_x_min, worldCoord.y - building.pos_y_min); } }
public Tile(MapDataStore container, DFCoord position) { this.container = container; this.position = position; tileType = default(int); material = default(MatPairStruct); base_material = default(MatPairStruct); layer_material = default(MatPairStruct); vein_material = default(MatPairStruct); construction_item = default(MatPairStruct); waterLevel = default(int); magmaLevel = default(int); rampType = 0; buildingMaterial = default(MatPairStruct); buildingType = default(BuildingStruct); buildingLocalPos = default(DFCoord2d); buildingDirection = 0; Hidden = false; trunkPercent = 0; positionOnTree = default(DFCoord); digDesignation = TileDigDesignation.NO_DIG; spatters = null; }
public void CopyFromRemote(WorldMap remoteMap, WorldMap mainMap) { if (remoteMap == null) { Debug.Log("Didn't get world map!"); return; } width = remoteMap.world_width; height = remoteMap.world_height; worldNameEnglish = remoteMap.name_english; embarkTileOffset = new Vector3((remoteMap.map_x * 16), 0, -(remoteMap.map_y * 16)); regionOrigin = new DFCoord(remoteMap.map_x * 16, remoteMap.map_y * 16, 0); SetPosition(mainMap); InitArrays(); for (int x = 0; x < width; x++) for (int y = 0; y < height; y++) { int index = y * width + x; tiles[x, y] = new RegionTile(remoteMap, index); } GenerateMesh(); }
public Tile this[DFCoord coord] { get { DFCoord local = WorldToLocalSpace(coord); if (InSliceBoundsLocal(local.x, local.y, local.z)) { return _tiles[local.x, local.y, local.z]; } else { return null; } } private set { DFCoord local = WorldToLocalSpace(coord); if (InSliceBoundsLocal(local.x, local.y, local.z)) { if (value == null) _tiles[local.x, local.y, local.z] = value; else if (value.container == null) { value.container = this; _tiles[local.x, local.y, local.z] = value; } else if (value.container != this) { if (_tiles[local.x, local.y, local.z] == null) _tiles[local.x, local.y, local.z] = new Tile(value); else _tiles[local.x, local.y, local.z].CopyFrom(value); Tile tile = _tiles[local.x, local.y, local.z]; tile.container = this; tile.position = coord; } else _tiles[local.x, local.y, local.z] = value; } } }
/// <summary> /// A big method, but pretty simple. /// Walk through tiles (starting in current one); /// in each tile, check if the ray is actively hitting something. /// If it's not, find the wall of the tile the ray exits through, /// go to that tile, and repeat. /// </summary> /// <param name="ray"></param> /// <param name="tileCoord"></param> /// <param name="unityCoord"></param> /// <returns>True, if hit.</returns> public static bool FindCurrentTarget(Ray ray, out DFCoord tileCoord, out Vector3 unityCoord) { if (!HitsMapCube(ray)) { tileCoord = default(DFCoord); unityCoord = default(Vector3); return false; } // In each tile, we find its bottom corner, and then add these // values to find the coordinates of the walls. // If the ray increases on this axis, the offset will be the // width of the tile along that axis; if the ray decreases, // the offset will be 0 (since we're already on that wall.) float xWallOffset, yWallOffset, zWallOffset; // When we pass through a tile and hit this wall, how do we increment // our DFCoord? DFCoord xHitIncrement, yHitIncrement, zHitIncrement; if (ray.direction.x > 0) { xWallOffset = GameMap.tileWidth; xHitIncrement = new DFCoord(1, 0, 0); } else { xWallOffset = 0; xHitIncrement = new DFCoord(-1, 0, 0); } if (ray.direction.z > 0) { zWallOffset = GameMap.tileWidth; zHitIncrement = new DFCoord(0, -1, 0); } else { zWallOffset = 0; zHitIncrement = new DFCoord(0, 1, 0); } if (ray.direction.y > 0) { yWallOffset = GameMap.tileHeight; yHitIncrement = new DFCoord(0, 0, 1); } else { yWallOffset = 0; yHitIncrement = new DFCoord(0, 0, -1); } // If this is true and we go onto a tile outside the map, // we stop iterating (since we can't hit anything.) bool haveHitMap = false; // The coordinate we start at. DFCoord currentCoord = GameMap.UnityToDFCoord(ray.origin); // The coordinate of the last tile wall intersection. Vector3 lastHit = ray.origin; // Cheap hack to keep from looping forever if we screw up somehow. for (int _insurance = 0; _insurance < MAXIMUM_CHECKS; _insurance++) { // Make sure we don't move backwards somehow. if ((lastHit.x - ray.origin.x) / ray.direction.x < 0) { throw new UnityException("Negative distance multiplier?"); } // Get the corner of the current tile. Vector3 cornerCoord = GameMap.DFtoUnityBottomCorner(currentCoord); // Are we in the selectable area of the map? if (!InMapBounds(currentCoord) || GameMap.Instance.PosZ <= currentCoord.z) { // No. if (haveHitMap) { // But we have been before; // we've entered and exited the map without hitting anything. tileCoord = default(DFCoord); unityCoord = default(Vector3); return false; } } else { // We are in the map. haveHitMap = true; Tile currentTile = Main[currentCoord.x, currentCoord.y, currentCoord.z]; // Are we in a real tile? if (currentTile != null) { // Yes. switch (currentTile.shape) { case TiletypeShape.EMPTY: case TiletypeShape.NO_SHAPE: // We're not hitting anything, though. break; //case RemoteFortressReader.TiletypeShape.SHRUB: //case RemoteFortressReader.TiletypeShape.SAPLING: case TiletypeShape.WALL: case TiletypeShape.FORTIFICATION: //case RemoteFortressReader.TiletypeShape.TRUNK_BRANCH: case TiletypeShape.TWIG: // We must be hitting things. // (maybe adjust shrub, saplings out of this group?) tileCoord = currentCoord; unityCoord = lastHit; return true; case TiletypeShape.RAMP: { // Check if we're in the ramp. // (that we're in the tile is implied.) if (Between(cornerCoord.y, lastHit.y, cornerCoord.y + GameMap.floorHeight + (GameMap.tileHeight / 2))) { tileCoord = currentCoord; unityCoord = lastHit; return true; } // Check if we enter the ramp; same way we check wall intersections. float floorY = cornerCoord.y + GameMap.floorHeight + (GameMap.tileHeight / 2); float toFloorMult = (floorY - ray.origin.y) / ray.direction.y; Vector3 floorIntercept = ray.origin + ray.direction * toFloorMult; if (Between(cornerCoord.x, floorIntercept.x, cornerCoord.x + GameMap.tileWidth) && Between(cornerCoord.z, floorIntercept.z, cornerCoord.z + GameMap.tileWidth)) { tileCoord = currentCoord; unityCoord = lastHit; return true; } } break; case TiletypeShape.FLOOR: case TiletypeShape.BOULDER: case TiletypeShape.PEBBLES: case TiletypeShape.BROOK_TOP: case TiletypeShape.SAPLING: case TiletypeShape.SHRUB: case TiletypeShape.BRANCH: case TiletypeShape.TRUNK_BRANCH: { // Check if we're in the floor. // (that we're in the tile is implied.) if (Between(cornerCoord.y, lastHit.y, cornerCoord.y + GameMap.floorHeight)) { tileCoord = currentCoord; unityCoord = lastHit; return true; } // Check if we enter the floor; same way we check wall intersections. float floorY = cornerCoord.y + GameMap.floorHeight; float toFloorMult = (floorY - ray.origin.y) / ray.direction.y; Vector3 floorIntercept = ray.origin + ray.direction * toFloorMult; if (Between(cornerCoord.x, floorIntercept.x, cornerCoord.x + GameMap.tileWidth) && Between(cornerCoord.z, floorIntercept.z, cornerCoord.z + GameMap.tileWidth)) { tileCoord = currentCoord; unityCoord = lastHit; return true; } } break; } } } // Didn't hit anything in the tile; figure out which wall we're hitting & walk to that tile. { float xMult = (cornerCoord.x + xWallOffset - ray.origin.x) / ray.direction.x; Vector3 xIntercept = ray.origin + ray.direction * xMult; if (Between(cornerCoord.z, xIntercept.z, cornerCoord.z + GameMap.tileWidth) && Between(cornerCoord.y, xIntercept.y, cornerCoord.y + GameMap.tileHeight)) { lastHit = xIntercept; currentCoord += xHitIncrement; continue; } } { float zMult = (cornerCoord.z + zWallOffset - ray.origin.z) / ray.direction.z; Vector3 zIntercept = ray.origin + ray.direction * zMult; if (Between(cornerCoord.x, zIntercept.x, cornerCoord.x + GameMap.tileWidth) && Between(cornerCoord.y, zIntercept.y, cornerCoord.y + GameMap.tileHeight)) { lastHit = zIntercept; currentCoord += zHitIncrement; continue; } } { float yMult = (cornerCoord.y + yWallOffset - ray.origin.y) / ray.direction.y; Vector3 yIntercept = ray.origin + ray.direction * yMult; if (cornerCoord.x <= yIntercept.x && yIntercept.x <= cornerCoord.x + GameMap.tileWidth && cornerCoord.z <= yIntercept.z && yIntercept.z <= cornerCoord.z + GameMap.tileWidth) { lastHit = yIntercept; currentCoord += yHitIncrement; continue; } } // We haven't found a wall to hit. // This shouldn't happen, but occasionally does. //throw new UnityException("Didn't hit any tile walls?"); } // We went the maximum amount of time without hitting anything tileCoord = default(DFCoord); unityCoord = default(Vector3); return false; }
// Called from DFConnection.InitStatics public static void InitMainMap(int xSize, int ySize, int zSize) { MapSize = new DFCoord(xSize, ySize, zSize); _main = new MapDataStore(new DFCoord(0,0,0), MapSize); }
public static bool InMapBounds(DFCoord coord) { return 0 <= coord.x && coord.x < MapSize.x && 0 <= coord.y && coord.y < MapSize.y && 0 <= coord.z && coord.z < MapSize.z; }
// Helpers public DFCoord WorldToLocalSpace(DFCoord coord) { return coord - SliceOrigin + new DFCoord(1, 1, 1); }
public void CopySliceTo(DFCoord newSliceOrigin, DFCoord newSliceSize, MapDataStore target) { if (newSliceSize != target.SliceSize) { throw new UnityException("Mismatched slice sizes"); } var localNewSliceOrigin = WorldToLocalSpace(newSliceOrigin); if (!InSliceBoundsLocal(localNewSliceOrigin) || !InSliceBoundsLocal(localNewSliceOrigin + newSliceSize - new DFCoord(1,1,1))) { throw new UnityException("Can't slice outside of our slice bounds"); } for (int x = 0; x < newSliceSize.x; x++) { for (int y = 0; y < newSliceSize.y; y++) { for (int z = 0; z < newSliceSize.z; z++) { //pre-calculate it before we copy, because afterwards we won't have contextual data. if (tiles[localNewSliceOrigin.x + x, localNewSliceOrigin.y + y, localNewSliceOrigin.z + z].shape == TiletypeShape.RAMP) tiles[localNewSliceOrigin.x + x, localNewSliceOrigin.y + y, localNewSliceOrigin.z + z].CalculateRampType(); target.tiles[x, y, z] = tiles[localNewSliceOrigin.x+x, localNewSliceOrigin.y+y, localNewSliceOrigin.z+z]; target.tiles[x, y, z].container = target; target.tilesPresent[target.PresentIndex(x, y, z)] = tilesPresent[PresentIndex(localNewSliceOrigin.x+x, localNewSliceOrigin.y+y, localNewSliceOrigin.z+z)]; } } } target.SliceOrigin = newSliceOrigin; }
public void InitOrModifyTile(DFCoord coord, int? tileType = null, MatPairStruct? material = null, MatPairStruct? base_material = null, MatPairStruct? layer_material = null, MatPairStruct? vein_material = null, int? waterLevel = null, int? magmaLevel = null, MatPairStruct? construction_item = null, int? rampType = null) { DFCoord local = WorldToLocalSpace(coord); if (!InSliceBoundsLocal(local.x, local.y, local.z)) { throw new UnityException("Can't modify tile outside of slice"); } tilesPresent[PresentIndex(local.x, local.y, local.z)] = true; tiles[local.x, local.y, local.z].Modify(tileType, material, base_material, layer_material, vein_material, waterLevel, magmaLevel, construction_item, rampType); }
public void InitOrModifyTile(DFCoord coord, int? tileType = null, MatPairStruct? material = null, MatPairStruct? base_material = null, MatPairStruct? layer_material = null, MatPairStruct? vein_material = null, int? waterLevel = null, int? magmaLevel = null, MatPairStruct? construction_item = null, int? rampType = null, BuildingStruct? buildingType = null, MatPairStruct? buildingMaterial = null, DFCoord2d? buildingLocalPos = null, BuildingDirection? buildingDirection = null, bool? hidden = null, byte? trunkPercent = null, DFCoord? positionOnTree = null, TileDigDesignation? digDesignation = null, List<Spatter> spatters = null) { if (!InSliceBounds(coord)) { throw new UnityException("Can't modify tile outside of slice"); } if (this[coord] == null) this[coord] = new Tile(this, coord); this[coord].Modify( tileType, material, base_material, layer_material, vein_material, waterLevel, magmaLevel, construction_item, rampType, buildingType, buildingMaterial, buildingLocalPos, buildingDirection, hidden, trunkPercent, positionOnTree, digDesignation, spatters ); }
public DFCoord LocalToWorldSpace(DFCoord coord) { return coord + SliceOrigin; }
public void StoreTiles(RemoteFortressReader.MapBlock block, out bool setTiles, out bool setLiquids, out bool setSpatters) { setTiles = block.tiles.Count > 0; setLiquids = block.water.Count > 0 || block.magma.Count > 0; setSpatters = block.spatterPile.Count > 0; if (!setTiles && !setLiquids) return; for (int xx = 0; xx < 16; xx++) for (int yy = 0; yy < 16; yy++) { DFCoord worldCoord = new DFCoord(block.map_x + xx, block.map_y + yy, block.map_z); if (!InSliceBounds(worldCoord)) { Debug.LogError(worldCoord + " is out of bounds for " + MapSize); return; } int netIndex = xx + (yy * 16); if (this[worldCoord] == null) this[worldCoord] = new Tile(this, worldCoord); if (block.tiles.Count > 0) { this[worldCoord].tileType = block.tiles[netIndex]; this[worldCoord].material = block.materials[netIndex]; this[worldCoord].base_material = block.base_materials[netIndex]; this[worldCoord].layer_material = block.layer_materials[netIndex]; this[worldCoord].vein_material = block.vein_materials[netIndex]; if (block.construction_items != null && block.construction_items.Count > netIndex) this[worldCoord].construction_item = block.construction_items[netIndex]; else this[worldCoord].construction_item = new MatPairStruct(-1, -1); if (block.tree_percent != null && block.tree_percent.Count > netIndex) { this[worldCoord].trunkPercent = (byte)block.tree_percent[netIndex]; this[worldCoord].positionOnTree = new DFCoord(block.tree_x[netIndex], block.tree_y[netIndex], block.tree_z[netIndex]); } else { this[worldCoord].trunkPercent = 0; this[worldCoord].positionOnTree = new DFCoord(0,0,0); } } if (setLiquids) { this[worldCoord].waterLevel = block.water[netIndex]; this[worldCoord].magmaLevel = block.magma[netIndex]; if (this[worldCoord].Hidden != block.hidden[netIndex]) { this[worldCoord].Hidden = block.hidden[netIndex]; setTiles = true; } if (block.tile_dig_designation != null && block.tile_dig_designation.Count > netIndex) { if (this[worldCoord].digDesignation != block.tile_dig_designation[netIndex]) { this[worldCoord].digDesignation = block.tile_dig_designation[netIndex]; setTiles = true; } } } if(setSpatters) { this[worldCoord].spatters = block.spatterPile[netIndex].spatters; } } foreach (var building in block.buildings) { if (building.building_type.building_type == 30) continue; // We won't do civzones right now. for (int xx = building.pos_x_min; xx <= building.pos_x_max; xx++) for (int yy = building.pos_y_min; yy <= building.pos_y_max; yy++) { if((building.building_type.building_type == 29) && building.room != null && building.room.extents.Count > 0) { int buildingLocalX = xx - building.room.pos_x; int buildingLocalY = yy - building.room.pos_y; if (building.room.extents[buildingLocalY * building.room.width + buildingLocalX] == 0) continue; } DFCoord worldCoord = new DFCoord(xx,yy, block.map_z); DFCoord2d buildingLocalCoord = GetRotatedLocalCoord(worldCoord, building);// = new DFCoord2d(xx - building.pos_x_min, yy - building.pos_y_min); if (!InSliceBounds(worldCoord)) { Debug.LogError(worldCoord + " is out of bounds for " + MapSize); continue; } if (this[worldCoord] == null) this[worldCoord] = new Tile(this, worldCoord); this[worldCoord].buildingType = building.building_type; this[worldCoord].buildingMaterial = building.material; this[worldCoord].buildingLocalPos = buildingLocalCoord; this[worldCoord].buildingDirection = building.direction; } } }
public void StoreTiles(RemoteFortressReader.MapBlock block) { bool setTiles = block.tiles.Count > 0; bool setLiquids = block.water.Count > 0 || block.magma.Count > 0; if (!setTiles && !setLiquids) return; for (int xx = 0; xx < 16; xx++) for (int yy = 0; yy < 16; yy++) { DFCoord worldCoord = new DFCoord(block.map_x + xx, block.map_y + yy, block.map_z); DFCoord localCoord = WorldToLocalSpace(worldCoord); int netIndex = xx + (yy * 16); tilesPresent[PresentIndex(localCoord.x, localCoord.y, localCoord.z)] = true; if (setTiles) { tiles[localCoord.x, localCoord.y, localCoord.z].tileType = block.tiles[netIndex]; tiles[localCoord.x, localCoord.y, localCoord.z].material = block.materials[netIndex]; tiles[localCoord.x, localCoord.y, localCoord.z].base_material = block.base_materials[netIndex]; tiles[localCoord.x, localCoord.y, localCoord.z].layer_material = block.layer_materials[netIndex]; tiles[localCoord.x, localCoord.y, localCoord.z].vein_material = block.vein_materials[netIndex]; tiles[localCoord.x, localCoord.y, localCoord.z].construction_item = block.construction_items[netIndex]; } if (setLiquids) { tiles[localCoord.x, localCoord.y, localCoord.z].waterLevel = block.water[netIndex]; tiles[localCoord.x, localCoord.y, localCoord.z].magmaLevel = block.magma[netIndex]; } } }
public DFCoord LocalToWorldSpace(DFCoord coord) { return coord + SliceOrigin - new DFCoord(1, 1, 1); }
bool InSliceBoundsLocal(DFCoord coord) { return InSliceBoundsLocal(coord.x, coord.y, coord.z); }
// Called from DFConnection.InitStatics public static void InitMainMap(int xSize, int ySize, int zSize) { MapSize = new DFCoord(xSize, ySize, zSize); _main = new MapDataStore(new DFCoord(0,0,0), MapSize); Debug.Log("Set main map to " + MapSize); }
public void Update() { if(fortOrigin != DFConnection.Instance.EmbarkMapPosition) { fortOrigin = DFConnection.Instance.EmbarkMapPosition; GenerateMesh(); } }
public bool CopySliceTo(DFCoord newSliceOrigin, DFCoord newSliceSize, MapDataStore target) { bool success = false; if (newSliceSize != target.SliceSize) { throw new UnityException("Mismatched slice sizes"); } var localNewSliceOrigin = WorldToLocalSpace(newSliceOrigin); if (!InSliceBoundsLocal(localNewSliceOrigin) || !InSliceBoundsLocal(localNewSliceOrigin + newSliceSize - new DFCoord(1,1,1))) { throw new UnityException("Can't slice outside of our slice bounds"); } target.SliceOrigin = newSliceOrigin; for (int x = target.MinCoord.x; x < target.MaxCoord.x; x++) { for (int y = target.MinCoord.y; y < target.MaxCoord.y; y++) { for (int z = target.MinCoord.z; z < target.MaxCoord.z; z++) { if (this[x, y, z] == null) { target[x, y, z] = null; continue; } //pre-calculate it before we copy, because afterwards we won't have contextual data. if (this[x,y,z].shape == TiletypeShape.RAMP) this[x, y, z].CalculateRampType(); target[x, y, z] = this[x,y,z]; success = true; } } } return success; }