diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 011d76f2a7..b83f384f85 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -394,7 +394,7 @@ item.thorium.description=A dense, radioactive metal used as structural support a item.silicon.name=Silicon item.silcion.description=An extremely useful semiconductor, with applications in solar panels and many complex electronics. item.plastanium.name=Plastanium -item.plastanium.description=A light, ductile material used in advanced aircraft and and fragmentation ammunition. +item.plastanium.description=A light, ductile material used in advanced aircraft and fragmentation ammunition. item.phase-matter.name=Phase Matter item.surge-alloy.name=Surge Alloy item.biomatter.name=Biomatter diff --git a/core/src/io/anuke/mindustry/content/UnitTypes.java b/core/src/io/anuke/mindustry/content/UnitTypes.java index d158f76747..656a24274b 100644 --- a/core/src/io/anuke/mindustry/content/UnitTypes.java +++ b/core/src/io/anuke/mindustry/content/UnitTypes.java @@ -18,6 +18,7 @@ public class UnitTypes implements ContentList { maxVelocity = 0.8f; ammoCapacity = 0; range = 50f; + healSpeed = 0.05f; health = 45; }}; @@ -67,7 +68,7 @@ public class UnitTypes implements ContentList { health = 45; buildPower = 0.9f; minePower = 1.1f; - healSpeed = 0.3f; + healSpeed = 0.09f; }}; } diff --git a/core/src/io/anuke/mindustry/content/blocks/DebugBlocks.java b/core/src/io/anuke/mindustry/content/blocks/DebugBlocks.java index 7b0b040f1e..023e8bbc3c 100644 --- a/core/src/io/anuke/mindustry/content/blocks/DebugBlocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/DebugBlocks.java @@ -15,7 +15,7 @@ import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.PowerBlock; import io.anuke.mindustry.world.blocks.distribution.Sorter; -import io.anuke.mindustry.world.blocks.power.PowerDistributor; +import io.anuke.mindustry.world.blocks.power.PowerNode; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.scene.ui.ButtonGroup; import io.anuke.ucore.scene.ui.ImageButton; @@ -36,7 +36,7 @@ public class DebugBlocks extends BlockList implements ContentList{ } }; - powerInfinite = new PowerDistributor("powerinfinite") { + powerInfinite = new PowerNode("powerinfinite") { { powerCapacity = 10000f; powerSpeed = 100f; diff --git a/core/src/io/anuke/mindustry/content/blocks/PowerBlocks.java b/core/src/io/anuke/mindustry/content/blocks/PowerBlocks.java index 13941497d9..a64c817c8a 100644 --- a/core/src/io/anuke/mindustry/content/blocks/PowerBlocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/PowerBlocks.java @@ -58,20 +58,20 @@ public class PowerBlocks extends BlockList implements ContentList { health = 600; }}; - battery = new PowerGenerator("battery") {{ + battery = new PowerDistributor("battery") {{ powerCapacity = 320f; }}; - batteryLarge = new PowerGenerator("battery-large") {{ + batteryLarge = new PowerDistributor("battery-large") {{ size = 3; powerCapacity = 2000f; }}; - powerNode = new PowerDistributor("power-node") {{ + powerNode = new PowerNode("power-node") {{ shadow = "shadow-round-1"; }}; - powerNodeLarge = new PowerDistributor("power-node-large") {{ + powerNodeLarge = new PowerNode("power-node-large") {{ size = 2; powerSpeed = 1f; maxNodes = 5; diff --git a/core/src/io/anuke/mindustry/content/blocks/ProductionBlocks.java b/core/src/io/anuke/mindustry/content/blocks/ProductionBlocks.java index e3dcee6d8e..91b60aed91 100644 --- a/core/src/io/anuke/mindustry/content/blocks/ProductionBlocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/ProductionBlocks.java @@ -79,6 +79,7 @@ public class ProductionBlocks extends BlockList implements ContentList { result = Liquids.oil; inputLiquid = Liquids.water; updateEffect = BlockFx.pulverize; + liquidCapacity = 50f; updateEffectChance = 0.05f; inputLiquidUse = 0.3f; powerUse = 0.6f; diff --git a/core/src/io/anuke/mindustry/content/bullets/TurretBullets.java b/core/src/io/anuke/mindustry/content/bullets/TurretBullets.java index 76c93298e8..673378e629 100644 --- a/core/src/io/anuke/mindustry/content/bullets/TurretBullets.java +++ b/core/src/io/anuke/mindustry/content/bullets/TurretBullets.java @@ -39,7 +39,9 @@ public class TurretBullets extends BulletList implements ContentList { { pierce = true; hitTiles = false; - drag = 0.3f; + collides = false; + collidesTiles = false; + drag = 0.03f; } @Override diff --git a/core/src/io/anuke/mindustry/entities/effect/Fire.java b/core/src/io/anuke/mindustry/entities/effect/Fire.java index db9576cba3..8ca852fbac 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Fire.java +++ b/core/src/io/anuke/mindustry/entities/effect/Fire.java @@ -7,6 +7,7 @@ import com.badlogic.gdx.utils.Pools; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.mindustry.content.StatusEffects; +import io.anuke.mindustry.content.bullets.TurretBullets; import io.anuke.mindustry.content.fx.EnvironmentFx; import io.anuke.mindustry.entities.Damage; import io.anuke.mindustry.entities.TileEntity; @@ -117,6 +118,10 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable GridPoint2 p = Mathf.select(Geometry.d4); Tile other = world.tile(tile.x + p.x, tile.y + p.y); create(other); + + if(Mathf.chance(0.05 * Timers.delta() * Mathf.clamp(flammability / 10.0))){ + CallEntity.createBullet(TurretBullets.fireball, x, y, Mathf.random(360f)); + } } if(Mathf.chance(0.1 * Timers.delta())){ diff --git a/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java index 99e0e03b33..41c27f6d8f 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java @@ -2,9 +2,10 @@ package io.anuke.mindustry.ui.fragments; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.files.FileHandle; +import io.anuke.mindustry.content.bullets.TurretBullets; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.effect.Fire; +import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.entities.units.UnitType; import io.anuke.mindustry.game.Team; @@ -60,7 +61,7 @@ public class DebugFragment implements Fragment { row(); new button("fire", () -> { for (int i = 0; i < 10; i++) { - Fire.create(world.tileWorld(player.x + Mathf.range(20), player.y + Mathf.range(20))); + Bullet.create(TurretBullets.fireball, player, player.x, player.y, Mathf.random(360f)); } }); row(); diff --git a/core/src/io/anuke/mindustry/world/BaseBlock.java b/core/src/io/anuke/mindustry/world/BaseBlock.java index f405a5159b..a3f4598f22 100644 --- a/core/src/io/anuke/mindustry/world/BaseBlock.java +++ b/core/src/io/anuke/mindustry/world/BaseBlock.java @@ -128,7 +128,9 @@ public abstract class BaseBlock { next = next.target(); if(next.block().hasLiquids && tile.entity.liquids.amount > 0f){ - if(next.entity.liquids.liquid == tile.entity.liquids.liquid || next.entity.liquids.amount <= 0.01f) { + + if((next.entity.liquids.liquid == tile.entity.liquids.liquid || next.entity.liquids.amount <= 0.01f) && + next.block().acceptLiquid(next, tile, tile.entity.liquids.liquid, 0f)) { float ofract = next.entity.liquids.amount / next.block().liquidCapacity; float fract = tile.entity.liquids.amount / liquidCapacity; float flow = Math.min(Mathf.clamp((fract - ofract) * (1f)) * (liquidCapacity), tile.entity.liquids.amount); diff --git a/core/src/io/anuke/mindustry/world/blocks/power/PowerDistributor.java b/core/src/io/anuke/mindustry/world/blocks/power/PowerDistributor.java index c094deb1f5..743e49ed9b 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/PowerDistributor.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerDistributor.java @@ -1,345 +1,55 @@ package io.anuke.mindustry.world.blocks.power; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.IntArray; -import io.anuke.annotations.Annotations.Loc; -import io.anuke.annotations.Annotations.Remote; -import io.anuke.mindustry.entities.Player; +import com.badlogic.gdx.math.GridPoint2; import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.gen.CallBlocks; -import io.anuke.mindustry.graphics.Layer; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.net.In; import io.anuke.mindustry.world.Edges; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.PowerBlock; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.StatUnit; -import io.anuke.ucore.core.Settings; import io.anuke.ucore.core.Timers; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.graphics.Shapes; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Translator; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; +public class PowerDistributor extends PowerBlock { -import static io.anuke.mindustry.Vars.*; - -public class PowerDistributor extends PowerBlock{ - public static final float thicknessScl = 0.7f; - public static final float flashScl = 0.12f; - - //last distribution block placed - private static int lastPlaced = -1; - - protected Translator t1 = new Translator(); - protected Translator t2 = new Translator(); - - protected float laserRange = 6; - protected float powerSpeed = 0.5f; - protected int maxNodes = 3; - - public PowerDistributor(String name){ - super(name); - expanded = true; - layer = Layer.power; - powerCapacity = 5f; - configurable = true; - } - - @Override - public void setBars(){} - - @Override - public void placed(Tile tile) { - Tile before = world.tile(lastPlaced); - if(linkValid(tile, before) && before.block() instanceof PowerDistributor){ - CallBlocks.linkPowerDistributors(null, tile, before); - } - - lastPlaced = tile.packedPosition(); - } - - @Override - public void setStats(){ - super.setStats(); - - stats.add(BlockStat.powerRange, laserRange, StatUnit.blocks); - stats.add(BlockStat.powerTransferSpeed, powerSpeed * 60, StatUnit.powerSecond); - } - - @Override - public void update(Tile tile){ - distributeLaserPower(tile); + public PowerDistributor(String name) { + super(name); } - @Override - public boolean onConfigureTileTapped(Tile tile, Tile other){ - DistributorEntity entity = tile.entity(); - other = other.target(); + protected void distributePower(Tile tile){ + TileEntity entity = tile.entity; + int sources = 0; - if(linkValid(tile, other)){ - if(linked(tile, other)){ - CallBlocks.unlinkPowerDistributors(null, tile, other); - }else if(entity.links.size < maxNodes){ - CallBlocks.linkPowerDistributors(null, tile, other); - } - return false; - } - return true; - } - - @Override - public void drawSelect(Tile tile){ - super.drawSelect(tile); - - Draw.color(Palette.power); - Lines.stroke(1f); - - Lines.poly(Edges.getPixelPolygon(laserRange), tile.worldx() - tilesize/2, tile.worldy() - tilesize/2, tilesize); - - Draw.reset(); - } - - @Override - public void drawConfigure(Tile tile){ - DistributorEntity entity = tile.entity(); - - Draw.color(Palette.accent); - - Lines.stroke(1f); - Lines.square(tile.drawx(), tile.drawy(), - tile.block().size * tilesize / 2f + 1f + Mathf.absin(Timers.time(), 4f, 1f)); - - Lines.stroke(1f); - - Lines.poly(Edges.getPixelPolygon(laserRange), tile.worldx() - tilesize/2, tile.worldy() - tilesize/2, tilesize); - - Draw.color(Palette.power); - - for(int x = (int)(tile.x - laserRange); x <= tile.x + laserRange; x ++){ - for(int y = (int)(tile.y - laserRange); y <= tile.y + laserRange; y ++){ - Tile link = world.tile(x, y); - if(link != null) link = link.target(); - - if(link != tile && linkValid(tile, link)){ - boolean linked = linked(tile, link); - Draw.color(linked ? Palette.place : Palette.breakInvalid); - - Lines.square(link.drawx(), link.drawy(), - link.block().size * tilesize / 2f + 1f + (linked ? 0f : Mathf.absin(Timers.time(), 4f, 1f))); - - if(entity.links.size >= maxNodes && !linked){ - Draw.color(); - Draw.rect("cross-" + link.block().size, link.drawx(), link.drawy()); - } - } - } - } - - Draw.reset(); - } - - @Override - public void drawPlace(int x, int y, int rotation, boolean valid){ - Draw.color(Palette.placing); - Lines.stroke(1f); - - Lines.poly(Edges.getPixelPolygon(laserRange), x * tilesize - tilesize/2, y * tilesize - tilesize/2, tilesize); - - Draw.reset(); - } - - @Override - public void drawLayer(Tile tile){ - if(!Settings.getBool("lasers")) return; - - DistributorEntity entity = tile.entity(); - - entity.laserColor = Mathf.lerpDelta(entity.laserColor, Mathf.clamp(entity.powerRecieved/(powerSpeed)), 0.08f); - - Draw.color(Palette.powerLaserFrom, Palette.powerLaserTo, entity.laserColor * (1f-flashScl) + Mathf.sin(Timers.time(), 1.7f, flashScl)); - - for(int i = 0; i < entity.links.size; i ++){ - Tile link = world.tile(entity.links.get(i)); - if(linkValid(tile, link)) drawLaser(tile, link); + for(GridPoint2 point : Edges.getEdges(size)){ + Tile target = tile.getNearby(point); + if(target != null && target.block().hasPower && + shouldDistribute(tile, target)) sources ++; } - Draw.color(); - } + if(sources == 0) return; - @Override - public float addPower(Tile tile, float amount){ - DistributorEntity entity = tile.entity(); + float result = entity.power.amount / sources; - if(entity.lastRecieved != threads.getFrameID()){ - entity.lastRecieved = threads.getFrameID(); - entity.powerRecieved = 0f; - } + for(GridPoint2 point : Edges.getEdges(size)){ + Tile target = tile.getNearby(point); + if(target == null) continue; + target = target.target(); - float added = super.addPower(tile, amount); - entity.powerRecieved += added; - return added; - } + if(target.block().hasPower && shouldDistribute(tile, target)){ + float diff = (tile.entity.power.amount / powerCapacity - target.entity.power.amount / target.block().powerCapacity)/1.4f; - protected boolean shouldDistribute(Tile tile, Tile other) { - return !(other.block() instanceof PowerDistributor) - || other.entity.power.amount / other.block().powerCapacity < tile.entity.power.amount / powerCapacity; - } - - protected void distributeLaserPower(Tile tile){ - DistributorEntity entity = tile.entity(); - - int targets = 0; - - //validate everything first. - for(int i = 0; i < entity.links.size; i ++){ - Tile target = world.tile(entity.links.get(i)); - if(!linkValid(tile, target)) { - entity.links.removeIndex(i); - i --; - }else if(shouldDistribute(tile, target)){ - targets ++; - } - } - - float result = Math.min(entity.power.amount / targets, powerSpeed * Timers.delta()); - - for(int i = 0; i < entity.links.size; i ++){ - Tile target = world.tile(entity.links.get(i)); - if(!shouldDistribute(tile, target)) continue; - - float transmit = Math.min(result * Timers.delta(), entity.power.amount); - if(target.block().acceptPower(target, tile, transmit)){ - entity.power.amount -= target.block().addPower(target, transmit); - } - } - } -/* - protected void link(Tile tile, Tile other){ - DistributorEntity entity = tile.entity(); - - if(!entity.links.contains(other.packedPosition())){ - entity.links.add(other.packedPosition()); - } - - if(other.block() instanceof PowerDistributor){ - DistributorEntity oe = other.entity(); - - if(!oe.links.contains(tile.packedPosition()) ){ - oe.links.add(tile.packedPosition()); - } - } - } - - protected void unlink(Tile tile, Tile other){ - DistributorEntity entity = tile.entity(); - - entity.links.removeValue(other.packedPosition()); - - if(other.block() instanceof PowerDistributor){ - DistributorEntity oe = other.entity(); - - oe.links.removeValue(tile.packedPosition()); - } - }*/ - - protected boolean linked(Tile tile, Tile other){ - return tile.entity().links.contains(other.packedPosition()); - } - - protected boolean linkValid(Tile tile, Tile link){ - if(!(tile != link && link != null && link.block().hasPower) - || link.block() instanceof PowerGenerator) return false; - - if(link.block() instanceof PowerDistributor){ - DistributorEntity oe = link.entity(); - - return Vector2.dst(tile.drawx(), tile.drawy(), link.drawx(), link.drawy()) <= Math.max(laserRange * tilesize, - ((PowerDistributor)link.block()).laserRange * tilesize) - tilesize/2f - + (link.block().size-1)*tilesize/2f + (tile.block().size-1)*tilesize/2f && - (oe.links.size < ((PowerDistributor)link.block()).maxNodes || oe.links.contains(tile.packedPosition())); - }else{ - return Vector2.dst(tile.drawx(), tile.drawy(), link.drawx(), link.drawy()) - <= laserRange * tilesize - tilesize/2f + (link.block().size-1)*tilesize; - } - } - - protected void drawLaser(Tile tile, Tile target){ - float x1 = tile.drawx(), y1 = tile.drawy(), - x2 = target.drawx(), y2 = target.drawy(); - - float angle1 = Angles.angle(x1, y1, x2, y2); - float angle2 = angle1 + 180f; - - t1.trns(angle1, tile.block().size * tilesize/2f + 1f); - t2.trns(angle2, target.block().size * tilesize/2f + 1f); - - Shapes.laser("laser", "laser-end", x1 + t1.x, y1 + t1.y, - x2 + t2.x, y2 + t2.y, thicknessScl); - } - - @Override - public TileEntity getEntity() { - return new DistributorEntity(); + float transmit = Math.min(result * Timers.delta(), diff * powerCapacity); + if(target.block().acceptPower(target, tile, transmit)){ + float transferred = target.block().addPower(target, transmit); + entity.power.amount -= transferred; + } + } + } } - @Remote(targets = Loc.both, called = Loc.both, in = In.blocks, forward = true) - public static void linkPowerDistributors(Player player, Tile tile, Tile other){ - DistributorEntity entity = tile.entity(); - - if(!entity.links.contains(other.packedPosition())){ - entity.links.add(other.packedPosition()); - } - - if(other.block() instanceof PowerDistributor){ - DistributorEntity oe = other.entity(); - - if(!oe.links.contains(tile.packedPosition()) ){ - oe.links.add(tile.packedPosition()); - } - } - } - - @Remote(targets = Loc.both, called = Loc.server, in = In.blocks, forward = true) - public static void unlinkPowerDistributors(Player player, Tile tile, Tile other){ - DistributorEntity entity = tile.entity(); - - entity.links.removeValue(other.packedPosition()); - - if(other.block() instanceof PowerDistributor){ - DistributorEntity oe = other.entity(); - - oe.links.removeValue(tile.packedPosition()); - } - } - - public static class DistributorEntity extends TileEntity{ - public float laserColor = 0f; - public float powerRecieved = 0f; - public long lastRecieved = 0; - public IntArray links = new IntArray(); - - @Override - public void write(DataOutputStream stream) throws IOException { - stream.writeShort(links.size); - for(int i = 0; i < links.size; i ++){ - stream.writeInt(links.get(i)); - } - } - - @Override - public void read(DataInputStream stream) throws IOException { - short amount = stream.readShort(); - for(int i = 0; i < amount; i ++){ - links.add(stream.readInt()); - } - } - } + protected boolean shouldDistribute(Tile tile, Tile other) { + return !(other.block() instanceof PowerGenerator) || other.entity.power.amount / other.block().powerCapacity < tile.entity.power.amount / powerCapacity; + } + @Override + public void update(Tile tile) { + distributePower(tile); + } } diff --git a/core/src/io/anuke/mindustry/world/blocks/power/PowerGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/PowerGenerator.java index 9ef2ab6874..03a8cbf43a 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/PowerGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerGenerator.java @@ -1,15 +1,10 @@ package io.anuke.mindustry.world.blocks.power; -import com.badlogic.gdx.math.GridPoint2; import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.world.Edges; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.PowerBlock; import io.anuke.mindustry.world.meta.BlockFlag; -import io.anuke.ucore.core.Timers; import io.anuke.ucore.util.EnumSet; -public class PowerGenerator extends PowerBlock { +public class PowerGenerator extends PowerDistributor { public PowerGenerator(String name) { super(name); @@ -17,43 +12,6 @@ public class PowerGenerator extends PowerBlock { flags = EnumSet.of(BlockFlag.producer); } - protected void distributePower(Tile tile){ - TileEntity entity = tile.entity; - int sources = 0; - - for(GridPoint2 point : Edges.getEdges(size)){ - Tile target = tile.getNearby(point); - if(target != null && target.block().hasPower && - shouldDistribute(tile, target)) sources ++; - } - - if(sources == 0) return; - - float result = entity.power.amount / sources; - - for(GridPoint2 point : Edges.getEdges(size)){ - Tile target = tile.getNearby(point); - if(target == null) continue; - target = target.target(); - - if(target.block().hasPower && shouldDistribute(tile, target)){ - float transmit = Math.min(result * Timers.delta(), entity.power.amount); - if(target.block().acceptPower(target, tile, transmit)){ - entity.power.amount -= target.block().addPower(target, transmit); - } - } - } - } - - protected boolean shouldDistribute(Tile tile, Tile other) { - return !(other.block() instanceof PowerGenerator) || other.entity.power.amount / other.block().powerCapacity < tile.entity.power.amount / powerCapacity; - } - - @Override - public void update(Tile tile) { - distributePower(tile); - } - @Override public TileEntity getEntity() { return new GeneratorEntity(); diff --git a/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java b/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java new file mode 100644 index 0000000000..cda82f6872 --- /dev/null +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java @@ -0,0 +1,317 @@ +package io.anuke.mindustry.world.blocks.power; + +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.utils.IntArray; +import io.anuke.annotations.Annotations.Loc; +import io.anuke.annotations.Annotations.Remote; +import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.gen.CallBlocks; +import io.anuke.mindustry.graphics.Layer; +import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.net.In; +import io.anuke.mindustry.world.Edges; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.PowerBlock; +import io.anuke.mindustry.world.meta.BlockStat; +import io.anuke.mindustry.world.meta.StatUnit; +import io.anuke.ucore.core.Settings; +import io.anuke.ucore.core.Timers; +import io.anuke.ucore.graphics.Draw; +import io.anuke.ucore.graphics.Lines; +import io.anuke.ucore.graphics.Shapes; +import io.anuke.ucore.util.Angles; +import io.anuke.ucore.util.Mathf; +import io.anuke.ucore.util.Translator; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import static io.anuke.mindustry.Vars.*; + +public class PowerNode extends PowerBlock{ + public static final float thicknessScl = 0.7f; + public static final float flashScl = 0.12f; + + //last distribution block placed + private static int lastPlaced = -1; + + protected Translator t1 = new Translator(); + protected Translator t2 = new Translator(); + + protected float laserRange = 6; + protected float powerSpeed = 0.5f; + protected int maxNodes = 3; + + public PowerNode(String name){ + super(name); + expanded = true; + layer = Layer.power; + powerCapacity = 5f; + configurable = true; + } + + @Override + public void setBars(){} + + @Override + public void placed(Tile tile) { + Tile before = world.tile(lastPlaced); + if(linkValid(tile, before) && before.block() instanceof PowerNode){ + CallBlocks.linkPowerDistributors(null, tile, before); + } + + lastPlaced = tile.packedPosition(); + } + + @Override + public void setStats(){ + super.setStats(); + + stats.add(BlockStat.powerRange, laserRange, StatUnit.blocks); + stats.add(BlockStat.powerTransferSpeed, powerSpeed * 60, StatUnit.powerSecond); + } + + @Override + public void update(Tile tile){ + distributeLaserPower(tile); + } + + @Override + public boolean onConfigureTileTapped(Tile tile, Tile other){ + DistributorEntity entity = tile.entity(); + other = other.target(); + + if(linkValid(tile, other)){ + if(linked(tile, other)){ + CallBlocks.unlinkPowerDistributors(null, tile, other); + }else if(entity.links.size < maxNodes){ + CallBlocks.linkPowerDistributors(null, tile, other); + } + return false; + } + return true; + } + + @Override + public void drawSelect(Tile tile){ + super.drawSelect(tile); + + Draw.color(Palette.power); + Lines.stroke(1f); + + Lines.poly(Edges.getPixelPolygon(laserRange), tile.worldx() - tilesize/2, tile.worldy() - tilesize/2, tilesize); + + Draw.reset(); + } + + @Override + public void drawConfigure(Tile tile){ + DistributorEntity entity = tile.entity(); + + Draw.color(Palette.accent); + + Lines.stroke(1f); + Lines.square(tile.drawx(), tile.drawy(), + tile.block().size * tilesize / 2f + 1f + Mathf.absin(Timers.time(), 4f, 1f)); + + Lines.stroke(1f); + + Lines.poly(Edges.getPixelPolygon(laserRange), tile.worldx() - tilesize/2, tile.worldy() - tilesize/2, tilesize); + + Draw.color(Palette.power); + + for(int x = (int)(tile.x - laserRange); x <= tile.x + laserRange; x ++){ + for(int y = (int)(tile.y - laserRange); y <= tile.y + laserRange; y ++){ + Tile link = world.tile(x, y); + if(link != null) link = link.target(); + + if(link != tile && linkValid(tile, link)){ + boolean linked = linked(tile, link); + Draw.color(linked ? Palette.place : Palette.breakInvalid); + + Lines.square(link.drawx(), link.drawy(), + link.block().size * tilesize / 2f + 1f + (linked ? 0f : Mathf.absin(Timers.time(), 4f, 1f))); + + if(entity.links.size >= maxNodes && !linked){ + Draw.color(); + Draw.rect("cross-" + link.block().size, link.drawx(), link.drawy()); + } + } + } + } + + Draw.reset(); + } + + @Override + public void drawPlace(int x, int y, int rotation, boolean valid){ + Draw.color(Palette.placing); + Lines.stroke(1f); + + Lines.poly(Edges.getPixelPolygon(laserRange), x * tilesize - tilesize/2, y * tilesize - tilesize/2, tilesize); + + Draw.reset(); + } + + @Override + public void drawLayer(Tile tile){ + if(!Settings.getBool("lasers")) return; + + DistributorEntity entity = tile.entity(); + + entity.laserColor = Mathf.lerpDelta(entity.laserColor, Mathf.clamp(entity.powerRecieved/(powerSpeed)), 0.08f); + + Draw.color(Palette.powerLaserFrom, Palette.powerLaserTo, entity.laserColor * (1f-flashScl) + Mathf.sin(Timers.time(), 1.7f, flashScl)); + + for(int i = 0; i < entity.links.size; i ++){ + Tile link = world.tile(entity.links.get(i)); + if(linkValid(tile, link)) drawLaser(tile, link); + } + + Draw.color(); + } + + @Override + public float addPower(Tile tile, float amount){ + DistributorEntity entity = tile.entity(); + + if(entity.lastRecieved != threads.getFrameID()){ + entity.lastRecieved = threads.getFrameID(); + entity.powerRecieved = 0f; + } + + float added = super.addPower(tile, amount); + entity.powerRecieved += added; + return added; + } + + protected boolean shouldDistribute(Tile tile, Tile other) { + return !(other.block() instanceof PowerNode) + || other.entity.power.amount / other.block().powerCapacity < tile.entity.power.amount / powerCapacity; + } + + protected void distributeLaserPower(Tile tile){ + DistributorEntity entity = tile.entity(); + + int targets = 0; + + //validate everything first. + for(int i = 0; i < entity.links.size; i ++){ + Tile target = world.tile(entity.links.get(i)); + if(!linkValid(tile, target)) { + entity.links.removeIndex(i); + i --; + }else if(shouldDistribute(tile, target)){ + targets ++; + } + } + + float result = Math.min(entity.power.amount / targets, powerSpeed * Timers.delta()); + + for(int i = 0; i < entity.links.size; i ++){ + Tile target = world.tile(entity.links.get(i)); + if(!shouldDistribute(tile, target)) continue; + + float transmit = Math.min(result * Timers.delta(), entity.power.amount); + if(target.block().acceptPower(target, tile, transmit)){ + entity.power.amount -= target.block().addPower(target, transmit); + } + } + } + + protected boolean linked(Tile tile, Tile other){ + return tile.entity().links.contains(other.packedPosition()); + } + + protected boolean linkValid(Tile tile, Tile link){ + if(!(tile != link && link != null && link.block().hasPower) + || link.block() instanceof PowerGenerator) return false; + + if(link.block() instanceof PowerNode){ + DistributorEntity oe = link.entity(); + + return Vector2.dst(tile.drawx(), tile.drawy(), link.drawx(), link.drawy()) <= Math.max(laserRange * tilesize, + ((PowerNode)link.block()).laserRange * tilesize) - tilesize/2f + + (link.block().size-1)*tilesize/2f + (tile.block().size-1)*tilesize/2f && + (oe.links.size < ((PowerNode)link.block()).maxNodes || oe.links.contains(tile.packedPosition())); + }else{ + return Vector2.dst(tile.drawx(), tile.drawy(), link.drawx(), link.drawy()) + <= laserRange * tilesize - tilesize/2f + (link.block().size-1)*tilesize; + } + } + + protected void drawLaser(Tile tile, Tile target){ + float x1 = tile.drawx(), y1 = tile.drawy(), + x2 = target.drawx(), y2 = target.drawy(); + + float angle1 = Angles.angle(x1, y1, x2, y2); + float angle2 = angle1 + 180f; + + t1.trns(angle1, tile.block().size * tilesize/2f + 1f); + t2.trns(angle2, target.block().size * tilesize/2f + 1f); + + Shapes.laser("laser", "laser-end", x1 + t1.x, y1 + t1.y, + x2 + t2.x, y2 + t2.y, thicknessScl); + } + + @Override + public TileEntity getEntity() { + return new DistributorEntity(); + } + + @Remote(targets = Loc.both, called = Loc.both, in = In.blocks, forward = true) + public static void linkPowerDistributors(Player player, Tile tile, Tile other){ + DistributorEntity entity = tile.entity(); + + if(!entity.links.contains(other.packedPosition())){ + entity.links.add(other.packedPosition()); + } + + if(other.block() instanceof PowerNode){ + DistributorEntity oe = other.entity(); + + if(!oe.links.contains(tile.packedPosition()) ){ + oe.links.add(tile.packedPosition()); + } + } + } + + @Remote(targets = Loc.both, called = Loc.server, in = In.blocks, forward = true) + public static void unlinkPowerDistributors(Player player, Tile tile, Tile other){ + DistributorEntity entity = tile.entity(); + + entity.links.removeValue(other.packedPosition()); + + if(other.block() instanceof PowerNode){ + DistributorEntity oe = other.entity(); + + oe.links.removeValue(tile.packedPosition()); + } + } + + public static class DistributorEntity extends TileEntity{ + public float laserColor = 0f; + public float powerRecieved = 0f; + public long lastRecieved = 0; + public IntArray links = new IntArray(); + + @Override + public void write(DataOutputStream stream) throws IOException { + stream.writeShort(links.size); + for(int i = 0; i < links.size; i ++){ + stream.writeInt(links.get(i)); + } + } + + @Override + public void read(DataInputStream stream) throws IOException { + short amount = stream.readShort(); + for(int i = 0; i < amount; i ++){ + links.add(stream.readInt()); + } + } + } + +} diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Fracker.java b/core/src/io/anuke/mindustry/world/blocks/production/Fracker.java index 867adfb98e..16465d6d45 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Fracker.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Fracker.java @@ -10,6 +10,7 @@ import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.StatUnit; import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; +import io.anuke.ucore.util.Log; public class Fracker extends SolidPump { protected Liquid inputLiquid; @@ -25,6 +26,7 @@ public class Fracker extends SolidPump { public Fracker(String name) { super(name); hasItems = true; + itemCapacity = 20; } @Override @@ -74,7 +76,7 @@ public class Fracker extends SolidPump { entity.accumulator -= itemUseTime; } - if(entity.input >= inputLiquidUse * Timers.delta() && entity.accumulator < itemUseTime){ + if(entity.input >= Math.min(inputLiquidUse * Timers.delta(), inputCapacity) && entity.accumulator < itemUseTime){ super.update(tile); entity.input -= inputLiquidUse * Timers.delta(); entity.accumulator += Timers.delta(); @@ -83,6 +85,11 @@ public class Fracker extends SolidPump { } } + @Override + public boolean acceptItem(Item item, Tile tile, Tile source) { + return item == inputItem && tile.entity.items.totalItems() < itemCapacity; + } + @Override public float handleAuxLiquid(Tile tile, Tile source, Liquid liquid, float amount) { if(liquid != inputLiquid){