asd
This commit is contained in:
@@ -120,6 +120,8 @@ public class Block extends UnlockableContent{
|
||||
public boolean autoResetEnabled = true;
|
||||
/** if true, the block stops updating when disabled */
|
||||
public boolean noUpdateDisabled = false;
|
||||
/** if true, this block updates when a payload of a unit. Currently unused! */
|
||||
public boolean updateInUnits = true;
|
||||
/** Whether to use this block's color in the minimap. Only used for overlays. */
|
||||
public boolean useColor = true;
|
||||
/** item that drops from this block, used for drills */
|
||||
@@ -152,7 +154,7 @@ public class Block extends UnlockableContent{
|
||||
public boolean alwaysReplace = false;
|
||||
/** if false, this block can never be replaced. */
|
||||
public boolean replaceable = true;
|
||||
/** The block group. Unless {@link #canReplace} is overriden, blocks in the same group can replace each other. */
|
||||
/** The block group. Unless {@link #canReplace} is overridden, blocks in the same group can replace each other. */
|
||||
public BlockGroup group = BlockGroup.none;
|
||||
/** List of block flags. Used for AI indexing. */
|
||||
public EnumSet<BlockFlag> flags = EnumSet.of();
|
||||
@@ -264,6 +266,7 @@ public class Block extends UnlockableContent{
|
||||
/** Main subclass. Non-anonymous. */
|
||||
public @Nullable Class<?> subclass;
|
||||
|
||||
public float selectScroll; //scroll position for certain blocks
|
||||
public Prov<Building> buildType = null; //initialized later
|
||||
public ObjectMap<Class<?>, Cons2> configurations = new ObjectMap<>();
|
||||
|
||||
|
||||
@@ -5,20 +5,29 @@ import arc.scene.style.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class ItemSelection{
|
||||
private static float scrollPos = 0f;
|
||||
|
||||
public static <T extends UnlockableContent> void buildTable(Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer){
|
||||
buildTable(table, items, holder, consumer, true);
|
||||
}
|
||||
|
||||
|
||||
public static <T extends UnlockableContent> void buildTable(Block block, Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer){
|
||||
buildTable(block, table, items, holder, consumer, true);
|
||||
}
|
||||
|
||||
public static <T extends UnlockableContent> void buildTable(Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer, boolean closeSelect){
|
||||
buildTable(null, table, items, holder, consumer, closeSelect);
|
||||
}
|
||||
|
||||
public static <T extends UnlockableContent> void buildTable(@Nullable Block block, Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer, boolean closeSelect){
|
||||
|
||||
ButtonGroup<ImageButton> group = new ButtonGroup<>();
|
||||
group.setMinCheckCount(0);
|
||||
@@ -52,10 +61,13 @@ public class ItemSelection{
|
||||
|
||||
ScrollPane pane = new ScrollPane(cont, Styles.smallPane);
|
||||
pane.setScrollingDisabled(true, false);
|
||||
pane.setScrollYForce(scrollPos);
|
||||
pane.update(() -> {
|
||||
scrollPos = pane.getScrollY();
|
||||
});
|
||||
|
||||
if(block != null){
|
||||
pane.setScrollYForce(block.selectScroll);
|
||||
pane.update(() -> {
|
||||
block.selectScroll = pane.getScrollY();
|
||||
});
|
||||
}
|
||||
|
||||
pane.setOverscroll(false, false);
|
||||
table.add(pane).maxHeight(Scl.scl(40 * 5));
|
||||
|
||||
@@ -109,7 +109,7 @@ public class OverdriveProjector extends Block{
|
||||
float realRange = range + phaseHeat * phaseRangeBoost;
|
||||
|
||||
charge = 0f;
|
||||
indexer.eachBlock(this, realRange, other -> true, other -> other.applyBoost(realBoost(), reload + 1f));
|
||||
indexer.eachBlock(this, realRange, other -> other.block.canOverdrive, other -> other.applyBoost(realBoost(), reload + 1f));
|
||||
}
|
||||
|
||||
if(timer(timerUse, useTime) && efficiency() > 0 && consValid()){
|
||||
|
||||
@@ -31,6 +31,7 @@ public class BaseTurret extends Block{
|
||||
priority = TargetPriority.turret;
|
||||
group = BlockGroup.turrets;
|
||||
flags = EnumSet.of(BlockFlag.turret);
|
||||
updateInUnits = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -100,6 +100,7 @@ public class Turret extends ReloadTurret{
|
||||
public Turret(String name){
|
||||
super(name);
|
||||
liquidCapacity = 20f;
|
||||
quickRotate = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -184,8 +185,8 @@ public class Turret extends ReloadTurret{
|
||||
logicControlTime = logicControlCooldown;
|
||||
logicShooting = !Mathf.zero(p2);
|
||||
|
||||
if(p1 instanceof Posc){
|
||||
targetPosition((Posc)p1);
|
||||
if(p1 instanceof Posc pos){
|
||||
targetPosition(pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ public class PayloadConveyor extends Block{
|
||||
if(!enabled) return;
|
||||
|
||||
if(item != null){
|
||||
item.update();
|
||||
item.update(false);
|
||||
}
|
||||
|
||||
lastInterp = curInterp;
|
||||
|
||||
@@ -124,7 +124,7 @@ public class Sorter extends Block{
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Table table){
|
||||
ItemSelection.buildTable(table, content.items(), () -> sortItem, this::configure);
|
||||
ItemSelection.buildTable(Sorter.this, table, content.items(), () -> sortItem, this::configure);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -37,7 +37,9 @@ public class BuildPayload implements Payload{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
public void update(boolean inUnit){
|
||||
if(inUnit && !build.block.updateInUnits) return;
|
||||
|
||||
if(build.tile == null) build.tile = emptyTile;
|
||||
build.update();
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.blocks.storage.*;
|
||||
@@ -55,7 +56,18 @@ public class Constructor extends BlockProducer{
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Table table){
|
||||
ItemSelection.buildTable(table, content.blocks().select(Constructor.this::canProduce), () -> recipe, this::configure);
|
||||
ItemSelection.buildTable(Constructor.this, table, content.blocks().select(Constructor.this::canProduce), () -> recipe, this::configure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onConfigureTileTapped(Building other){
|
||||
if(this == other){
|
||||
deselect();
|
||||
configure(null);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -36,8 +36,9 @@ public interface Payload extends Position{
|
||||
/** @return the time taken to build this payload. */
|
||||
float buildTime();
|
||||
|
||||
/** update this payload if it is a block */
|
||||
default void update(){}
|
||||
/** update this payload if it is a block
|
||||
* @param inUnit whether this payload is in a unit */
|
||||
default void update(boolean inUnit){}
|
||||
|
||||
/** @return whether this payload was dumped. */
|
||||
default boolean dump(){
|
||||
|
||||
@@ -138,7 +138,7 @@ public class PayloadBlock extends Block{
|
||||
@Override
|
||||
public void updateTile(){
|
||||
if(payload != null){
|
||||
payload.update();
|
||||
payload.update(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -85,12 +85,23 @@ public class PayloadSource extends PayloadBlock{
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Table table){
|
||||
ItemSelection.buildTable(table,
|
||||
ItemSelection.buildTable(PayloadSource.this, table,
|
||||
content.blocks().select(PayloadSource.this::canProduce).<UnlockableContent>as()
|
||||
.and(content.units().select(PayloadSource.this::canProduce).as()),
|
||||
() -> (UnlockableContent)config(), this::configure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onConfigureTileTapped(Building other){
|
||||
if(this == other){
|
||||
deselect();
|
||||
configure(null);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object config(){
|
||||
return unit == null ? block : unit;
|
||||
|
||||
@@ -49,6 +49,7 @@ public class NuclearReactor extends PowerGenerator{
|
||||
|
||||
public NuclearReactor(String name){
|
||||
super(name);
|
||||
updateInUnits = false;
|
||||
itemCapacity = 30;
|
||||
liquidCapacity = 30;
|
||||
hasItems = true;
|
||||
@@ -138,6 +139,7 @@ public class NuclearReactor extends PowerGenerator{
|
||||
if((fuel < 5 && heat < 0.5f) || !state.rules.reactorExplosions) return;
|
||||
|
||||
Effect.shake(6f, 16f, x, y);
|
||||
// * ((float)fuel / itemCapacity) to scale based on fullness
|
||||
Damage.damage(x, y, explosionRadius * tilesize, explosionDamage * 4);
|
||||
|
||||
explodeEffect.at(x, y);
|
||||
|
||||
@@ -280,6 +280,13 @@ public class PowerGraph{
|
||||
}
|
||||
}
|
||||
|
||||
public void clear(){
|
||||
all.clear();
|
||||
producers.clear();
|
||||
consumers.clear();
|
||||
batteries.clear();
|
||||
}
|
||||
|
||||
public void reflow(Building tile){
|
||||
queue.clear();
|
||||
queue.addLast(tile);
|
||||
|
||||
@@ -73,7 +73,7 @@ public class ItemSource extends Block{
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Table table){
|
||||
ItemSelection.buildTable(table, content.items(), () -> outputItem, this::configure);
|
||||
ItemSelection.buildTable(ItemSource.this, table, content.items(), () -> outputItem, this::configure);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -73,7 +73,7 @@ public class LiquidSource extends Block{
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Table table){
|
||||
ItemSelection.buildTable(table, content.liquids(), () -> source, this::configure);
|
||||
ItemSelection.buildTable(LiquidSource.this, table, content.liquids(), () -> source, this::configure);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,6 +3,7 @@ package mindustry.world.blocks.storage;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.entities.units.*;
|
||||
@@ -54,56 +55,133 @@ public class Unloader extends Block{
|
||||
public class UnloaderBuild extends Building{
|
||||
public float unloadTimer = 0f;
|
||||
public Item sortItem = null;
|
||||
public Building dumpingTo;
|
||||
public int offset = 0;
|
||||
public int[] rotations;
|
||||
public int rotations = 0;
|
||||
public Seq<ContainerStat> possibleBlocks = new Seq<>();
|
||||
|
||||
public class ContainerStat{
|
||||
Building building;
|
||||
float loadFactor;
|
||||
boolean canLoad;
|
||||
boolean canUnload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
if((unloadTimer += delta()) >= speed){
|
||||
boolean any = false;
|
||||
if(rotations == null || rotations.length != proximity.size){
|
||||
rotations = new int[proximity.size];
|
||||
if(((unloadTimer += delta()) < speed) || (proximity.size < 2)) return;
|
||||
Item item = null;
|
||||
boolean any = false;
|
||||
int itemslength = content.items().size;
|
||||
|
||||
//initialize possibleBlocks only if the new size is bigger than the previous, to avoid unnecessary allocations
|
||||
if(possibleBlocks.size != proximity.size){
|
||||
int tmp = possibleBlocks.size;
|
||||
possibleBlocks.setSize(proximity.size);
|
||||
for(int i = tmp; i < proximity.size; i++){
|
||||
possibleBlocks.set(i, new ContainerStat());
|
||||
}
|
||||
}
|
||||
|
||||
if(sortItem != null){
|
||||
item = sortItem;
|
||||
|
||||
for(int pos = 0; pos < proximity.size; pos++){
|
||||
var other = proximity.get(pos);
|
||||
boolean interactable = other.interactable(team);
|
||||
|
||||
//set the stats of all buildings in possibleBlocks
|
||||
ContainerStat pb = possibleBlocks.get(pos);
|
||||
pb.building = other;
|
||||
pb.canUnload = interactable && other.canUnload() && other.items != null && other.items.has(sortItem);
|
||||
pb.canLoad = interactable && !(other.block instanceof StorageBlock) && other.acceptItem(this, sortItem);
|
||||
}
|
||||
}else{
|
||||
//select the next item for nulloaders
|
||||
//inspired of nextIndex() but for all proximity at once, and also way more powerful
|
||||
for(int i = 0; i < itemslength; i++){
|
||||
int total = (rotations + i + 1) % itemslength;
|
||||
boolean hasProvider = false;
|
||||
boolean hasReceiver = false;
|
||||
boolean isDistinct = false;
|
||||
Item possibleItem = content.item(total);
|
||||
|
||||
for(int pos = 0; pos < proximity.size; pos++){
|
||||
var other = proximity.get(pos);
|
||||
boolean interactable = other.interactable(team);
|
||||
|
||||
//set the stats of all buildings in possibleBlocks while we are at it
|
||||
ContainerStat pb = possibleBlocks.get(pos);
|
||||
pb.building = other;
|
||||
pb.canUnload = interactable && other.canUnload() && other.items != null && other.items.has(possibleItem);
|
||||
pb.canLoad = interactable && !(other.block instanceof StorageBlock) && other.acceptItem(this, possibleItem);
|
||||
|
||||
//the part handling framerate issues and slow conveyor belts, to avoid skipping items
|
||||
if(hasProvider && pb.canLoad) isDistinct = true;
|
||||
if(hasReceiver && pb.canUnload) isDistinct = true;
|
||||
hasProvider = hasProvider || pb.canUnload;
|
||||
hasReceiver = hasReceiver || pb.canLoad;
|
||||
}
|
||||
if(isDistinct){
|
||||
item = possibleItem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(item != null){
|
||||
//only compute the load factor if a transfer is possible
|
||||
for(int pos = 0; pos < proximity.size; pos++){
|
||||
ContainerStat pb = possibleBlocks.get(pos);
|
||||
var other = pb.building;
|
||||
pb.loadFactor = (other.getMaximumAccepted(item) == 0) || (other.items == null) ? 0 : other.items.get(item) / (float)other.getMaximumAccepted(item);
|
||||
}
|
||||
|
||||
for(int i = 0; i < proximity.size; i++){
|
||||
int pos = (offset + i) % proximity.size;
|
||||
var other = proximity.get(pos);
|
||||
//sort so it gives full priority to blocks that can give but not receive (mainly plast and storage), and then by load
|
||||
possibleBlocks.sort((e1, e2) -> {
|
||||
// TODO: instead of canLoad it should be ((instance of Storage) || (is it a plast belt i can unload from))
|
||||
// otherwise a 100% full factory will get full priority over the storage/plast, barely an issue but still wasting trades and thus speed
|
||||
int canLoad = Boolean.compare(e2.canLoad, e1.canLoad);
|
||||
return (canLoad != 0) ? canLoad : Float.compare(e1.loadFactor, e2.loadFactor);
|
||||
});
|
||||
|
||||
if(other.interactable(team) && other.block.unloadable && other.canUnload() && other.block.hasItems
|
||||
&& ((sortItem == null && other.items.total() > 0) || (sortItem != null && other.items.has(sortItem)))){
|
||||
//make sure the item can't be dumped back into this block
|
||||
dumpingTo = other;
|
||||
ContainerStat dumpingFrom = null;
|
||||
ContainerStat dumpingTo = null;
|
||||
|
||||
//get item to be taken
|
||||
Item item = sortItem == null ? other.items.takeIndex(rotations[pos]) : sortItem;
|
||||
|
||||
//remove item if it's dumped correctly
|
||||
if(put(item)){
|
||||
other.items.remove(item, 1);
|
||||
any = true;
|
||||
|
||||
if(sortItem == null){
|
||||
rotations[pos] = item.id + 1;
|
||||
}
|
||||
|
||||
other.itemTaken(item);
|
||||
}else if(sortItem == null){
|
||||
rotations[pos] = other.items.nextIndex(rotations[pos]);
|
||||
}
|
||||
//choose the building to accept the item
|
||||
for(int i = 0; i < possibleBlocks.size; i++){
|
||||
if(possibleBlocks.get(i).canLoad){
|
||||
dumpingTo = possibleBlocks.get(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(any){
|
||||
unloadTimer %= speed;
|
||||
}else{
|
||||
unloadTimer = Math.min(unloadTimer, speed);
|
||||
//choose the building to give the item
|
||||
for(int i = possibleBlocks.size - 1; i >= 0; i--){
|
||||
if(possibleBlocks.get(i).canUnload){
|
||||
dumpingFrom = possibleBlocks.get(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(proximity.size > 0){
|
||||
offset ++;
|
||||
offset %= proximity.size;
|
||||
//trade the items
|
||||
if(dumpingFrom != null && dumpingTo != null && dumpingFrom.loadFactor != dumpingTo.loadFactor){
|
||||
dumpingTo.building.handleItem(this, item);
|
||||
dumpingFrom.building.removeStack(item, 1);
|
||||
any = true;
|
||||
}
|
||||
|
||||
if(sortItem == null) rotations = item.id;
|
||||
}
|
||||
|
||||
if(any){
|
||||
unloadTimer %= speed;
|
||||
}else{
|
||||
unloadTimer = Math.min(unloadTimer, speed);
|
||||
}
|
||||
|
||||
if(proximity.size > 0){
|
||||
offset++;
|
||||
offset %= proximity.size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +196,7 @@ public class Unloader extends Block{
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Table table){
|
||||
ItemSelection.buildTable(table, content.items(), () -> sortItem, this::configure);
|
||||
ItemSelection.buildTable(Unloader.this, table, content.items(), () -> sortItem, this::configure);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -132,11 +210,6 @@ public class Unloader extends Block{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDump(Building to, Item item){
|
||||
return !(to.block instanceof StorageBlock) && to != dumpingTo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item config(){
|
||||
return sortItem;
|
||||
@@ -160,4 +233,4 @@ public class Unloader extends Block{
|
||||
sortItem = id == -1 ? null : content.items().get(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -231,7 +231,7 @@ public class Reconstructor extends UnitBlock{
|
||||
|
||||
@Override
|
||||
public boolean shouldConsume(){
|
||||
return constructing();
|
||||
return constructing() && enabled;
|
||||
}
|
||||
|
||||
public UnitType unit(){
|
||||
|
||||
@@ -160,12 +160,23 @@ public class UnitFactory extends UnitBlock{
|
||||
Seq<UnitType> units = Seq.with(plans).map(u -> u.unit).filter(u -> u.unlockedNow() && !u.isBanned());
|
||||
|
||||
if(units.any()){
|
||||
ItemSelection.buildTable(table, units, () -> currentPlan == -1 ? null : plans.get(currentPlan).unit, unit -> configure(plans.indexOf(u -> u.unit == unit)));
|
||||
ItemSelection.buildTable(UnitFactory.this, table, units, () -> currentPlan == -1 ? null : plans.get(currentPlan).unit, unit -> configure(plans.indexOf(u -> u.unit == unit)));
|
||||
}else{
|
||||
table.table(Styles.black3, t -> t.add("@none").color(Color.lightGray));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onConfigureTileTapped(Building other){
|
||||
if(this == other){
|
||||
deselect();
|
||||
configure(null);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptPayload(Building source, Payload payload){
|
||||
return false;
|
||||
|
||||
@@ -68,7 +68,8 @@ public class ConsumePower extends Consume{
|
||||
* @return The amount of power which is requested per tick.
|
||||
*/
|
||||
public float requestedPower(Building entity){
|
||||
if(entity.tile == null || entity.tile.build == null) return 0f;
|
||||
if(entity == null) return 0f;
|
||||
|
||||
if(buffered){
|
||||
return (1f-entity.power.status)*capacity;
|
||||
}else{
|
||||
|
||||
Reference in New Issue
Block a user