public override bool CanCombine(Point16 orig, Point16 dir) { NetworkCollection.HasFluidPipeAt(orig + dir, out FluidNetwork thisNet); NetworkCollection.HasFluidPipeAt(orig - dir, out FluidNetwork otherNet); var otherAxis = new Point16(dir.Y, dir.X); NetworkCollection.HasFluidPipeAt(orig + otherAxis, out FluidNetwork axisNet); NetworkCollection.HasFluidPipeAt(orig - otherAxis, out FluidNetwork otherAxisNet); Tile center = Framing.GetTileSafely(orig); if (ModContent.GetModTile(center.type) is TransportJunction) { //At this point, only one axis is being handled, so that's fine JunctionMerge merge = JunctionMergeable.mergeTypes[center.frameX / 18]; if (((merge & JunctionMerge.Fluids_LeftRight) != 0 && dir.X != 0) || ((merge & JunctionMerge.Fluids_UpDown) != 0 && dir.Y != 0)) { return(otherNet is null || (otherNet.liquidType == thisNet.liquidType && otherNet.gasType == thisNet.gasType)); } return(false); } //Not a junction at the center. Need to check every direction //All directions just need to be checked against this one bool hasConnOther = otherNet != null; bool hasConnAxis = axisNet != null; bool hasConnAxisOther = otherAxisNet != null; return((!hasConnOther || (otherNet.liquidType == thisNet.liquidType && otherNet.gasType == thisNet.gasType)) && (!hasConnAxis || (axisNet.liquidType == thisNet.liquidType && axisNet.gasType == thisNet.gasType)) && (!hasConnAxisOther || (otherAxisNet.liquidType == thisNet.liquidType && otherAxisNet.gasType == thisNet.gasType))); }
public static void TryImportGases <T>(this T entity, Point16 pipePos, int indexToExtract) where T : MachineEntity, IGasMachine { if (indexToExtract < 0 || indexToExtract >= entity.GasEntries.Length) { return; } var entry = entity.GasEntries[indexToExtract]; if (!NetworkCollection.HasFluidPipeAt(pipePos, out FluidNetwork net) || net.liquidType != MachineLiquidID.None || net.gasType == MachineGasID.None || !entry.isInput || (entry.id != MachineGasID.None && entry.id != net.gasType) || (entry.validTypes?.Length > 0 && Array.FindIndex(entry.validTypes, id => id == net.gasType) == -1)) { return; } Tile tile = Framing.GetTileSafely(pipePos); ModTile modTile = ModContent.GetModTile(tile.type); float rate = modTile is FluidTransportTile transport ? transport.ExportRate : (modTile is FluidPumpTile ? ModContent.GetInstance <FluidTransportTile>().ExportRate : -1); if (rate <= 0) { return; } float exported = Math.Min(rate, net.Capacity); if (exported + entry.current > entry.max) { exported = entry.max - entry.current; } if (exported <= 0) { return; } if (entry.id == MachineGasID.None) { entry.id = net.gasType; } entry.current += exported; net.StoredFluid -= exported; if (net.StoredFluid <= 0) { net.gasType = MachineGasID.None; } }
internal static void DrawFluid(Point16 tilePos, Texture2D texture, SpriteBatch spriteBatch) { Tile tile = Framing.GetTileSafely(tilePos); if (NetworkCollection.HasFluidPipeAt(tilePos, out FluidNetwork net)) { float factor = net.StoredFluid / net.Capacity; float alpha = net.liquidType != MachineLiquidID.None ? 1f : (net.gasType != MachineGasID.None ? 0.65f * factor : 0); if (alpha == 0) { return; } Color color = net.gasType != MachineGasID.None ? Capsule.GetBackColor(net.gasType) : net.liquidType != MachineLiquidID.None ? Capsule.GetBackColor(net.liquidType) : throw new Exception(); color = MiscUtils.MixLightColors(Lighting.GetColor(tilePos.X, tilePos.Y), color); var offset = MiscUtils.GetLightingDrawOffset(); var rect = new Rectangle(tile.frameX, tile.frameY, 16, 16); if (net.liquidType != MachineLiquidID.None) { //Adjust the frame to the proper subset int subsetHeight = texture.Frame(1, 4, 0, 0).Height; if (factor < 0.3f) { rect.X += subsetHeight * 3; } else if (factor < 0.6f) { rect.X += subsetHeight * 2; } else if (factor < 0.90f) { rect.X += subsetHeight; } } spriteBatch.Draw(texture, tilePos.ToWorldCoordinates(0, 0) + offset - Main.screenPosition, rect, color * alpha, 0f, Vector2.Zero, 1f, SpriteEffects.None, 0); } }
public static void TryExportLiquids <T>(this T entity, Point16 pumpPos, int indexToExtract) where T : MachineEntity, ILiquidMachine { if (indexToExtract < 0 || indexToExtract >= entity.LiquidEntries.Length) { return; } var entry = entity.LiquidEntries[indexToExtract]; if (!NetworkCollection.HasFluidPipeAt(pumpPos, out FluidNetwork net) || net.gasType != MachineGasID.None || entry.isInput || (entry.id != MachineLiquidID.None && net.liquidType != MachineLiquidID.None && entry.id != net.liquidType)) { return; } Tile tile = Framing.GetTileSafely(pumpPos); ModTile modTile = ModContent.GetModTile(tile.type); if (!(modTile is FluidPumpTile pump) || pump.GetConnectedMachine(pumpPos) != entity) { return; } float rate = pump.CapacityExtractedPerPump; float extracted = Math.Min(rate, entry.current); if (net.liquidType == MachineLiquidID.None) { net.liquidType = entry.id; } if (net.StoredFluid + extracted > net.Capacity) { extracted = net.Capacity - net.StoredFluid; } net.StoredFluid += extracted; entry.current -= extracted; if (entry.current <= 0) { entry.id = MachineLiquidID.None; } }
public override void PostDraw(int i, int j, SpriteBatch spriteBatch) { //Essentially a copy of ItemPumpTile, but for fluids Point16 pos = new Point16(i, j); NetworkCollection.HasFluidPipeAt(pos, out FluidNetwork net); //Uh oh if (net is null || !net.pumpTimers.TryGetValue(pos, out Timer pumpTimer)) { return; } int timer = pumpTimer.value; /* Graph: Cosine Sine * _|_ | ___ * .' | `. '. | .' `. * _______/___|___\_______ __\_________|/_______\___ * / | \ \ /| \ * '-__-' | '-__-' '-___-' | '- */ const float max = 34f; //Get the value on the graph for this sinusoidal movement float time = (timer - max / 4) / (max / 2); float radians = MathHelper.Pi * time; float sin = (float)Math.Sin(radians); //Move it up to above the X-axis sin += 1; //Then stretch it to fit the entire movement of the pump sin *= 8f / 2f; //Find the direction the offset needs to sway in Vector2 dir; int tileFrame = Framing.GetTileSafely(i, j).frameX / 18; switch (tileFrame) { case 0: dir = new Vector2(0, -1); break; case 1: dir = new Vector2(-1, 0); break; case 2: dir = new Vector2(0, 1); break; case 3: dir = new Vector2(1, 0); break; default: throw new Exception($"Inner TerraScience error -- Unexpected pump tile frame (ID: {tileFrame})"); } Texture2D tileTexture = Main.tileTexture[Type]; Texture2D texture = ModContent.GetTexture("TerraScience/Content/Tiles/Effect_FluidPumpTile_bar"); Rectangle tileSource = tileTexture.Frame(4, 1, tileFrame, 0); Rectangle frame = texture.Frame(4, 1, tileFrame, 0); frame.Width -= 2; frame.Height -= 2; Vector2 offset = MiscUtils.GetLightingDrawOffset(); Vector2 tilePos = pos.ToVector2() * 16 - Main.screenPosition + offset; Vector2 drawPos = tilePos + dir * sin; var color = Lighting.GetColor(i, j); spriteBatch.Draw(tileTexture, tilePos, tileSource, color, 0f, Vector2.Zero, 1f, SpriteEffects.None, 0); spriteBatch.Draw(texture, drawPos, frame, color, 0f, Vector2.Zero, 1f, SpriteEffects.None, 0); }
public override void PlaceInWorld(int i, int j, Item item) { // TODO: TileObject.CanPlace is throwing null-ref exceptions. why??? MachineItem mItem = item.modItem as MachineItem; GetDefaultParams(out _, out uint width, out uint height, out _); Point16 tePos = new Point16(i, j) - new Point16((int)width / 2, (int)height - 1); int type = (item.modItem as MachineItem).TileType; MachineEntity entity = TileUtils.tileToEntity[type]; if (entity.Find(tePos.X, tePos.Y) < 0) { int id = entity.Place(tePos.X, tePos.Y); if (Main.netMode == NetmodeID.MultiplayerClient) { NetMessage.SendData(MessageID.TileEntitySharing, remoteClient: -1, ignoreClient: Main.myPlayer, number: id); } } //Restore the saved data, if it exists MachineEntity placed = TileEntity.ByPosition[tePos] as MachineEntity; if (mItem.entityData != null) { placed.Load(mItem.entityData); } //If this structure has a powered entity on it, try to connect it to nearby networks Point16 checkOrig = tePos - new Point16(1, 1); bool canUseWires = placed is PoweredMachineEntity; bool canUseItemPipes = placed.SlotsCount > 0; bool canUseFluidPipes = placed is ILiquidMachine || placed is IGasMachine; for (int cx = checkOrig.X; cx < checkOrig.X + width + 2; cx++) { for (int cy = checkOrig.Y; cy < checkOrig.Y + height + 2; cy++) { WorldGen.TileFrame(cx, cy); //Ignore the corners if ((cx == 0 && cy == 0) || (cx == width + 1 && cy == 0) || (cx == 0 && cy == height + 1) || (cx == width + 1 && cy == height + 1)) { continue; } Point16 test = new Point16(cx, cy); if (canUseWires && NetworkCollection.HasWireAt(test, out WireNetwork wireNet)) { wireNet.AddMachine(placed); } if (canUseItemPipes && NetworkCollection.HasItemPipeAt(test, out ItemNetwork itemNet)) { itemNet.AddMachine(placed); itemNet.pipesConnectedToMachines.Add(test); } if (canUseFluidPipes && NetworkCollection.HasFluidPipeAt(test, out FluidNetwork fluidNet)) { fluidNet.AddMachine(placed); } } } if (Main.netMode == NetmodeID.MultiplayerClient) { NetMessage.SendTileRange(Main.myPlayer, checkOrig.X, checkOrig.Y, (int)width + 1, (int)height + 1); } }
public override void PostDrawTiles() { bool began = false; //Draw any junction stuff if (Main.LocalPlayer.HeldItem.modItem is TransportJunctionItem) { if (!string.IsNullOrWhiteSpace(TransportJunctionItem.display) && TransportJunctionItem.displayTimer >= 0) { Vector2 measure = Main.fontMouseText.MeasureString(TransportJunctionItem.display); Vector2 position = Main.LocalPlayer.Top - new Vector2(0, 20) - Main.screenPosition; Main.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, DepthStencilState.Default, RasterizerState.CullNone, null); began = true; Utils.DrawBorderStringFourWay(Main.spriteBatch, Main.fontMouseText, TransportJunctionItem.display, position.X, position.Y, Color.Yellow, Color.Black, measure / 2f); } if (TransportJunctionItem.displayTimer >= 0) { TransportJunctionItem.displayTimer--; } } else { TransportJunctionItem.display = null; TransportJunctionItem.displayTimer = -1; } if (!TechMod.debugging) { if (began) { Main.spriteBatch.End(); } return; } if (Main.LocalPlayer.HeldItem.type != ModContent.ItemType <DebugTool>() || Main.LocalPlayer.inventory[58].type == ModContent.ItemType <DebugTool>()) { if (began) { Main.spriteBatch.End(); } return; } Point16 mouse = Main.MouseWorld.ToTileCoordinates16(); bool hasWire = NetworkCollection.HasWireAt(mouse, out WireNetwork wireNet); bool hasItem = NetworkCollection.HasItemPipeAt(mouse, out ItemNetwork itemNet); bool hasFluid = NetworkCollection.HasFluidPipeAt(mouse, out FluidNetwork fluidNet); if (!hasWire && !hasItem && !hasFluid) { if (began) { Main.spriteBatch.End(); } return; } if (!began) { Main.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, DepthStencilState.Default, RasterizerState.CullNone, null); } //For every wire on-screen in the network the player's mouse is hovering over, draw an indicator if (hasWire) { DrawNetTiles(wireNet.GetEntries(), Color.Blue * 0.45f); } if (hasItem) { DrawNetTiles(itemNet.GetEntries(), Color.Green * 0.45f); } if (hasFluid) { DrawNetTiles(fluidNet.GetEntries(), Color.Red * 0.45f); } //Then draw what network is being targeted Vector2 offset = Main.MouseScreen + new Vector2(20, 20); bool hasOffset = false; if (wireNet != null) { hasOffset = true; Utils.DrawBorderStringFourWay(Main.spriteBatch, Main.fontMouseText, $"Targeting Wire Network (ID: {wireNet.ID})", offset.X, offset.Y, Color.Blue, Color.Black, Vector2.Zero); Utils.DrawBorderStringFourWay(Main.spriteBatch, Main.fontMouseText, $"Stored TF: {(float)wireNet.StoredFlux :0.##} / {(float)wireNet.Capacity :0.##} TF", offset.X, offset.Y += 20, Color.White, Color.Black, Vector2.Zero); Utils.DrawBorderStringFourWay(Main.spriteBatch, Main.fontMouseText, $"Exported Flux: {(float)wireNet.totalExportedFlux :0.##} TF/t ({(float)wireNet.totalExportedFlux * 60 :0.##} TF/s)", offset.X, offset.Y += 20, Color.White, Color.Black, Vector2.Zero); } if (itemNet != null) { Utils.DrawBorderStringFourWay(Main.spriteBatch, Main.fontMouseText, $"Targeting Item Network (ID: {itemNet.ID})", offset.X, !hasOffset ? offset.Y : (offset.Y += 20), Color.Green, Color.Black, Vector2.Zero); hasOffset = true; Utils.DrawBorderStringFourWay(Main.spriteBatch, Main.fontMouseText, $"Item Stacks in Network: {itemNet.paths.Count}", offset.X, offset.Y += 20, Color.White, Color.Black, Vector2.Zero); Utils.DrawBorderStringFourWay(Main.spriteBatch, Main.fontMouseText, $"Connected Chests: {itemNet.chests.Count}", offset.X, offset.Y += 20, Color.White, Color.Black, Vector2.Zero); Utils.DrawBorderStringFourWay(Main.spriteBatch, Main.fontMouseText, $"Pipes Connected to Chests: {itemNet.pipesConnectedToChests.Count}", offset.X, offset.Y += 20, Color.White, Color.Black, Vector2.Zero); Utils.DrawBorderStringFourWay(Main.spriteBatch, Main.fontMouseText, $"Pipes Connected to Machines: {itemNet.pipesConnectedToMachines.Count}", offset.X, offset.Y += 20, Color.White, Color.Black, Vector2.Zero); } if (fluidNet != null) { Utils.DrawBorderStringFourWay(Main.spriteBatch, Main.fontMouseText, $"Targeting Fluid Network (ID: {fluidNet.ID})", offset.X, !hasOffset ? offset.Y : (offset.Y += 20), Color.Red, Color.Black, Vector2.Zero); Utils.DrawBorderStringFourWay(Main.spriteBatch, Main.fontMouseText, $"Fluid Type: {(fluidNet.liquidType != MachineLiquidID.None ? fluidNet.liquidType.ProperEnumName() : fluidNet.gasType.ProperEnumName())}", offset.X, offset.Y += 20, Color.White, Color.Black, Vector2.Zero); Utils.DrawBorderStringFourWay(Main.spriteBatch, Main.fontMouseText, $"Stored Fluid: {fluidNet.StoredFluid :0.##} / {fluidNet.Capacity :0.##} L", offset.X, offset.Y += 20, Color.White, Color.Black, Vector2.Zero); } Main.spriteBatch.End(); }