oh no
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
package mindustry.world;
|
||||
|
||||
import arc.*;
|
||||
import arc.Graphics.*;
|
||||
import arc.Graphics.Cursor.*;
|
||||
import arc.audio.*;
|
||||
import arc.func.*;
|
||||
import arc.graphics.*;
|
||||
@@ -11,11 +9,11 @@ import arc.graphics.g2d.TextureAtlas.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.Array;
|
||||
import arc.struct.EnumSet;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.pooling.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.entities.*;
|
||||
@@ -26,18 +24,34 @@ import mindustry.graphics.MultiPacker.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.blocks.power.*;
|
||||
import mindustry.world.consumers.*;
|
||||
import mindustry.world.meta.*;
|
||||
import mindustry.world.meta.values.*;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
import static mindustry.Vars.tilesize;
|
||||
|
||||
public class Block extends BlockStorage{
|
||||
public class Block extends UnlockableContent{
|
||||
public static final int crackRegions = 8, maxCrackSize = 5;
|
||||
|
||||
public boolean hasItems;
|
||||
public boolean hasLiquids;
|
||||
public boolean hasPower;
|
||||
|
||||
public boolean outputsLiquid = false;
|
||||
public boolean consumesPower = true;
|
||||
public boolean outputsPower = false;
|
||||
|
||||
public int itemCapacity = 10;
|
||||
public float liquidCapacity = 10f;
|
||||
public float liquidPressure = 1f;
|
||||
|
||||
public final BlockStats stats = new BlockStats();
|
||||
public final BlockBars bars = new BlockBars();
|
||||
public final Consumers consumes = new Consumers();
|
||||
|
||||
/** whether this block has a tile entity that updates */
|
||||
public boolean update;
|
||||
/** whether this block has health and can be destroyed */
|
||||
@@ -140,12 +154,13 @@ public class Block extends BlockStorage{
|
||||
public boolean instantTransfer = false;
|
||||
public boolean alwaysUnlocked = false;
|
||||
|
||||
protected Prov<Tilec> entityType = null; //initialized later
|
||||
protected TextureRegion[] cacheRegions = {};
|
||||
protected Array<String> cacheRegionStrings = new Array<>();
|
||||
protected Prov<Tilec> entityType = TileEntity::create;
|
||||
protected ObjectMap<Class<?>, ConfigHandler> configurations = new ObjectMap<>();
|
||||
protected ObjectMap<Class<?>, Cons2> configurations = new ObjectMap<>();
|
||||
|
||||
protected Array<Tile> tempTiles = new Array<>();
|
||||
protected Array<Tilec> tempTileEnts = new Array<>();
|
||||
protected TextureRegion[] generatedIcons;
|
||||
protected TextureRegion[] variantRegions, editorVariantRegions;
|
||||
protected TextureRegion region, editorIcon;
|
||||
@@ -162,302 +177,6 @@ public class Block extends BlockStorage{
|
||||
this.solid = false;
|
||||
}
|
||||
|
||||
public boolean isAir(){
|
||||
return id == 0;
|
||||
}
|
||||
|
||||
public boolean canBreak(Tile tile){
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isBuildable(){
|
||||
return buildVisibility != BuildVisibility.hidden && buildVisibility != BuildVisibility.debugOnly;
|
||||
}
|
||||
|
||||
public boolean isStatic(){
|
||||
return cacheLayer == CacheLayer.walls;
|
||||
}
|
||||
|
||||
public void onProximityRemoved(Tile tile){
|
||||
if(tile.entity.power() != null){
|
||||
tile.block().powerGraphRemoved(tile);
|
||||
}
|
||||
}
|
||||
|
||||
public void onProximityAdded(Tile tile){
|
||||
if(tile.block().hasPower) tile.block().updatePowerGraph(tile);
|
||||
}
|
||||
|
||||
protected void updatePowerGraph(Tile tile){
|
||||
Tilec entity = tile.ent();
|
||||
|
||||
for(Tile other : getPowerConnections(tile, tempTiles)){
|
||||
if(other.entity.power() != null){
|
||||
other.entity.power().graph.add(entity.power().graph);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void powerGraphRemoved(Tile tile){
|
||||
if(tile.entity == null || tile.entity.power() == null){
|
||||
return;
|
||||
}
|
||||
|
||||
tile.entity.power().graph.remove(tile);
|
||||
for(int i = 0; i < tile.entity.power().links.size; i++){
|
||||
Tile other = world.tile(tile.entity.power().links.get(i));
|
||||
if(other != null && other.entity != null && other.entity.power() != null){
|
||||
other.entity.power().links.removeValue(tile.pos());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Array<Tile> getPowerConnections(Tile tile, Array<Tile> out){
|
||||
out.clear();
|
||||
if(tile == null || tile.entity == null || tile.entity.power() == null) return out;
|
||||
|
||||
for(Tile other : tile.entity.proximity()){
|
||||
if(other != null && other.entity != null && other.entity.power() != null
|
||||
&& !(consumesPower && other.block().consumesPower && !outputsPower && !other.block().outputsPower)
|
||||
&& !tile.entity.power().links.contains(other.pos())){
|
||||
out.add(other);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < tile.entity.power().links.size; i++){
|
||||
Tile link = world.tile(tile.entity.power().links.get(i));
|
||||
if(link != null && link.entity != null && link.entity.power() != null) out.add(link);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
protected float getProgressIncrease(Tilec entity, float baseTime){
|
||||
return 1f / baseTime * entity.delta() * entity.efficiency();
|
||||
}
|
||||
|
||||
/** @return whether this block should play its active sound.*/
|
||||
public boolean shouldActiveSound(Tile tile){
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @return whether this block should play its idle sound.*/
|
||||
public boolean shouldIdleSound(Tile tile){
|
||||
return shouldConsume(tile);
|
||||
}
|
||||
|
||||
public void drawLayer(Tile tile){
|
||||
}
|
||||
|
||||
public void drawLayer2(Tile tile){
|
||||
}
|
||||
|
||||
public void drawCracks(Tile tile){
|
||||
if(!tile.entity.damaged() || size > maxCrackSize) return;
|
||||
int id = tile.pos();
|
||||
TextureRegion region = cracks[size - 1][Mathf.clamp((int)((1f - tile.entity.healthf()) * crackRegions), 0, crackRegions-1)];
|
||||
Draw.colorl(0.2f, 0.1f + (1f - tile.entity.healthf())* 0.6f);
|
||||
Draw.rect(region, tile.drawx(), tile.drawy(), (id%4)*90);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
/** Draw the block overlay that is shown when a cursor is over the block. */
|
||||
public void drawSelect(Tile tile){
|
||||
}
|
||||
|
||||
/** Drawn when you are placing a block. */
|
||||
public void drawPlace(int x, int y, int rotation, boolean valid){
|
||||
}
|
||||
|
||||
public float drawPlaceText(String text, int x, int y, boolean valid){
|
||||
if(renderer.pixelator.enabled()) return 0;
|
||||
|
||||
Color color = valid ? Pal.accent : Pal.remove;
|
||||
BitmapFont font = Fonts.outline;
|
||||
GlyphLayout layout = Pools.obtain(GlyphLayout.class, GlyphLayout::new);
|
||||
boolean ints = font.usesIntegerPositions();
|
||||
font.setUseIntegerPositions(false);
|
||||
font.getData().setScale(1f / 4f / Scl.scl(1f));
|
||||
layout.setText(font, text);
|
||||
|
||||
float width = layout.width;
|
||||
|
||||
font.setColor(color);
|
||||
float dx = x * tilesize + offset(), dy = y * tilesize + offset() + size * tilesize / 2f + 3;
|
||||
font.draw(text, dx, dy + layout.height + 1, Align.center);
|
||||
dy -= 1f;
|
||||
Lines.stroke(2f, Color.darkGray);
|
||||
Lines.line(dx - layout.width / 2f - 2f, dy, dx + layout.width / 2f + 1.5f, dy);
|
||||
Lines.stroke(1f, color);
|
||||
Lines.line(dx - layout.width / 2f - 2f, dy, dx + layout.width / 2f + 1.5f, dy);
|
||||
|
||||
font.setUseIntegerPositions(ints);
|
||||
font.setColor(Color.white);
|
||||
font.getData().setScale(1f);
|
||||
Draw.reset();
|
||||
Pools.free(layout);
|
||||
return width;
|
||||
}
|
||||
|
||||
public void draw(Tile tile){
|
||||
Draw.rect(region, tile.drawx(), tile.drawy(), rotate ? tile.rotation() * 90 : 0);
|
||||
}
|
||||
|
||||
public void drawLight(Tile tile){
|
||||
if(tile.entity != null && hasLiquids && drawLiquidLight && tile.entity.liquids().current().lightColor.a > 0.001f){
|
||||
drawLiquidLight(tile, tile.entity.liquids().current(), tile.entity.liquids().smoothAmount());
|
||||
}
|
||||
}
|
||||
|
||||
public void drawLiquidLight(Tile tile, Liquid liquid, float amount){
|
||||
if(amount > 0.01f){
|
||||
Color color = liquid.lightColor;
|
||||
float fract = 1f;
|
||||
float opacity = color.a * fract;
|
||||
if(opacity > 0.001f){
|
||||
renderer.lights.add(tile.drawx(), tile.drawy(), size * 30f * fract, color, opacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void drawTeam(Tile tile){
|
||||
Draw.color(tile.team().color);
|
||||
Draw.rect("block-border", tile.drawx() - size * tilesize / 2f + 4, tile.drawy() - size * tilesize / 2f + 4);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
/** Called after the block is placed by this client. */
|
||||
@CallSuper
|
||||
public void playerPlaced(Tile tile){
|
||||
|
||||
}
|
||||
|
||||
/** Called after the block is placed by anyone. */
|
||||
@CallSuper
|
||||
public void placed(Tile tile){
|
||||
if(net.client()) return;
|
||||
|
||||
if((consumesPower && !outputsPower) || (!consumesPower && outputsPower)){
|
||||
int range = 10;
|
||||
tempTiles.clear();
|
||||
Geometry.circle(tile.x, tile.y, range, (x, y) -> {
|
||||
Tile other = world.ltile(x, y);
|
||||
if(other != null && other.block instanceof PowerNode && ((PowerNode)other.block).linkValid(other, tile) && !PowerNode.insulated(other, tile) && !other.entity.proximity().contains(tile) &&
|
||||
!(outputsPower && tile.entity.proximity().contains(p -> p.entity != null && p.entity.power() != null && p.entity.power().graph == other.entity.power().graph))){
|
||||
tempTiles.add(other);
|
||||
}
|
||||
});
|
||||
tempTiles.sort(Structs.comparingFloat(t -> t.dst2(tile)));
|
||||
if(!tempTiles.isEmpty()){
|
||||
Tile toLink = tempTiles.first();
|
||||
if(!toLink.entity.power().links.contains(tile.pos())){
|
||||
toLink.configureAny(tile.pos());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removed(Tile tile){
|
||||
}
|
||||
|
||||
/** Called every frame a unit is on this tile. */
|
||||
public void unitOn(Tile tile, Unitc unit){
|
||||
}
|
||||
|
||||
/** Called when a unit that spawned at this tile is removed. */
|
||||
public void unitRemoved(Tile tile, Unitc unit){
|
||||
}
|
||||
|
||||
/** Returns whether ot not this block can be place on the specified tile. */
|
||||
public boolean canPlaceOn(Tile tile){
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Call when some content is produced. This unlocks the content if it is applicable. */
|
||||
public void useContent(Tile tile, UnlockableContent content){
|
||||
//only unlocks content in zones
|
||||
if(!headless && tile.team() == player.team() && state.isCampaign()){
|
||||
logic.handleContent(content);
|
||||
}
|
||||
}
|
||||
|
||||
public float sumAttribute(Attribute attr, int x, int y){
|
||||
Tile tile = world.tile(x, y);
|
||||
if(tile == null) return 0;
|
||||
float sum = 0;
|
||||
for(Tile other : tile.getLinkedTilesAs(this, tempTiles)){
|
||||
sum += other.floor().attributes.get(attr);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
public float percentSolid(int x, int y){
|
||||
Tile tile = world.tile(x, y);
|
||||
if(tile == null) return 0;
|
||||
float sum = 0;
|
||||
for(Tile other : tile.getLinkedTilesAs(this, tempTiles)){
|
||||
sum += !other.floor.isLiquid ? 1f : 0f;
|
||||
}
|
||||
return sum / size / size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayInfo(Table table){
|
||||
ContentDisplay.displayBlock(table, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentType getContentType(){
|
||||
return ContentType.block;
|
||||
}
|
||||
|
||||
/** Called after all blocks are created. */
|
||||
@Override
|
||||
@CallSuper
|
||||
public void init(){
|
||||
//initialize default health based on size
|
||||
if(health == -1){
|
||||
health = size * size * 40;
|
||||
}
|
||||
|
||||
buildCost = 0f;
|
||||
for(ItemStack stack : requirements){
|
||||
buildCost += stack.amount * stack.item.cost;
|
||||
}
|
||||
buildCost *= buildCostMultiplier;
|
||||
|
||||
if(consumes.has(ConsumeType.power)) hasPower = true;
|
||||
if(consumes.has(ConsumeType.item)) hasItems = true;
|
||||
if(consumes.has(ConsumeType.liquid)) hasLiquids = true;
|
||||
|
||||
setStats();
|
||||
setBars();
|
||||
|
||||
consumes.init();
|
||||
|
||||
if(!outputsPower && consumes.hasPower() && consumes.getPower().buffered){
|
||||
throw new IllegalArgumentException("Consumer using buffered power: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(){
|
||||
region = Core.atlas.find(name);
|
||||
|
||||
cacheRegions = new TextureRegion[cacheRegionStrings.size];
|
||||
for(int i = 0; i < cacheRegions.length; i++){
|
||||
cacheRegions[i] = Core.atlas.find(cacheRegionStrings.get(i));
|
||||
}
|
||||
|
||||
if(cracks == null || (cracks[0][0].getTexture() != null && cracks[0][0].getTexture().isDisposed())){
|
||||
cracks = new TextureRegion[maxCrackSize][crackRegions];
|
||||
for(int size = 1; size <= maxCrackSize; size++){
|
||||
for(int i = 0; i < crackRegions; i++){
|
||||
cracks[size - 1][i] = Core.atlas.find("cracks-" + size + "-" + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Adds a region by name to be loaded, with the final name "{name}-suffix". Returns an ID to looks this region up by in {@link #reg(int)}. */
|
||||
protected int reg(String suffix){
|
||||
cacheRegionStrings.add(name + suffix);
|
||||
@@ -469,78 +188,10 @@ public class Block extends BlockStorage{
|
||||
return cacheRegions[id];
|
||||
}
|
||||
|
||||
/** Called when the block is tapped. This is equivalent to being configured with null. */
|
||||
public void tapped(Tile tile, Playerc player){
|
||||
|
||||
}
|
||||
|
||||
/** Called when arbitrary configuration is applied to a tile. */
|
||||
public void configured(Tile tile, @Nullable Playerc player, @Nullable Object value){
|
||||
//null is of type Void.class; anonymous classes use their superclass.
|
||||
Class<?> type = value == null ? void.class : value.getClass().isAnonymousClass() ? value.getClass().getSuperclass() : value.getClass();
|
||||
|
||||
if(configurations.containsKey(type)){
|
||||
configurations.get(type).configured(tile, value);
|
||||
}
|
||||
}
|
||||
|
||||
/** Configure when a null value is passed.*/
|
||||
public void configClear(Cons<Tile> cons){
|
||||
configurations.put(void.class, (tile, value) -> cons.get(tile));
|
||||
}
|
||||
|
||||
/** Listen for a config by class type. */
|
||||
public <T> void config(Class<T> type, ConfigHandler<T> config){
|
||||
configurations.put(type, config);
|
||||
}
|
||||
|
||||
/** Returns whether or not a hand cursor should be shown over this block. */
|
||||
public Cursor getCursor(Tile tile){
|
||||
return configurable ? SystemCursor.hand : SystemCursor.arrow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this block is tapped to build a UI on the table.
|
||||
* {@link #configurable} must return true for this to be called.
|
||||
*/
|
||||
public void buildConfiguration(Tile tile, Table table){
|
||||
}
|
||||
|
||||
/** Update table alignment after configuring.*/
|
||||
public void updateTableAlign(Tile tile, Table table){
|
||||
Vec2 pos = Core.input.mouseScreen(tile.drawx(), tile.drawy() - tile.block().size * tilesize / 2f - 1);
|
||||
table.setPosition(pos.x, pos.y, Align.top);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when another tile is tapped while this block is selected.
|
||||
* Returns whether or not this block should be deselected.
|
||||
*/
|
||||
public boolean onConfigureTileTapped(Tile tile, Tile other){
|
||||
return tile != other;
|
||||
}
|
||||
|
||||
/** Returns whether this config menu should show when the specified player taps it. */
|
||||
public boolean shouldShowConfigure(Tile tile, Playerc player){
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Whether this configuration should be hidden now. Called every frame the config is open. */
|
||||
public boolean shouldHideConfigure(Tile tile, Playerc player){
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean synthetic(){
|
||||
return update || destructible;
|
||||
}
|
||||
|
||||
public void drawConfigure(Tile tile){
|
||||
Draw.color(Pal.accent);
|
||||
Lines.stroke(1f);
|
||||
Lines.square(tile.drawx(), tile.drawy(), tile.block().size * tilesize / 2f + 1f);
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
public void setStats(){
|
||||
stats.add(BlockStat.size, "{0}x{0}", size);
|
||||
stats.add(BlockStat.health, health, StatUnit.none);
|
||||
@@ -568,7 +219,7 @@ public class Block extends BlockStorage{
|
||||
current = entity -> entity.liquids().current();
|
||||
}
|
||||
bars.add("liquid", entity -> new Bar(() -> entity.liquids().get(current.get(entity)) <= 0.001f ? Core.bundle.get("bar.liquid") : current.get(entity).localizedName,
|
||||
() -> current.get(entity).barColor(), () -> entity.liquids().get(current.get(entity)) / liquidCapacity));
|
||||
() -> current.get(entity).barColor(), () -> entity.liquids().get(current.get(entity)) / liquidCapacity));
|
||||
}
|
||||
|
||||
if(hasPower && consumes.hasPower()){
|
||||
@@ -577,7 +228,7 @@ public class Block extends BlockStorage{
|
||||
float capacity = cons.capacity;
|
||||
|
||||
bars.add("power", entity -> new Bar(() -> buffered ? Core.bundle.format("bar.poweramount", Float.isNaN(entity.power().status * capacity) ? "<ERROR>" : (int)(entity.power().status * capacity)) :
|
||||
Core.bundle.get("bar.power"), () -> Pal.powerBar, () -> Mathf.zero(cons.requestedPower(entity)) && entity.power().graph.getPowerProduced() + entity.power().graph.getBatteryStored() > 0f ? 1f : entity.power().status));
|
||||
Core.bundle.get("bar.power"), () -> Pal.powerBar, () -> Mathf.zero(cons.requestedPower(entity)) && entity.power().graph.getPowerProduced() + entity.power().graph.getBatteryStored() > 0f ? 1f : entity.power().status));
|
||||
}
|
||||
|
||||
if(hasItems && configurable){
|
||||
@@ -585,14 +236,6 @@ public class Block extends BlockStorage{
|
||||
}
|
||||
}
|
||||
|
||||
public Tile linked(Tile tile){
|
||||
return tile;
|
||||
}
|
||||
|
||||
public boolean isSolidFor(Tile tile){
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean canReplace(Block other){
|
||||
return (other != this || rotate) && this.group != BlockGroup.none && other.group == this.group;
|
||||
}
|
||||
@@ -602,129 +245,6 @@ public class Block extends BlockStorage{
|
||||
return this;
|
||||
}
|
||||
|
||||
public float handleDamage(Tile tile, float amount){
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void handleBulletHit(Tilec entity, Bulletc bullet){
|
||||
entity.damage(bullet.damage());
|
||||
}
|
||||
|
||||
public void update(Tile tile){
|
||||
}
|
||||
|
||||
public boolean isAccessible(){
|
||||
return (hasItems && itemCapacity > 0);
|
||||
}
|
||||
|
||||
/** Called when the block is destroyed. */
|
||||
public void onDestroyed(Tile tile){
|
||||
float x = tile.worldx(), y = tile.worldy();
|
||||
float explosiveness = baseExplosiveness;
|
||||
float flammability = 0f;
|
||||
float power = 0f;
|
||||
|
||||
if(hasItems){
|
||||
for(Item item : content.items()){
|
||||
int amount = tile.entity.items().get(item);
|
||||
explosiveness += item.explosiveness * amount;
|
||||
flammability += item.flammability * amount;
|
||||
}
|
||||
}
|
||||
|
||||
if(hasLiquids){
|
||||
flammability += tile.entity.liquids().sum((liquid, amount) -> liquid.explosiveness * amount / 2f);
|
||||
explosiveness += tile.entity.liquids().sum((liquid, amount) -> liquid.flammability * amount / 2f);
|
||||
}
|
||||
|
||||
if(consumes.hasPower() && consumes.getPower().buffered){
|
||||
power += tile.entity.power().status * consumes.getPower().capacity;
|
||||
}
|
||||
|
||||
if(hasLiquids){
|
||||
|
||||
tile.entity.liquids().each((liquid, amount) -> {
|
||||
float splash = Mathf.clamp(amount / 4f, 0f, 10f);
|
||||
|
||||
for(int i = 0; i < Mathf.clamp(amount / 5, 0, 30); i++){
|
||||
Time.run(i / 2f, () -> {
|
||||
Tile other = world.tile(tile.x + Mathf.range(size / 2), tile.y + Mathf.range(size / 2));
|
||||
if(other != null){
|
||||
Puddles.deposit(other, liquid, splash);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Damage.dynamicExplosion(x, y, flammability, explosiveness * 3.5f, power, tilesize * size / 2f, Pal.darkFlame);
|
||||
if(!tile.floor().solid && !tile.floor().isLiquid){
|
||||
Effects.rubble(tile.drawx(), tile.drawy(), size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the flammability of the tile. Used for fire calculations.
|
||||
* Takes flammability of floor liquid into account.
|
||||
*/
|
||||
public float getFlammability(Tile tile){
|
||||
if(!hasItems || tile.entity == null){
|
||||
if(tile.floor().isLiquid && !solid){
|
||||
return tile.floor().liquidDrop.flammability;
|
||||
}
|
||||
return 0;
|
||||
}else{
|
||||
float result = tile.entity.items().sum((item, amount) -> item.flammability * amount);
|
||||
|
||||
if(hasLiquids){
|
||||
result += tile.entity.liquids().sum((liquid, amount) -> liquid.flammability * amount / 3f);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public String getDisplayName(Tile tile){
|
||||
return localizedName;
|
||||
}
|
||||
|
||||
public TextureRegion getDisplayIcon(Tile tile){
|
||||
return icon(Cicon.medium);
|
||||
}
|
||||
|
||||
public void display(Tile tile, Table table){
|
||||
Tilec entity = tile.entity;
|
||||
|
||||
if(entity != null){
|
||||
table.table(bars -> {
|
||||
bars.defaults().growX().height(18f).pad(4);
|
||||
|
||||
displayBars(tile, bars);
|
||||
}).growX();
|
||||
table.row();
|
||||
table.table(ctable -> {
|
||||
displayConsumption(tile, ctable);
|
||||
}).growX();
|
||||
|
||||
table.marginBottom(-5);
|
||||
}
|
||||
}
|
||||
|
||||
public void displayConsumption(Tile tile, Table table){
|
||||
table.left();
|
||||
for(Consume cons : consumes.all()){
|
||||
if(cons.isOptional() && cons.isBoost()) continue;
|
||||
cons.build(tile, table);
|
||||
}
|
||||
}
|
||||
|
||||
public void displayBars(Tile tile, Table table){
|
||||
for(Func<Tilec, Bar> bar : bars.list()){
|
||||
table.add(bar.get(tile.entity)).growX();
|
||||
table.row();
|
||||
}
|
||||
}
|
||||
|
||||
public void drawRequest(BuildRequest req, Eachable<BuildRequest> list, boolean valid){
|
||||
Draw.reset();
|
||||
Draw.mixcol(!valid ? Pal.breakInvalid : Color.white, (!valid ? 0.4f : 0.24f) + Mathf.absin(Time.globalTime(), 6f, 0.28f));
|
||||
@@ -736,9 +256,9 @@ public class Block extends BlockStorage{
|
||||
public void drawRequestRegion(BuildRequest req, Eachable<BuildRequest> list){
|
||||
TextureRegion reg = getRequestRegion(req, list);
|
||||
Draw.rect(reg, req.drawx(), req.drawy(),
|
||||
reg.getWidth() * req.animScale * Draw.scl,
|
||||
reg.getHeight() * req.animScale * Draw.scl,
|
||||
!rotate ? 0 : req.rotation * 90);
|
||||
reg.getWidth() * req.animScale * Draw.scl,
|
||||
reg.getHeight() * req.animScale * Draw.scl,
|
||||
!rotate ? 0 : req.rotation * 90);
|
||||
|
||||
if(req.hasConfig){
|
||||
drawRequestConfig(req, list);
|
||||
@@ -766,75 +286,32 @@ public class Block extends BlockStorage{
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
/** @return a custom minimap color for this tile, or 0 to use default colors. */
|
||||
public int minimapColor(Tile tile){
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void drawRequestConfigTop(BuildRequest req, Eachable<BuildRequest> list){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createIcons(MultiPacker packer){
|
||||
super.createIcons(packer);
|
||||
/** Called when arbitrary configuration is applied to a tile. */
|
||||
public void configured(Tilec tile, @Nullable Playerc player, @Nullable Object value){
|
||||
//null is of type Void.class; anonymous classes use their superclass.
|
||||
Class<?> type = value == null ? void.class : value.getClass().isAnonymousClass() ? value.getClass().getSuperclass() : value.getClass();
|
||||
|
||||
packer.add(PageType.editor, name + "-icon-editor", Core.atlas.getPixmap((AtlasRegion)icon(Cicon.full)));
|
||||
|
||||
if(!synthetic()){
|
||||
PixmapRegion image = Core.atlas.getPixmap((AtlasRegion)icon(Cicon.full));
|
||||
mapColor.set(image.getPixel(image.width/2, image.height/2));
|
||||
if(configurations.containsKey(type)){
|
||||
configurations.get(type).get(tile, value);
|
||||
}
|
||||
}
|
||||
|
||||
getGeneratedIcons();
|
||||
/** Configure when a null value is passed.*/
|
||||
public void configClear(Cons<Tilec> cons){
|
||||
configurations.put(void.class, (tile, value) -> cons.get((Tilec)tile));
|
||||
}
|
||||
|
||||
Pixmap last = null;
|
||||
/** Listen for a config by class type. */
|
||||
public <T> void config(Class<T> type, Cons2<Tile, T> config){
|
||||
configurations.put(type, config);
|
||||
}
|
||||
|
||||
if(outlineIcon){
|
||||
final int radius = 4;
|
||||
PixmapRegion region = Core.atlas.getPixmap(getGeneratedIcons()[getGeneratedIcons().length-1]);
|
||||
Pixmap out = new Pixmap(region.width, region.height);
|
||||
Color color = new Color();
|
||||
for(int x = 0; x < region.width; x++){
|
||||
for(int y = 0; y < region.height; y++){
|
||||
|
||||
region.getPixel(x, y, color);
|
||||
out.draw(x, y, color);
|
||||
if(color.a < 1f){
|
||||
boolean found = false;
|
||||
outer:
|
||||
for(int rx = -radius; rx <= radius; rx++){
|
||||
for(int ry = -radius; ry <= radius; ry++){
|
||||
if(Structs.inBounds(rx + x, ry + y, region.width, region.height) && Mathf.dst2(rx, ry) <= radius*radius && color.set(region.getPixel(rx + x, ry + y)).a > 0.01f){
|
||||
found = true;
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(found){
|
||||
out.draw(x, y, outlineColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
last = out;
|
||||
|
||||
packer.add(PageType.main, name, out);
|
||||
}
|
||||
|
||||
if(generatedIcons.length > 1){
|
||||
Pixmap base = Core.atlas.getPixmap(generatedIcons[0]).crop();
|
||||
for(int i = 1; i < generatedIcons.length; i++){
|
||||
if(i == generatedIcons.length - 1 && last != null){
|
||||
base.drawPixmap(last);
|
||||
}else{
|
||||
base.draw(Core.atlas.getPixmap(generatedIcons[i]));
|
||||
}
|
||||
}
|
||||
packer.add(PageType.main, "block-" + name + "-full", base);
|
||||
generatedIcons = null;
|
||||
Arrays.fill(cicons, null);
|
||||
}
|
||||
public boolean isAccessible(){
|
||||
return (hasItems && itemCapacity > 0);
|
||||
}
|
||||
|
||||
/** Never use outside of the editor! */
|
||||
@@ -911,14 +388,16 @@ public class Block extends BlockStorage{
|
||||
return (Floor)this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHidden(){
|
||||
return !buildVisibility.visible();
|
||||
public boolean isAir(){
|
||||
return id == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean alwaysUnlocked(){
|
||||
return alwaysUnlocked;
|
||||
public boolean isBuildable(){
|
||||
return buildVisibility != BuildVisibility.hidden && buildVisibility != BuildVisibility.debugOnly;
|
||||
}
|
||||
|
||||
public boolean isStatic(){
|
||||
return cacheLayer == CacheLayer.walls;
|
||||
}
|
||||
|
||||
protected void requirements(Category cat, ItemStack[] stacks, boolean unlocked){
|
||||
@@ -939,8 +418,157 @@ public class Block extends BlockStorage{
|
||||
Arrays.sort(requirements, Structs.comparingInt(i -> i.item.id));
|
||||
}
|
||||
|
||||
public interface ConfigHandler<T>{
|
||||
void configured(Tile tile, T value);
|
||||
@Override
|
||||
public void displayInfo(Table table){
|
||||
ContentDisplay.displayBlock(table, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentType getContentType(){
|
||||
return ContentType.block;
|
||||
}
|
||||
|
||||
/** Called after all blocks are created. */
|
||||
@Override
|
||||
@CallSuper
|
||||
public void init(){
|
||||
//initialize default health based on size
|
||||
if(health == -1){
|
||||
health = size * size * 40;
|
||||
}
|
||||
|
||||
if(entityType == null){
|
||||
//assign default value for now
|
||||
entityType = TileEntity::create;
|
||||
|
||||
//attempt to find the first declared class and use it as the entity type
|
||||
try{
|
||||
Class<?>[] classes = getClass().getDeclaredClasses();
|
||||
//first class that is subclass of Tilec
|
||||
Class<?> type = Structs.find(classes, Tilec.class::isAssignableFrom);
|
||||
if(type != null){
|
||||
Constructor<? extends Tilec> cons = (Constructor<? extends Tilec>)type.getConstructor();
|
||||
entityType = () -> {
|
||||
try{
|
||||
return cons.newInstance();
|
||||
}catch(Exception e){
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
}catch(Throwable ignored){
|
||||
}
|
||||
}
|
||||
|
||||
buildCost = 0f;
|
||||
for(ItemStack stack : requirements){
|
||||
buildCost += stack.amount * stack.item.cost;
|
||||
}
|
||||
buildCost *= buildCostMultiplier;
|
||||
|
||||
if(consumes.has(ConsumeType.power)) hasPower = true;
|
||||
if(consumes.has(ConsumeType.item)) hasItems = true;
|
||||
if(consumes.has(ConsumeType.liquid)) hasLiquids = true;
|
||||
|
||||
setStats();
|
||||
setBars();
|
||||
|
||||
consumes.init();
|
||||
|
||||
if(!outputsPower && consumes.hasPower() && consumes.getPower().buffered){
|
||||
throw new IllegalArgumentException("Consumer using buffered power: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(){
|
||||
region = Core.atlas.find(name);
|
||||
|
||||
cacheRegions = new TextureRegion[cacheRegionStrings.size];
|
||||
for(int i = 0; i < cacheRegions.length; i++){
|
||||
cacheRegions[i] = Core.atlas.find(cacheRegionStrings.get(i));
|
||||
}
|
||||
|
||||
if(cracks == null || (cracks[0][0].getTexture() != null && cracks[0][0].getTexture().isDisposed())){
|
||||
cracks = new TextureRegion[maxCrackSize][crackRegions];
|
||||
for(int size = 1; size <= maxCrackSize; size++){
|
||||
for(int i = 0; i < crackRegions; i++){
|
||||
cracks[size - 1][i] = Core.atlas.find("cracks-" + size + "-" + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHidden(){
|
||||
return !buildVisibility.visible();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean alwaysUnlocked(){
|
||||
return alwaysUnlocked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createIcons(MultiPacker packer){
|
||||
super.createIcons(packer);
|
||||
|
||||
packer.add(PageType.editor, name + "-icon-editor", Core.atlas.getPixmap((AtlasRegion)icon(Cicon.full)));
|
||||
|
||||
if(!synthetic()){
|
||||
PixmapRegion image = Core.atlas.getPixmap((AtlasRegion)icon(Cicon.full));
|
||||
mapColor.set(image.getPixel(image.width/2, image.height/2));
|
||||
}
|
||||
|
||||
getGeneratedIcons();
|
||||
|
||||
Pixmap last = null;
|
||||
|
||||
if(outlineIcon){
|
||||
final int radius = 4;
|
||||
PixmapRegion region = Core.atlas.getPixmap(getGeneratedIcons()[getGeneratedIcons().length-1]);
|
||||
Pixmap out = new Pixmap(region.width, region.height);
|
||||
Color color = new Color();
|
||||
for(int x = 0; x < region.width; x++){
|
||||
for(int y = 0; y < region.height; y++){
|
||||
|
||||
region.getPixel(x, y, color);
|
||||
out.draw(x, y, color);
|
||||
if(color.a < 1f){
|
||||
boolean found = false;
|
||||
outer:
|
||||
for(int rx = -radius; rx <= radius; rx++){
|
||||
for(int ry = -radius; ry <= radius; ry++){
|
||||
if(Structs.inBounds(rx + x, ry + y, region.width, region.height) && Mathf.dst2(rx, ry) <= radius*radius && color.set(region.getPixel(rx + x, ry + y)).a > 0.01f){
|
||||
found = true;
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(found){
|
||||
out.draw(x, y, outlineColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
last = out;
|
||||
|
||||
packer.add(PageType.main, name, out);
|
||||
}
|
||||
|
||||
if(generatedIcons.length > 1){
|
||||
Pixmap base = Core.atlas.getPixmap(generatedIcons[0]).crop();
|
||||
for(int i = 1; i < generatedIcons.length; i++){
|
||||
if(i == generatedIcons.length - 1 && last != null){
|
||||
base.drawPixmap(last);
|
||||
}else{
|
||||
base.draw(Core.atlas.getPixmap(generatedIcons[i]));
|
||||
}
|
||||
}
|
||||
packer.add(PageType.main, "block-" + name + "-full", base);
|
||||
generatedIcons = null;
|
||||
Arrays.fill(cicons, null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,280 +0,0 @@
|
||||
package mindustry.world;
|
||||
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.consumers.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
public abstract class BlockStorage extends UnlockableContent{
|
||||
public boolean hasItems;
|
||||
public boolean hasLiquids;
|
||||
public boolean hasPower;
|
||||
|
||||
public boolean outputsLiquid = false;
|
||||
public boolean consumesPower = true;
|
||||
public boolean outputsPower = false;
|
||||
|
||||
public int itemCapacity = 10;
|
||||
public float liquidCapacity = 10f;
|
||||
public float liquidPressure = 1f;
|
||||
|
||||
public final BlockStats stats = new BlockStats();
|
||||
public final BlockBars bars = new BlockBars();
|
||||
public final Consumers consumes = new Consumers();
|
||||
|
||||
public BlockStorage(String name){
|
||||
super(name);
|
||||
}
|
||||
|
||||
public boolean shouldConsume(Tile tile){
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean productionValid(Tile tile){
|
||||
return true;
|
||||
}
|
||||
|
||||
public float getPowerProduction(Tile tile){
|
||||
return 0f;
|
||||
}
|
||||
|
||||
/** Returns the amount of items this block can accept. */
|
||||
public int acceptStack(Item item, int amount, Tile tile, Teamc source){
|
||||
if(acceptItem(item, tile, tile) && hasItems && (source == null || source.team() == tile.team())){
|
||||
return Math.min(getMaximumAccepted(tile, item) - tile.entity.items().get(item), amount);
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public int getMaximumAccepted(Tile tile, Item item){
|
||||
return itemCapacity;
|
||||
}
|
||||
|
||||
/** Remove a stack from this inventory, and return the amount removed. */
|
||||
public int removeStack(Tile tile, Item item, int amount){
|
||||
if(tile.entity == null || tile.entity.items() == null) return 0;
|
||||
amount = Math.min(amount, tile.entity.items().get(item));
|
||||
tile.entity.noSleep();
|
||||
tile.entity.items().remove(item, amount);
|
||||
return amount;
|
||||
}
|
||||
|
||||
/** Handle a stack input. */
|
||||
public void handleStack(Item item, int amount, Tile tile, Teamc source){
|
||||
tile.entity.noSleep();
|
||||
tile.entity.items().add(item, amount);
|
||||
}
|
||||
|
||||
public boolean outputsItems(){
|
||||
return hasItems;
|
||||
}
|
||||
|
||||
/** Returns offset for stack placement. */
|
||||
public void getStackOffset(Item item, Tile tile, Vec2 trns){
|
||||
|
||||
}
|
||||
|
||||
public void onProximityUpdate(Tile tile){
|
||||
if(tile.entity != null) tile.entity.noSleep();
|
||||
}
|
||||
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
tile.entity.items().add(item, 1);
|
||||
}
|
||||
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
return consumes.itemFilters.get(item.id) && tile.entity.items().get(item) < getMaximumAccepted(tile, item);
|
||||
}
|
||||
|
||||
public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){
|
||||
return hasLiquids && tile.entity.liquids().get(liquid) + amount < liquidCapacity && consumes.liquidfilters.get(liquid.id);
|
||||
}
|
||||
|
||||
public void handleLiquid(Tile tile, Tile source, Liquid liquid, float amount){
|
||||
tile.entity.liquids().add(liquid, amount);
|
||||
}
|
||||
|
||||
public void tryDumpLiquid(Tile tile, Liquid liquid){
|
||||
Array<Tile> proximity = tile.entity.proximity();
|
||||
int dump = tile.rotation();
|
||||
|
||||
for(int i = 0; i < proximity.size; i++){
|
||||
incrementDump(tile, proximity.size);
|
||||
Tile other = proximity.get((i + dump) % proximity.size);
|
||||
Tile in = Edges.getFacingEdge(tile, other);
|
||||
|
||||
other = other.block().getLiquidDestination(other, in, liquid);
|
||||
|
||||
if(other != null && other.team() == tile.team() && other.block().hasLiquids && canDumpLiquid(tile, other, liquid) && other.entity.liquids() != null){
|
||||
float ofract = other.entity.liquids().get(liquid) / other.block().liquidCapacity;
|
||||
float fract = tile.entity.liquids().get(liquid) / liquidCapacity;
|
||||
|
||||
if(ofract < fract) tryMoveLiquid(tile, in, other, (fract - ofract) * liquidCapacity / 2f, liquid);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean canDumpLiquid(Tile tile, Tile to, Liquid liquid){
|
||||
return true;
|
||||
}
|
||||
|
||||
public void tryMoveLiquid(Tile tile, Tile tileSource, Tile next, float amount, Liquid liquid){
|
||||
float flow = Math.min(next.block().liquidCapacity - next.entity.liquids().get(liquid) - 0.001f, amount);
|
||||
|
||||
if(next.block().acceptLiquid(next, tileSource, liquid, flow)){
|
||||
next.block().handleLiquid(next, tileSource, liquid, flow);
|
||||
tile.entity.liquids().remove(liquid, flow);
|
||||
}
|
||||
}
|
||||
|
||||
public float tryMoveLiquid(Tile tile, Tile next, boolean leak, Liquid liquid){
|
||||
return tryMoveLiquid(tile, next, leak ? 1.5f : 100, liquid);
|
||||
}
|
||||
|
||||
public float tryMoveLiquid(Tile tile, Tile next, float leakResistance, Liquid liquid){
|
||||
if(next == null) return 0;
|
||||
|
||||
next = next.link();
|
||||
next = next.block().getLiquidDestination(next, tile, liquid);
|
||||
|
||||
if(next.team() == tile.team() && next.block().hasLiquids && tile.entity.liquids().get(liquid) > 0f){
|
||||
|
||||
if(next.block().acceptLiquid(next, tile, liquid, 0f)){
|
||||
float ofract = next.entity.liquids().get(liquid) / next.block().liquidCapacity;
|
||||
float fract = tile.entity.liquids().get(liquid) / liquidCapacity * liquidPressure;
|
||||
float flow = Math.min(Mathf.clamp((fract - ofract) * (1f)) * (liquidCapacity), tile.entity.liquids().get(liquid));
|
||||
flow = Math.min(flow, next.block().liquidCapacity - next.entity.liquids().get(liquid) - 0.001f);
|
||||
|
||||
if(flow > 0f && ofract <= fract && next.block().acceptLiquid(next, tile, liquid, flow)){
|
||||
next.block().handleLiquid(next, tile, liquid, flow);
|
||||
tile.entity.liquids().remove(liquid, flow);
|
||||
return flow;
|
||||
}else if(ofract > 0.1f && fract > 0.1f){
|
||||
Liquid other = next.entity.liquids().current();
|
||||
if((other.flammability > 0.3f && liquid.temperature > 0.7f) || (liquid.flammability > 0.3f && other.temperature > 0.7f)){
|
||||
tile.entity.damage(1 * Time.delta());
|
||||
next.entity.damage(1 * Time.delta());
|
||||
if(Mathf.chance(0.1 * Time.delta())){
|
||||
Fx.fire.at((tile.worldx() + next.worldx()) / 2f, (tile.worldy() + next.worldy()) / 2f);
|
||||
}
|
||||
}else if((liquid.temperature > 0.7f && other.temperature < 0.55f) || (other.temperature > 0.7f && liquid.temperature < 0.55f)){
|
||||
tile.entity.liquids().remove(liquid, Math.min(tile.entity.liquids().get(liquid), 0.7f * Time.delta()));
|
||||
if(Mathf.chance(0.2f * Time.delta())){
|
||||
Fx.steam.at((tile.worldx() + next.worldx()) / 2f, (tile.worldy() + next.worldy()) / 2f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if(leakResistance != 100f && !next.block().solid && !next.block().hasLiquids){
|
||||
float leakAmount = tile.entity.liquids().get(liquid) / leakResistance;
|
||||
Puddles.deposit(next, tile, liquid, leakAmount);
|
||||
tile.entity.liquids().remove(liquid, leakAmount);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Tile getLiquidDestination(Tile tile, Tile from, Liquid liquid){
|
||||
return tile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to put this item into a nearby container, if there are no available
|
||||
* containers, it gets added to the block's inventory.
|
||||
*/
|
||||
public void offloadNear(Tile tile, Item item){
|
||||
Array<Tile> proximity = tile.entity.proximity();
|
||||
int dump = tile.rotation();
|
||||
|
||||
for(int i = 0; i < proximity.size; i++){
|
||||
incrementDump(tile, proximity.size);
|
||||
Tile other = proximity.get((i + dump) % proximity.size);
|
||||
Tile in = Edges.getFacingEdge(tile, other);
|
||||
if(other.team() == tile.team() && other.block().acceptItem(item, other, in) && canDump(tile, other, item)){
|
||||
other.block().handleItem(item, other, in);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
handleItem(item, tile, tile);
|
||||
}
|
||||
|
||||
/** Try dumping any item near the tile. */
|
||||
public boolean tryDump(Tile tile){
|
||||
return tryDump(tile, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try dumping a specific item near the tile.
|
||||
* @param todump Item to dump. Can be null to dump anything.
|
||||
*/
|
||||
public boolean tryDump(Tile tile, Item todump){
|
||||
Tilec entity = tile.entity;
|
||||
if(entity == null || !hasItems || tile.entity.items().total() == 0 || (todump != null && !entity.items().has(todump)))
|
||||
return false;
|
||||
|
||||
Array<Tile> proximity = entity.proximity();
|
||||
int dump = tile.rotation();
|
||||
|
||||
if(proximity.size == 0) return false;
|
||||
|
||||
for(int i = 0; i < proximity.size; i++){
|
||||
Tile other = proximity.get((i + dump) % proximity.size);
|
||||
Tile in = Edges.getFacingEdge(tile, other);
|
||||
|
||||
if(todump == null){
|
||||
|
||||
for(int ii = 0; ii < Vars.content.items().size; ii++){
|
||||
Item item = Vars.content.item(ii);
|
||||
|
||||
if(other.team() == tile.team() && entity.items().has(item) && other.block().acceptItem(item, other, in) && canDump(tile, other, item)){
|
||||
other.block().handleItem(item, other, in);
|
||||
tile.entity.items().remove(item, 1);
|
||||
incrementDump(tile, proximity.size);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
|
||||
if(other.team() == tile.team() && other.block().acceptItem(todump, other, in) && canDump(tile, other, todump)){
|
||||
other.block().handleItem(todump, other, in);
|
||||
tile.entity.items().remove(todump, 1);
|
||||
incrementDump(tile, proximity.size);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
incrementDump(tile, proximity.size);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void incrementDump(Tile tile, int prox){
|
||||
tile.rotation((byte)((tile.rotation() + 1) % prox));
|
||||
}
|
||||
|
||||
/** Used for dumping items. */
|
||||
public boolean canDump(Tile tile, Tile to, Item item){
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Try offloading an item to a nearby container in its facing direction. Returns true if success. */
|
||||
public boolean offloadDir(Tile tile, Item item){
|
||||
Tile other = tile.front();
|
||||
if(other != null && other.team() == tile.team() && other.block().acceptItem(item, other, tile)){
|
||||
other.block().handleItem(item, other, tile);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -15,19 +15,16 @@ import static mindustry.Vars.*;
|
||||
|
||||
public class Build{
|
||||
|
||||
/** Returns block type that was broken, or null if unsuccesful. */
|
||||
@Remote(called = Loc.server)
|
||||
public static void beginBreak(Team team, int x, int y){
|
||||
if(!validBreak(team, x, y)){
|
||||
return;
|
||||
}
|
||||
|
||||
Tile tile = world.ltile(x, y);
|
||||
Tile tile = world.tilec(x, y);
|
||||
//this should never happen, but it doesn't hurt to check for links
|
||||
float prevPercent = 1f;
|
||||
|
||||
//just in case
|
||||
if(tile == null) return;
|
||||
|
||||
if(tile.entity != null){
|
||||
prevPercent = tile.entity.healthf();
|
||||
}
|
||||
@@ -36,7 +33,7 @@ public class Build{
|
||||
Block previous = tile.block();
|
||||
Block sub = BuildBlock.get(previous.size);
|
||||
|
||||
tile.set(sub, team, rotation);
|
||||
tile.setBlock(sub, team, rotation);
|
||||
tile.<BuildEntity>ent().setDeconstruct(previous);
|
||||
tile.entity.health(tile.entity.maxHealth() * prevPercent);
|
||||
|
||||
@@ -58,7 +55,7 @@ public class Build{
|
||||
Block previous = tile.block();
|
||||
Block sub = BuildBlock.get(result.size);
|
||||
|
||||
tile.set(sub, team, rotation);
|
||||
tile.setBlock(sub, team, rotation);
|
||||
tile.<BuildEntity>ent().setConstruct(previous, result);
|
||||
|
||||
Core.app.post(() -> Events.fire(new BlockBuildBeginEvent(tile, team, false)));
|
||||
@@ -152,7 +149,7 @@ public class Build{
|
||||
|
||||
/** Returns whether the tile at this position is breakable by this team */
|
||||
public static boolean validBreak(Team team, int x, int y){
|
||||
Tile tile = world.ltile(x, y);
|
||||
Tile tile = world.tile(x, y);
|
||||
return tile != null && tile.block().canBreak(tile) && tile.breakable() && tile.interactable(team);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,15 +19,13 @@ public class Tile implements Position{
|
||||
/** Tile traversal cost. */
|
||||
public byte cost = 1;
|
||||
/** Tile entity, usually null. */
|
||||
public Tilec entity;
|
||||
public @Nullable Tilec entity;
|
||||
public short x, y;
|
||||
protected @NonNull Block block;
|
||||
protected @NonNull Floor floor;
|
||||
protected @NonNull Floor overlay;
|
||||
/** Rotation, 0-3. Also used to store offload location, in which case it can be any number.*/
|
||||
protected byte rotation;
|
||||
/** Team ordinal. */
|
||||
protected byte team;
|
||||
|
||||
public Tile(int x, int y){
|
||||
this.x = (short)x;
|
||||
@@ -144,23 +142,63 @@ public class Tile implements Position{
|
||||
}
|
||||
|
||||
public Team team(){
|
||||
return Team.get(link().team);
|
||||
return entity == null ? Team.derelict : entity.team();
|
||||
}
|
||||
|
||||
public void setTeam(Team team){
|
||||
this.team = (byte) team.id;
|
||||
if(entity != null){
|
||||
entity.team(team);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isCenter(){
|
||||
return entity == null || entity.tile() == this;
|
||||
}
|
||||
|
||||
public byte getTeamID(){
|
||||
return team;
|
||||
return team().id;
|
||||
}
|
||||
|
||||
public void setBlock(@NonNull Block type, Team team, int rotation){
|
||||
preChanged();
|
||||
this.block = type;
|
||||
this.team = (byte) team.id;
|
||||
this.rotation = (byte)Mathf.mod(rotation, 4);
|
||||
this.rotation = rotation == 0 ? 0 : (byte)Mathf.mod(rotation, 4);
|
||||
changed();
|
||||
|
||||
if(entity != null){
|
||||
entity.team(team);
|
||||
}
|
||||
|
||||
//set up multiblock
|
||||
if(block.isMultiblock()){
|
||||
int offsetx = -(block.size - 1) / 2;
|
||||
int offsety = -(block.size - 1) / 2;
|
||||
|
||||
//two passes: first one clears, second one sets
|
||||
for(int pass = 0; pass < 2; pass++){
|
||||
for(int dx = 0; dx < block.size; dx++){
|
||||
for(int dy = 0; dy < block.size; dy++){
|
||||
int worldx = dx + offsetx + x;
|
||||
int worldy = dy + offsety + y;
|
||||
if(!(worldx == x && worldy == y)){
|
||||
Tile other = world.tile(worldx, worldy);
|
||||
|
||||
if(other != null){
|
||||
if(pass == 0){
|
||||
//first pass: delete existing blocks - this should automatically trigger removal if overlap exists
|
||||
other.setBlock(Blocks.air);
|
||||
}else{
|
||||
//second pass: assign changed data
|
||||
//assign entity and type to blocks, so they act as proxies for this one
|
||||
other.entity = entity;
|
||||
other.block = block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setBlock(@NonNull Block type, Team team){
|
||||
@@ -168,11 +206,7 @@ public class Tile implements Position{
|
||||
}
|
||||
|
||||
public void setBlock(@NonNull Block type){
|
||||
if(type == null) throw new IllegalArgumentException("Block cannot be null.");
|
||||
preChanged();
|
||||
this.block = type;
|
||||
this.rotation = 0;
|
||||
changed();
|
||||
setBlock(type, Team.derelict, 0);
|
||||
}
|
||||
|
||||
/** This resets the overlay! */
|
||||
@@ -181,7 +215,9 @@ public class Tile implements Position{
|
||||
this.overlay = (Floor)Blocks.air;
|
||||
|
||||
recache();
|
||||
block.onProximityUpdate(this);
|
||||
if(entity != null){
|
||||
block.onProximityUpdate(entity);
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets the floor, preserving overlay.*/
|
||||
@@ -205,32 +241,8 @@ public class Tile implements Position{
|
||||
}
|
||||
|
||||
public void remove(){
|
||||
link().getLinkedTiles(other -> other.setBlock(Blocks.air));
|
||||
}
|
||||
|
||||
public void set(Block block, Team team){
|
||||
set(block, team, 0);
|
||||
}
|
||||
|
||||
public void set(Block block, Team team, int rotation){
|
||||
setBlock(block, team, rotation);
|
||||
if(block.isMultiblock()){
|
||||
int offsetx = -(block.size - 1) / 2;
|
||||
int offsety = -(block.size - 1) / 2;
|
||||
|
||||
for(int dx = 0; dx < block.size; dx++){
|
||||
for(int dy = 0; dy < block.size; dy++){
|
||||
int worldx = dx + offsetx + x;
|
||||
int worldy = dy + offsety + y;
|
||||
if(!(worldx == x && worldy == y)){
|
||||
Tile toplace = world.tile(worldx, worldy);
|
||||
if(toplace != null){
|
||||
toplace.setBlock(BlockPart.get(dx + offsetx, dy + offsety), team);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//this automatically removes multiblock references to this block
|
||||
setBlock(Blocks.air);
|
||||
}
|
||||
|
||||
/** remove()-s this tile, except it's synced across the network */
|
||||
@@ -274,11 +286,13 @@ public class Tile implements Position{
|
||||
}
|
||||
|
||||
public void setOverlayID(short ore){
|
||||
this.overlay = (Floor)content.block(ore);
|
||||
setOverlay(content.block(ore));
|
||||
}
|
||||
|
||||
public void setOverlay(Block block){
|
||||
this.overlay = (Floor)block;
|
||||
|
||||
recache();
|
||||
}
|
||||
|
||||
public void clearOverlay(){
|
||||
@@ -286,7 +300,7 @@ public class Tile implements Position{
|
||||
}
|
||||
|
||||
public boolean passable(){
|
||||
return isLinked() || !((floor.solid && (block == Blocks.air || block.solidifes)) || (block.solid && (!block.destructible && !block.update)));
|
||||
return !((floor.solid && (block == Blocks.air || block.solidifes)) || (block.solid && (!block.destructible && !block.update)));
|
||||
}
|
||||
|
||||
/** Whether this block was placed by a player/unit. */
|
||||
@@ -295,27 +309,19 @@ public class Tile implements Position{
|
||||
}
|
||||
|
||||
public boolean solid(){
|
||||
return block.solid || block.isSolidFor(this) || (isLinked() && link() != this && link().solid());
|
||||
return block.solid || (entity != null && block.isSolidFor(entity));
|
||||
}
|
||||
|
||||
public boolean breakable(){
|
||||
return !isLinked() ? (block.destructible || block.breakable || block.update) : link().breakable();
|
||||
}
|
||||
|
||||
public Tile link(){
|
||||
return block.linked(this);
|
||||
return block.destructible || block.breakable || block.update;
|
||||
}
|
||||
|
||||
public boolean isEnemyCheat(){
|
||||
return team() == state.rules.waveTeam && state.rules.enemyCheat;
|
||||
}
|
||||
|
||||
public boolean isLinked(){
|
||||
return block instanceof BlockPart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of all tiles linked to this multiblock, or an empty array if it's not a multiblock.
|
||||
* Returns the list of all tiles linked to this multiblock, or just itself if it's not a multiblock.
|
||||
* This array contains all linked tiles, including this tile itself.
|
||||
*/
|
||||
public void getLinkedTiles(Cons<Tile> cons){
|
||||
@@ -385,29 +391,29 @@ public class Tile implements Position{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Tile getNearbyLink(int rotation){
|
||||
if(rotation == 0) return world.ltile(x + 1, y);
|
||||
if(rotation == 1) return world.ltile(x, y + 1);
|
||||
if(rotation == 2) return world.ltile(x - 1, y);
|
||||
if(rotation == 3) return world.ltile(x, y - 1);
|
||||
public Tilec getNearbyEntity(int rotation){
|
||||
if(rotation == 0) return world.ent(x + 1, y);
|
||||
if(rotation == 1) return world.ent(x, y + 1);
|
||||
if(rotation == 2) return world.ent(x - 1, y);
|
||||
if(rotation == 3) return world.ent(x, y - 1);
|
||||
return null;
|
||||
}
|
||||
|
||||
// ▲ ▲ ▼ ▼ ◀ ▶ ◀ ▶ B A
|
||||
public @Nullable Tile front(){
|
||||
return getNearbyLink((rotation + 4) % 4);
|
||||
public @Nullable Tilec front(){
|
||||
return getNearbyEntity((rotation + 4) % 4);
|
||||
}
|
||||
|
||||
public @Nullable Tile right(){
|
||||
return getNearbyLink((rotation + 3) % 4);
|
||||
public @Nullable Tilec right(){
|
||||
return getNearbyEntity((rotation + 3) % 4);
|
||||
}
|
||||
|
||||
public @Nullable Tile back(){
|
||||
return getNearbyLink((rotation + 2) % 4);
|
||||
public @Nullable Tilec back(){
|
||||
return getNearbyEntity((rotation + 2) % 4);
|
||||
}
|
||||
|
||||
public @Nullable Tile left(){
|
||||
return getNearbyLink((rotation + 1) % 4);
|
||||
public @Nullable Tilec left(){
|
||||
return getNearbyEntity((rotation + 1) % 4);
|
||||
}
|
||||
|
||||
public boolean interactable(Team team){
|
||||
@@ -443,8 +449,8 @@ public class Tile implements Position{
|
||||
|
||||
//+26
|
||||
|
||||
if(link().synthetic() && link().solid()){
|
||||
cost += Mathf.clamp(link().block.health / 10f, 0, 20);
|
||||
if(block.synthetic() && solid()){
|
||||
cost += Mathf.clamp(block.health / 10f, 0, 20);
|
||||
}
|
||||
|
||||
//+46
|
||||
@@ -467,15 +473,34 @@ public class Tile implements Position{
|
||||
}
|
||||
|
||||
protected void preChanged(){
|
||||
block.removed(this);
|
||||
if(entity != null){
|
||||
//only call removed() for the center block - this only gets called once.
|
||||
block.removed(entity);
|
||||
entity.removeFromProximity();
|
||||
|
||||
//remove this tile's dangling entities
|
||||
if(entity.block().isMultiblock()){
|
||||
int size = entity.block().size;
|
||||
int offsetx = -(size - 1) / 2;
|
||||
int offsety = -(size - 1) / 2;
|
||||
for(int dx = 0; dx < size; dx++){
|
||||
for(int dy = 0; dy < size; dy++){
|
||||
Tile other = world.tile(entity.tileX() + dx + offsetx, entity.tileY() + dy + offsety);
|
||||
if(other != null){
|
||||
//reset entity and block *manually* - thus, preChanged() will not be called anywhere else, for multiblocks
|
||||
other.entity = null;
|
||||
other.block = Blocks.air;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//recache when static blocks get changed
|
||||
if(block.isStatic()){
|
||||
recache();
|
||||
}
|
||||
team = 0;
|
||||
}
|
||||
|
||||
protected void changed(){
|
||||
@@ -493,18 +518,18 @@ public class Tile implements Position{
|
||||
if(block.hasLiquids) entity.liquids(new LiquidModule());
|
||||
if(block.hasPower){
|
||||
entity.power(new PowerModule());
|
||||
entity.power().graph.add(this);
|
||||
entity.power().graph.add(entity);
|
||||
}
|
||||
|
||||
if(!world.isGenerating()){
|
||||
entity.updateProximity();
|
||||
}
|
||||
}else if(!(block instanceof BlockPart) && !world.isGenerating()){
|
||||
}else if(!world.isGenerating()){
|
||||
//since the entity won't update proximity for us, update proximity for all nearby tiles manually
|
||||
for(Point2 p : Geometry.d4){
|
||||
Tile tile = world.ltile(x + p.x, y + p.y);
|
||||
Tile tile = world.tile(x + p.x, y + p.y);
|
||||
if(tile != null){
|
||||
tile.block().onProximityUpdate(tile);
|
||||
tile.block().onProximityUpdate(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -549,7 +574,7 @@ public class Tile implements Position{
|
||||
|
||||
@Remote(called = Loc.server)
|
||||
public static void setTile(Tile tile, Block block, Team team, int rotation){
|
||||
tile.set(block, team, rotation);
|
||||
tile.setBlock(block, team, rotation);
|
||||
}
|
||||
|
||||
@Remote(called = Loc.server, unreliable = true)
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
package mindustry.world.blocks;
|
||||
|
||||
import mindustry.type.Item;
|
||||
import mindustry.type.Liquid;
|
||||
import mindustry.world.Block;
|
||||
import mindustry.world.Tile;
|
||||
|
||||
/**
|
||||
* Used for multiblocks. Each block that is not the center of the multiblock is a part.
|
||||
* Think of these as delegates to the actual block; all events are passed to the target block.
|
||||
* They are made to share all properties from the linked tile/block.
|
||||
*/
|
||||
public class BlockPart extends Block{
|
||||
public final static int maxSize = 9;
|
||||
private final static BlockPart[][] parts = new BlockPart[maxSize][maxSize];
|
||||
|
||||
private final int dx, dy;
|
||||
|
||||
public BlockPart(int dx, int dy){
|
||||
super("part_" + dx + "_" + dy);
|
||||
this.dx = dx;
|
||||
this.dy = dy;
|
||||
solid = false;
|
||||
hasPower = hasItems = hasLiquids = true;
|
||||
parts[dx + maxSize/2][dy + maxSize/2] = this;
|
||||
}
|
||||
|
||||
public static BlockPart get(int dx, int dy){
|
||||
if(dx == -maxSize/2 && dy == -maxSize/2) throw new IllegalArgumentException("Why are you getting a [0,0] blockpart? Stop it.");
|
||||
return parts[dx + maxSize/2][dy + maxSize/2];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
return tile.link().block().acceptItem(item, tile.link(), source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
tile.link().block().handleItem(item, tile.link(), source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleLiquid(Tile tile, Tile source, Liquid liquid, float amount){
|
||||
Block block = tile.link().block();
|
||||
block.handleLiquid(tile.link(), source, liquid, amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){
|
||||
Block block = tile.link().block();
|
||||
return block.hasLiquids && block.acceptLiquid(tile.link(), source, liquid, amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tile linked(Tile tile){
|
||||
Tile out = tile.getNearby(-dx, -dy);
|
||||
return out == null ? tile : out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawTeam(Tile tile){}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){}
|
||||
|
||||
@Override
|
||||
public boolean synthetic(){
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHidden(){
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "BlockPart[" + dx + ", " + dy + "]";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public class BuildBlock extends Block{
|
||||
public static void onConstructFinish(Tile tile, Block block, int builderID, byte rotation, Team team, boolean skipConfig){
|
||||
if(tile == null) return;
|
||||
float healthf = tile.entity == null ? 1f : tile.entity.healthf();
|
||||
tile.set(block, team, rotation);
|
||||
tile.setBlock(block, team, (int)rotation);
|
||||
if(tile.entity != null){
|
||||
tile.entity.health(block.health * healthf);
|
||||
}
|
||||
@@ -265,8 +265,8 @@ public class BuildBlock extends Block{
|
||||
|
||||
if(clampedAmount > 0 && accumulated > 0){ //if it's positive, add it to the core
|
||||
if(core != null){
|
||||
int accepting = core.tile().block().acceptStack(requirements[i].item, accumulated, core.tile(), builder);
|
||||
core.tile().block().handleStack(requirements[i].item, accepting, core.tile(), builder);
|
||||
int accepting = core.tile().block().acceptStack(core.tile(), requirements[i].item, accumulated, builder);
|
||||
core.tile().block().handleStack(core.tile(), requirements[i].item, accepting, builder);
|
||||
accumulator[i] -= accepting;
|
||||
}else{
|
||||
accumulator[i] -= accumulated;
|
||||
|
||||
@@ -10,6 +10,7 @@ import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.net;
|
||||
|
||||
//TODO remove ?
|
||||
public class RespawnBlock{
|
||||
|
||||
public static void drawRespawn(Tile tile, float heat, float progress, float time, Playerc player, UnitType to){
|
||||
|
||||
@@ -18,8 +18,6 @@ import mindustry.world.consumers.*;
|
||||
import mindustry.world.meta.*;
|
||||
import mindustry.world.meta.values.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class ItemTurret extends CooledTurret{
|
||||
@@ -45,7 +43,7 @@ public class ItemTurret extends CooledTurret{
|
||||
stats.add(BlockStat.ammo, new AmmoListValue<>(ammo));
|
||||
consumes.add(new ConsumeItemFilter(i -> ammo.containsKey(i)){
|
||||
@Override
|
||||
public void build(Tile tile, Table table){
|
||||
public void build(Tilec tile, Table table){
|
||||
MultiReqImage image = new MultiReqImage();
|
||||
content.items().each(i -> filter.get(i) && (!state.isCampaign() || data.isUnlocked(i)), item -> image.add(new ReqImage(new ItemImage(item.icon(Cicon.medium)),
|
||||
() -> tile.entity != null && !((ItemTurretEntity)tile.entity).ammo.isEmpty() && ((ItemEntry)tile.<ItemTurretEntity>ent().ammo.peek()).item == item)));
|
||||
@@ -72,7 +70,7 @@ public class ItemTurret extends CooledTurret{
|
||||
|
||||
//add first ammo item to cheaty blocks so they can shoot properly
|
||||
if(tile.isEnemyCheat() && ammo.size > 0){
|
||||
handleItem(ammo.entries().next().key, tile, tile);
|
||||
handleItem(tile, tile, ammo.entries().next().key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +85,7 @@ public class ItemTurret extends CooledTurret{
|
||||
}
|
||||
|
||||
@Override
|
||||
public int acceptStack(Item item, int amount, Tile tile, Teamc source){
|
||||
public int acceptStack(Tile tile, Item item, int amount, Teamc source){
|
||||
TurretEntity entity = tile.ent();
|
||||
|
||||
BulletType type = ammo.get(item);
|
||||
@@ -98,9 +96,9 @@ public class ItemTurret extends CooledTurret{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleStack(Item item, int amount, Tile tile, Teamc source){
|
||||
public void handleStack(Tile tile, Item item, int amount, Teamc source){
|
||||
for(int i = 0; i < amount; i++){
|
||||
handleItem(item, tile, null);
|
||||
handleItem(tile, null, item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +109,7 @@ public class ItemTurret extends CooledTurret{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
public void handleItem(Tile tile, Tile source, Item item){
|
||||
TurretEntity entity = tile.ent();
|
||||
if(entity == null) return;
|
||||
|
||||
@@ -144,7 +142,7 @@ public class ItemTurret extends CooledTurret{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
public boolean acceptItem(Tile tile, Tile source, Item item){
|
||||
TurretEntity entity = tile.ent();
|
||||
|
||||
return ammo != null && ammo.get(item) != null && entity.totalAmmo + ammo.get(item).ammoMultiplier <= maxAmmo;
|
||||
|
||||
@@ -123,7 +123,7 @@ public class LiquidTurret extends Turret{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
public boolean acceptItem(Tile tile, Tile source, Item item){
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ public class ArmoredConveyor extends Conveyor{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
return super.acceptItem(item, tile, source) && (source.block() instanceof Conveyor || Edges.getFacingEdge(source, tile).relativeTo(tile) == tile.rotation());
|
||||
public boolean acceptItem(Tile tile, Tile source, Item item){
|
||||
return super.acceptItem(tile, source, item) && (source.block() instanceof Conveyor || Edges.getFacingEdge(source, tile).relativeTo(tile) == tile.rotation());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,8 +5,6 @@ import arc.util.io.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class BufferedItemBridge extends ExtendingItemBridge{
|
||||
public final int timerAccept = timers++;
|
||||
|
||||
@@ -29,9 +27,9 @@ public class BufferedItemBridge extends ExtendingItemBridge{
|
||||
}
|
||||
|
||||
Item item = entity.buffer.poll();
|
||||
if(entity.timer(timerAccept, 4) && item != null && other.block().acceptItem(item, other, tile)){
|
||||
if(entity.timer(timerAccept, 4) && item != null && other.block().acceptItem(other, tile, item)){
|
||||
entity.cycleSpeed = Mathf.lerpDelta(entity.cycleSpeed, 4f, 0.05f);
|
||||
other.block().handleItem(item, other, tile);
|
||||
other.block().handleItem(other, tile, item);
|
||||
entity.buffer.remove();
|
||||
}else{
|
||||
entity.cycleSpeed = Mathf.lerpDelta(entity.cycleSpeed, 0f, 0.008f);
|
||||
|
||||
@@ -19,8 +19,6 @@ import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class Conveyor extends Block implements Autotiler{
|
||||
@@ -251,18 +249,18 @@ public class Conveyor extends Block implements Autotiler{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getStackOffset(Item item, Tile tile, Vec2 trns){
|
||||
public void getStackOffset(Tile tile, Item item, Vec2 trns){
|
||||
trns.trns(tile.rotation() * 90 + 180f, tilesize / 2f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int acceptStack(Item item, int amount, Tile tile, Teamc source){
|
||||
public int acceptStack(Tile tile, Item item, int amount, Teamc source){
|
||||
ConveyorEntity entity = tile.ent();
|
||||
return Math.min((int)(entity.minitem / itemSpace), amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleStack(Item item, int amount, Tile tile, Teamc source){
|
||||
public void handleStack(Tile tile, Item item, int amount, Teamc source){
|
||||
ConveyorEntity e = tile.ent();
|
||||
amount = Math.min(amount, itemCapacity - e.len);
|
||||
|
||||
@@ -278,7 +276,7 @@ public class Conveyor extends Block implements Autotiler{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
public boolean acceptItem(Tile tile, Tile source, Item item){
|
||||
ConveyorEntity e = tile.ent();
|
||||
if(e.len >= capacity) return false;
|
||||
int direction = source == null ? 0 : Math.abs(source.relativeTo(tile.x, tile.y) - tile.rotation());
|
||||
@@ -286,7 +284,7 @@ public class Conveyor extends Block implements Autotiler{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
public void handleItem(Tile tile, Tile source, Item item){
|
||||
ConveyorEntity e = tile.ent();
|
||||
if(e.len >= capacity) return;
|
||||
|
||||
|
||||
@@ -200,8 +200,8 @@ public class ItemBridge extends Block{
|
||||
|
||||
if(entity.uptime >= 0.5f && entity.timer(timerTransport, transportTime)){
|
||||
Item item = entity.items().take();
|
||||
if(item != null && other.block().acceptItem(item, other, tile)){
|
||||
other.block().handleItem(item, other, tile);
|
||||
if(item != null && other.block().acceptItem(other, tile, item)){
|
||||
other.block().handleItem(other, tile, item);
|
||||
entity.cycleSpeed = Mathf.lerpDelta(entity.cycleSpeed, 4f, 0.05f);
|
||||
}else{
|
||||
entity.cycleSpeed = Mathf.lerpDelta(entity.cycleSpeed, 1f, 0.01f);
|
||||
@@ -252,7 +252,7 @@ public class ItemBridge extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
public boolean acceptItem(Tile tile, Tile source, Item item){
|
||||
if(tile.team() != source.team()) return false;
|
||||
|
||||
ItemBridgeEntity entity = tile.ent();
|
||||
|
||||
@@ -10,8 +10,6 @@ import mindustry.world.DirectionalItemBuffer;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.world.meta.BlockGroup;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static mindustry.Vars.content;
|
||||
|
||||
public class Junction extends Block{
|
||||
@@ -28,7 +26,7 @@ public class Junction extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public int acceptStack(Item item, int amount, Tile tile, Teamc source){
|
||||
public int acceptStack(Tile tile, Item item, int amount, Teamc source){
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -55,11 +53,11 @@ public class Junction extends Block{
|
||||
if(dest != null) dest = dest.link();
|
||||
|
||||
//skip blocks that don't want the item, keep waiting until they do
|
||||
if(dest == null || !dest.block().acceptItem(item, dest, tile) || dest.team() != tile.team()){
|
||||
if(dest == null || !dest.block().acceptItem(dest, tile, item) || dest.team() != tile.team()){
|
||||
continue;
|
||||
}
|
||||
|
||||
dest.block().handleItem(item, dest, tile);
|
||||
dest.block().handleItem(dest, tile, item);
|
||||
System.arraycopy(buffer.buffers[i], 1, buffer.buffers[i], 0, buffer.indexes[i] - 1);
|
||||
buffer.indexes[i] --;
|
||||
}
|
||||
@@ -68,14 +66,14 @@ public class Junction extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
public void handleItem(Tile tile, Tile source, Item item){
|
||||
JunctionEntity entity = tile.ent();
|
||||
int relative = source.relativeTo(tile.x, tile.y);
|
||||
entity.buffer.accept(relative, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
public boolean acceptItem(Tile tile, Tile source, Item item){
|
||||
JunctionEntity entity = tile.ent();
|
||||
int relative = source.relativeTo(tile.x, tile.y);
|
||||
|
||||
|
||||
@@ -221,7 +221,7 @@ public class MassDriver extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
public boolean acceptItem(Tile tile, Tile source, Item item){
|
||||
//mass drivers that ouput only cannot accept items
|
||||
return tile.entity.items().total() < itemCapacity && linkValid(tile);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ public class OverflowGate extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public int acceptStack(Item item, int amount, Tile tile, Teamc source){
|
||||
public int acceptStack(Tile tile, Item item, int amount, Teamc source){
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public class OverflowGate extends Block{
|
||||
|
||||
if(target != null && (entity.time >= 1f)){
|
||||
getTileTarget(tile, entity.lastItem, entity.lastInput, true);
|
||||
target.block().handleItem(entity.lastItem, target, Edges.getFacingEdge(tile, target));
|
||||
target.block().handleItem(target, Edges.getFacingEdge(tile, target), entity.lastItem);
|
||||
entity.items().remove(entity.lastItem, 1);
|
||||
entity.lastItem = null;
|
||||
}
|
||||
@@ -71,14 +71,14 @@ public class OverflowGate extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
public boolean acceptItem(Tile tile, Tile source, Item item){
|
||||
OverflowGateEntity entity = tile.ent();
|
||||
|
||||
return tile.team() == source.team() && entity.lastItem == null && entity.items().total() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
public void handleItem(Tile tile, Tile source, Item item){
|
||||
OverflowGateEntity entity = tile.ent();
|
||||
entity.items().add(item, 1);
|
||||
entity.lastItem = item;
|
||||
@@ -94,13 +94,13 @@ public class OverflowGate extends Block{
|
||||
Tile to = tile.getNearby((from + 2) % 4);
|
||||
if(to == null) return null;
|
||||
Tile edge = Edges.getFacingEdge(tile, to);
|
||||
boolean canForward = to.block().acceptItem(item, to, edge) && to.team() == tile.team() && !(to.block() instanceof OverflowGate);
|
||||
boolean canForward = to.block().acceptItem(to, edge, item) && to.team() == tile.team() && !(to.block() instanceof OverflowGate);
|
||||
|
||||
if(!canForward || invert){
|
||||
Tile a = tile.getNearby(Mathf.mod(from - 1, 4));
|
||||
Tile b = tile.getNearby(Mathf.mod(from + 1, 4));
|
||||
boolean ac = a != null && a.block().acceptItem(item, a, edge) && !(a.block() instanceof OverflowGate) && a.team() == tile.team();
|
||||
boolean bc = b != null && b.block().acceptItem(item, b, edge) && !(b.block() instanceof OverflowGate) && b.team() == tile.team();
|
||||
boolean ac = a != null && a.block().acceptItem(a, edge, item) && !(a.block() instanceof OverflowGate) && a.team() == tile.team();
|
||||
boolean bc = b != null && b.block().acceptItem(b, edge, item) && !(b.block() instanceof OverflowGate) && b.team() == tile.team();
|
||||
|
||||
if(!ac && !bc){
|
||||
return invert && canForward ? to : null;
|
||||
|
||||
@@ -36,7 +36,7 @@ public class Router extends Block{
|
||||
|
||||
if(target != null && (entity.time >= 1f || !(target.block() instanceof Router))){
|
||||
getTileTarget(tile, entity.lastItem, entity.lastInput, true);
|
||||
target.block().handleItem(entity.lastItem, target, Edges.getFacingEdge(tile, target));
|
||||
target.block().handleItem(target, Edges.getFacingEdge(tile, target), entity.lastItem);
|
||||
entity.items().remove(entity.lastItem, 1);
|
||||
entity.lastItem = null;
|
||||
}
|
||||
@@ -44,14 +44,14 @@ public class Router extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
public boolean acceptItem(Tile tile, Tile source, Item item){
|
||||
RouterEntity entity = tile.ent();
|
||||
|
||||
return tile.team() == source.team() && entity.lastItem == null && entity.items().total() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
public void handleItem(Tile tile, Tile source, Item item){
|
||||
RouterEntity entity = tile.ent();
|
||||
entity.items().add(item, 1);
|
||||
entity.lastItem = item;
|
||||
@@ -66,7 +66,7 @@ public class Router extends Block{
|
||||
Tile other = proximity.get((i + counter) % proximity.size);
|
||||
if(set) tile.rotation((byte)((tile.rotation() + 1) % proximity.size));
|
||||
if(other == from && from.block() == Blocks.overflowGate) continue;
|
||||
if(other.block().acceptItem(item, other, Edges.getFacingEdge(tile, other))){
|
||||
if(other.block().acceptItem(other, Edges.getFacingEdge(tile, other), item)){
|
||||
return other;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,17 +77,17 @@ public class Sorter extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
public boolean acceptItem(Tile tile, Tile source, Item item){
|
||||
Tile to = getTileTarget(item, tile, source, false);
|
||||
|
||||
return to != null && to.block().acceptItem(item, to, tile) && to.team() == tile.team();
|
||||
return to != null && to.block().acceptItem(to, tile, item) && to.team() == tile.team();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
public void handleItem(Tile tile, Tile source, Item item){
|
||||
Tile to = getTileTarget(item, tile, source, true);
|
||||
|
||||
to.block().handleItem(item, to, tile);
|
||||
to.block().handleItem(to, tile, item);
|
||||
}
|
||||
|
||||
boolean isSame(Tile tile, Tile other){
|
||||
@@ -112,9 +112,9 @@ public class Sorter extends Block{
|
||||
Tile a = dest.getNearby(Mathf.mod(dir - 1, 4));
|
||||
Tile b = dest.getNearby(Mathf.mod(dir + 1, 4));
|
||||
boolean ac = a != null && !(a.block().instantTransfer && source.block().instantTransfer) &&
|
||||
a.block().acceptItem(item, a, dest);
|
||||
a.block().acceptItem(a, dest, item);
|
||||
boolean bc = b != null && !(b.block().instantTransfer && source.block().instantTransfer) &&
|
||||
b.block().acceptItem(item, b, dest);
|
||||
b.block().acceptItem(b, dest, item);
|
||||
|
||||
if(ac && !bc){
|
||||
to = a;
|
||||
|
||||
@@ -54,7 +54,7 @@ public class LiquidBridge extends ItemBridge{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
public boolean acceptItem(Tile tile, Tile source, Item item){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ public class LiquidExtendingBridge extends ExtendingItemBridge{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
public boolean acceptItem(Tile tile, Tile source, Item item){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
package mindustry.world.blocks.power;
|
||||
|
||||
import arc.*;
|
||||
import arc.struct.*;
|
||||
import arc.math.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.consumers.*;
|
||||
|
||||
public class PowerGraph{
|
||||
private final static Queue<Tile> queue = new Queue<>();
|
||||
private final static Array<Tile> outArray1 = new Array<>();
|
||||
private final static Array<Tile> outArray2 = new Array<>();
|
||||
private final static Queue<Tilec> queue = new Queue<>();
|
||||
private final static Array<Tilec> outArray1 = new Array<>();
|
||||
private final static Array<Tilec> outArray2 = new Array<>();
|
||||
private final static IntSet closedSet = new IntSet();
|
||||
|
||||
private final ObjectSet<Tile> producers = new ObjectSet<>();
|
||||
private final ObjectSet<Tile> consumers = new ObjectSet<>();
|
||||
private final ObjectSet<Tile> batteries = new ObjectSet<>();
|
||||
private final ObjectSet<Tile> all = new ObjectSet<>();
|
||||
private final ObjectSet<Tilec> producers = new ObjectSet<>();
|
||||
private final ObjectSet<Tilec> consumers = new ObjectSet<>();
|
||||
private final ObjectSet<Tilec> batteries = new ObjectSet<>();
|
||||
private final ObjectSet<Tilec> all = new ObjectSet<>();
|
||||
|
||||
private final WindowedMean powerBalance = new WindowedMean(60);
|
||||
private float lastPowerProduced, lastPowerNeeded, lastUsageFraction;
|
||||
@@ -62,21 +62,21 @@ public class PowerGraph{
|
||||
|
||||
public float getPowerProduced(){
|
||||
float powerProduced = 0f;
|
||||
for(Tile producer : producers){
|
||||
for(Tilec producer : producers){
|
||||
if(producer.entity == null) continue;
|
||||
powerProduced += producer.block().getPowerProduction(producer) * producer.entity.delta();
|
||||
powerProduced += producer.block().getPowerProduction(producer) * producer.delta();
|
||||
}
|
||||
return powerProduced;
|
||||
}
|
||||
|
||||
public float getPowerNeeded(){
|
||||
float powerNeeded = 0f;
|
||||
for(Tile consumer : consumers){
|
||||
for(Tilec consumer : consumers){
|
||||
Consumers consumes = consumer.block().consumes;
|
||||
if(consumes.hasPower()){
|
||||
ConsumePower consumePower = consumes.getPower();
|
||||
if(otherConsumersAreValid(consumer, consumePower)){
|
||||
powerNeeded += consumePower.requestedPower(consumer.entity) * consumer.entity.delta();
|
||||
powerNeeded += consumePower.requestedPower(consumer) * consumer.delta();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,10 +85,10 @@ public class PowerGraph{
|
||||
|
||||
public float getBatteryStored(){
|
||||
float totalAccumulator = 0f;
|
||||
for(Tile battery : batteries){
|
||||
for(Tilec battery : batteries){
|
||||
Consumers consumes = battery.block().consumes;
|
||||
if(consumes.hasPower()){
|
||||
totalAccumulator += battery.entity.power().status * consumes.getPower().capacity;
|
||||
totalAccumulator += battery.power().status * consumes.getPower().capacity;
|
||||
}
|
||||
}
|
||||
return totalAccumulator;
|
||||
@@ -96,10 +96,10 @@ public class PowerGraph{
|
||||
|
||||
public float getBatteryCapacity(){
|
||||
float totalCapacity = 0f;
|
||||
for(Tile battery : batteries){
|
||||
for(Tilec battery : batteries){
|
||||
if(battery.block().consumes.hasPower()){
|
||||
ConsumePower power = battery.block().consumes.getPower();
|
||||
totalCapacity += (1f - battery.entity.power().status) * power.capacity;
|
||||
totalCapacity += (1f - battery.power().status) * power.capacity;
|
||||
}
|
||||
}
|
||||
return totalCapacity;
|
||||
@@ -107,7 +107,7 @@ public class PowerGraph{
|
||||
|
||||
public float getTotalBatteryCapacity(){
|
||||
float totalCapacity = 0f;
|
||||
for(Tile battery : batteries){
|
||||
for(Tilec battery : batteries){
|
||||
if(battery.block().consumes.hasPower()){
|
||||
totalCapacity += battery.block().consumes.getPower().capacity;
|
||||
}
|
||||
@@ -121,10 +121,10 @@ public class PowerGraph{
|
||||
|
||||
float used = Math.min(stored, needed);
|
||||
float consumedPowerPercentage = Math.min(1.0f, needed / stored);
|
||||
for(Tile battery : batteries){
|
||||
for(Tilec battery : batteries){
|
||||
Consumers consumes = battery.block().consumes;
|
||||
if(consumes.hasPower()){
|
||||
battery.entity.power().status *= (1f-consumedPowerPercentage);
|
||||
battery.power().status *= (1f-consumedPowerPercentage);
|
||||
}
|
||||
}
|
||||
return used;
|
||||
@@ -136,12 +136,12 @@ public class PowerGraph{
|
||||
float chargedPercent = Math.min(excess/capacity, 1f);
|
||||
if(Mathf.equal(capacity, 0f)) return 0f;
|
||||
|
||||
for(Tile battery : batteries){
|
||||
for(Tilec battery : batteries){
|
||||
Consumers consumes = battery.block().consumes;
|
||||
if(consumes.hasPower()){
|
||||
ConsumePower consumePower = consumes.getPower();
|
||||
if(consumePower.capacity > 0f){
|
||||
battery.entity.power().status += (1f-battery.entity.power().status) * chargedPercent;
|
||||
battery.power().status += (1f-battery.power().status) * chargedPercent;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,25 +151,25 @@ public class PowerGraph{
|
||||
public void distributePower(float needed, float produced){
|
||||
//distribute even if not needed. this is because some might be requiring power but not using it; it updates consumers
|
||||
float coverage = Mathf.zero(needed) && Mathf.zero(produced) ? 0f : Mathf.zero(needed) ? 1f : Math.min(1, produced / needed);
|
||||
for(Tile consumer : consumers){
|
||||
for(Tilec consumer : consumers){
|
||||
Consumers consumes = consumer.block().consumes;
|
||||
if(consumes.hasPower()){
|
||||
ConsumePower consumePower = consumes.getPower();
|
||||
if(consumePower.buffered){
|
||||
if(!Mathf.zero(consumePower.capacity)){
|
||||
// Add an equal percentage of power to all buffers, based on the global power coverage in this graph
|
||||
float maximumRate = consumePower.requestedPower(consumer.entity) * coverage * consumer.entity.delta();
|
||||
consumer.entity.power().status = Mathf.clamp(consumer.entity.power().status + maximumRate / consumePower.capacity);
|
||||
float maximumRate = consumePower.requestedPower(consumer) * coverage * consumer.delta();
|
||||
consumer.power().status = Mathf.clamp(consumer.power().status + maximumRate / consumePower.capacity);
|
||||
}
|
||||
}else{
|
||||
//valid consumers get power as usual
|
||||
if(otherConsumersAreValid(consumer, consumePower)){
|
||||
consumer.entity.power().status = coverage;
|
||||
consumer.power().status = coverage;
|
||||
}else{ //invalid consumers get an estimate, if they were to activate
|
||||
consumer.entity.power().status = Math.min(1, produced / (needed + consumePower.usage * consumer.entity.delta()));
|
||||
consumer.power().status = Math.min(1, produced / (needed + consumePower.usage * consumer.delta()));
|
||||
//just in case
|
||||
if(Float.isNaN(consumer.entity.power().status)){
|
||||
consumer.entity.power().status = 0f;
|
||||
if(Float.isNaN(consumer.power().status)){
|
||||
consumer.power().status = 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -180,10 +180,10 @@ public class PowerGraph{
|
||||
public void update(){
|
||||
if(Core.graphics.getFrameId() == lastFrameUpdated){
|
||||
return;
|
||||
}else if(!consumers.isEmpty() && consumers.first().isEnemyCheat()){
|
||||
}else if(!consumers.isEmpty() && consumers.first().tile().isEnemyCheat()){
|
||||
//when cheating, just set status to 1
|
||||
for(Tile tile : consumers){
|
||||
tile.entity.power().status = 1f;
|
||||
for(Tilec tile : consumers){
|
||||
tile.power().status = 1f;
|
||||
}
|
||||
|
||||
lastPowerNeeded = lastPowerProduced = lastUsageFraction = 1f;
|
||||
@@ -224,14 +224,14 @@ public class PowerGraph{
|
||||
}
|
||||
|
||||
public void add(PowerGraph graph){
|
||||
for(Tile tile : graph.all){
|
||||
for(Tilec tile : graph.all){
|
||||
add(tile);
|
||||
}
|
||||
}
|
||||
|
||||
public void add(Tile tile){
|
||||
if(tile.entity == null || tile.entity.power() == null) return;
|
||||
tile.entity.power().graph = this;
|
||||
public void add(Tilec tile){
|
||||
if(tile.entity == null || tile.power() == null) return;
|
||||
tile.power().graph = this;
|
||||
all.add(tile);
|
||||
|
||||
if(tile.block().outputsPower && tile.block().consumesPower && !tile.block().consumes.getPower().buffered){
|
||||
@@ -246,14 +246,14 @@ public class PowerGraph{
|
||||
}
|
||||
}
|
||||
|
||||
public void reflow(Tile tile){
|
||||
public void reflow(Tilec tile){
|
||||
queue.clear();
|
||||
queue.addLast(tile);
|
||||
closedSet.clear();
|
||||
while(queue.size > 0){
|
||||
Tile child = queue.removeFirst();
|
||||
Tilec child = queue.removeFirst();
|
||||
add(child);
|
||||
for(Tile next : child.block().getPowerConnections(child, outArray2)){
|
||||
for(Tilec next : child.block().getPowerConnections(child, outArray2)){
|
||||
if(!closedSet.contains(next.pos())){
|
||||
queue.addLast(next);
|
||||
closedSet.add(next.pos());
|
||||
@@ -262,22 +262,22 @@ public class PowerGraph{
|
||||
}
|
||||
}
|
||||
|
||||
private void removeSingle(Tile tile){
|
||||
private void removeSingle(Tilec tile){
|
||||
all.remove(tile);
|
||||
producers.remove(tile);
|
||||
consumers.remove(tile);
|
||||
batteries.remove(tile);
|
||||
}
|
||||
|
||||
public void remove(Tile tile){
|
||||
public void remove(Tilec tile){
|
||||
removeSingle(tile);
|
||||
//begin by clearing the closed set
|
||||
closedSet.clear();
|
||||
|
||||
//go through all the connections of this tile
|
||||
for(Tile other : tile.block().getPowerConnections(tile, outArray1)){
|
||||
for(Tilec other : tile.block().getPowerConnections(tile, outArray1)){
|
||||
//a graph has already been assigned to this tile from a previous call, skip it
|
||||
if(other.entity.power().graph != this) continue;
|
||||
if(other.power().graph != this) continue;
|
||||
|
||||
//create graph for this branch
|
||||
PowerGraph graph = new PowerGraph();
|
||||
@@ -287,16 +287,16 @@ public class PowerGraph{
|
||||
queue.addLast(other);
|
||||
while(queue.size > 0){
|
||||
//get child from queue
|
||||
Tile child = queue.removeFirst();
|
||||
Tilec child = queue.removeFirst();
|
||||
//remove it from this graph
|
||||
removeSingle(child);
|
||||
//add it to the new branch graph
|
||||
graph.add(child);
|
||||
//go through connections
|
||||
for(Tile next : child.block().getPowerConnections(child, outArray2)){
|
||||
for(Tilec next : child.block().getPowerConnections(child, outArray2)){
|
||||
//make sure it hasn't looped back, and that the new graph being assigned hasn't already been assigned
|
||||
//also skip closed tiles
|
||||
if(next != tile && next.entity.power().graph != graph && !closedSet.contains(next.pos())){
|
||||
if(next != tile && next.power().graph != graph && !closedSet.contains(next.pos())){
|
||||
queue.addLast(next);
|
||||
closedSet.add(next.pos());
|
||||
}
|
||||
@@ -307,9 +307,9 @@ public class PowerGraph{
|
||||
}
|
||||
}
|
||||
|
||||
private boolean otherConsumersAreValid(Tile tile, Consume consumePower){
|
||||
private boolean otherConsumersAreValid(Tilec tile, Consume consumePower){
|
||||
for(Consume cons : tile.block().consumes.all()){
|
||||
if(cons != consumePower && !cons.isOptional() && !cons.valid(tile.ent())){
|
||||
if(cons != consumePower && !cons.isOptional() && !cons.valid(tile)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,12 +313,12 @@ public class PowerNode extends PowerBlock{
|
||||
return tile.entity.power().links.contains(other.pos());
|
||||
}
|
||||
|
||||
public boolean linkValid(Tile tile, Tile link){
|
||||
public boolean linkValid(Tilec tile, Tilec link){
|
||||
return linkValid(tile, link, true);
|
||||
}
|
||||
|
||||
public boolean linkValid(Tile tile, Tile link, boolean checkMaxNodes){
|
||||
if(tile == link || link == null || link.entity == null || tile.entity == null || !link.block().hasPower || tile.team() != link.team()) return false;
|
||||
public boolean linkValid(Tilec tile, Tilec link, boolean checkMaxNodes){
|
||||
if(tile == link || link == null || !link.block().hasPower || tile.team() != link.team()) return false;
|
||||
|
||||
if(overlaps(tile, link, laserRange * tilesize) || (link.block() instanceof PowerNode && overlaps(link, tile, link.<PowerNode>cblock().laserRange * tilesize))){
|
||||
if(checkMaxNodes && link.block() instanceof PowerNode){
|
||||
@@ -369,8 +369,8 @@ public class PowerNode extends PowerBlock{
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
public static boolean insulated(Tile tile, Tile other){
|
||||
return insulated(tile.x, tile.y, other.x, other.y);
|
||||
public static boolean insulated(Tilec tile, Tilec other){
|
||||
return insulated(tile.tileX(), tile.tileY(), other.tileX(), other.tileY());
|
||||
}
|
||||
|
||||
public static boolean insulated(int x, int y, int x2, int y2){
|
||||
|
||||
@@ -59,8 +59,8 @@ public class GenericCrafter extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldIdleSound(Tile tile){
|
||||
return tile.entity.cons().valid();
|
||||
public boolean shouldIdleSound(Tilec tile){
|
||||
return tile.cons().valid();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -59,14 +59,14 @@ public class Incinerator extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
public void handleItem(Tile tile, Tile source, Item item){
|
||||
if(Mathf.chance(0.3)){
|
||||
effect.at(tile.drawx(), tile.drawy());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
public boolean acceptItem(Tile tile, Tile source, Item item){
|
||||
IncineratorEntity entity = tile.ent();
|
||||
return entity.heat > 0.5f;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ public class ItemSource extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
public boolean acceptItem(Tile tile, Tile source, Item item){
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,11 +12,11 @@ public class ItemVoid extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
public void handleItem(Tile tile, Tile source, Item item){
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
public boolean acceptItem(Tile tile, Tile source, Item item){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public class CoreBlock extends StorageBlock{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
public boolean acceptItem(Tile tile, Tile source, Item item){
|
||||
return tile.entity.items().get(item) < getMaximumAccepted(tile, item);
|
||||
}
|
||||
|
||||
@@ -191,9 +191,9 @@ public class CoreBlock extends StorageBlock{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
public void handleItem(Tile tile, Tile source, Item item){
|
||||
if(net.server() || !net.active()){
|
||||
super.handleItem(item, tile, source);
|
||||
super.handleItem(tile, source, item);
|
||||
if(state.rules.tutorial){
|
||||
Events.fire(new CoreItemDeliverEvent());
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public class LaunchPad extends StorageBlock{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
public boolean acceptItem(Tile tile, Tile source, Item item){
|
||||
return item.type == ItemType.material && tile.entity.items().total() < itemCapacity;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,9 @@ public abstract class StorageBlock extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
public boolean acceptItem(Tile tile, Tile source, Item item){
|
||||
StorageBlockEntity entity = tile.ent();
|
||||
return entity.linkedCore != null ? entity.linkedCore.block().acceptItem(item, entity.linkedCore, source) : tile.entity.items().get(item) < getMaximumAccepted(tile, item);
|
||||
return entity.linkedCore != null ? entity.linkedCore.block().acceptItem(entity.linkedCore, source, item) : tile.entity.items().get(item) < getMaximumAccepted(tile, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,7 +3,6 @@ package mindustry.world.consumers;
|
||||
import arc.struct.*;
|
||||
import arc.scene.ui.layout.Table;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.world.meta.BlockStats;
|
||||
|
||||
/** An abstract class that defines a type of resource that a block can consume. */
|
||||
@@ -59,7 +58,7 @@ public abstract class Consume{
|
||||
|
||||
public abstract ConsumeType type();
|
||||
|
||||
public abstract void build(Tile tile, Table table);
|
||||
public abstract void build(Tilec tile, Table table);
|
||||
|
||||
/** Called when a consumption is triggered manually. */
|
||||
public void trigger(Tilec entity){
|
||||
|
||||
@@ -8,7 +8,6 @@ import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.ui.Cicon;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
import mindustry.world.meta.values.*;
|
||||
|
||||
@@ -33,7 +32,7 @@ public class ConsumeItemFilter extends Consume{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(Tile tile, Table table){
|
||||
public void build(Tilec tile, Table table){
|
||||
MultiReqImage image = new MultiReqImage();
|
||||
content.items().each(i -> filter.get(i) && (!state.isCampaign() || data.isUnlocked(i)), item -> image.add(new ReqImage(new ItemImage(item.icon(Cicon.medium), 1), () -> tile.entity != null && tile.entity.items() != null && tile.entity.items().has(item))));
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.ui.Cicon;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
import mindustry.world.meta.values.*;
|
||||
|
||||
@@ -36,7 +35,7 @@ public class ConsumeItems extends Consume{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(Tile tile, Table table){
|
||||
public void build(Tilec tile, Table table){
|
||||
for(ItemStack stack : items){
|
||||
table.add(new ReqImage(new ItemImage(stack.item.icon(Cicon.medium), stack.amount), () -> tile.entity != null && tile.entity.items() != null && tile.entity.items().has(stack.item, stack.amount))).size(8 * 4).padRight(5);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.ui.Cicon;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
public class ConsumeLiquid extends ConsumeLiquidBase{
|
||||
@@ -28,7 +27,7 @@ public class ConsumeLiquid extends ConsumeLiquidBase{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(Tile tile, Table table){
|
||||
public void build(Tilec tile, Table table){
|
||||
table.add(new ReqImage(liquid.icon(Cicon.medium), () -> valid(tile.entity))).size(8 * 4);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import mindustry.type.Liquid;
|
||||
import mindustry.ui.Cicon;
|
||||
import mindustry.ui.MultiReqImage;
|
||||
import mindustry.ui.ReqImage;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.world.meta.BlockStat;
|
||||
import mindustry.world.meta.BlockStats;
|
||||
import mindustry.world.meta.values.LiquidFilterValue;
|
||||
@@ -29,7 +28,7 @@ public class ConsumeLiquidFilter extends ConsumeLiquidBase{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(Tile tile, Table table){
|
||||
public void build(Tilec tile, Table table){
|
||||
Array<Liquid> list = content.liquids().select(l -> !l.isHidden() && filter.get(l));
|
||||
MultiReqImage image = new MultiReqImage();
|
||||
list.each(liquid -> image.add(new ReqImage(liquid.icon(Cicon.medium), () -> tile.entity != null && tile.entity.liquids() != null && tile.entity.liquids().get(liquid) >= use(tile.entity))));
|
||||
|
||||
@@ -3,7 +3,6 @@ package mindustry.world.consumers;
|
||||
import arc.math.Mathf;
|
||||
import arc.scene.ui.layout.Table;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
/** Consumer class for blocks which consume power while being connected to a power graph. */
|
||||
@@ -31,7 +30,7 @@ public class ConsumePower extends Consume{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(Tile tile, Table table){
|
||||
public void build(Tilec tile, Table table){
|
||||
//No tooltip for power, for now
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user