mirror of
https://github.com/Anuken/Mindustry.git
synced 2026-10-02 11:10:50 +03:00
Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a37546835 | ||
|
|
b32b0abbe6 | ||
|
|
ed015e72d0 | ||
|
|
f1ec63a2f7 | ||
|
|
1911f52281 | ||
|
|
0c547d12d5 | ||
|
|
34ec1719ad | ||
|
|
210da0cca1 | ||
|
|
2889160bed |
@@ -5,6 +5,21 @@ import java.lang.annotation.*;
|
||||
public class Annotations{
|
||||
//region entity interfaces
|
||||
|
||||
@Repeatable(BuildingListDefs.class)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface BuildingListDef{
|
||||
String qualifiedType() default "";
|
||||
Class<?> type() default void.class;
|
||||
String method();
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface BuildingListDefs{
|
||||
BuildingListDef[] value();
|
||||
}
|
||||
|
||||
/** Indicates that a method overrides other methods. */
|
||||
@Target({ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
package mindustry.annotations.entity;
|
||||
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.annotations.*;
|
||||
|
||||
import javax.annotation.processing.*;
|
||||
import javax.lang.model.type.*;
|
||||
import javax.tools.*;
|
||||
import java.io.*;
|
||||
|
||||
@SupportedAnnotationTypes("mindustry.annotations.Annotations.BuildingListDefs")
|
||||
public class BuildingListProcess extends BaseProcessor{
|
||||
static final String template = """
|
||||
package mindustry.gen;
|
||||
|
||||
import ELEMENT_TYPE;
|
||||
|
||||
public class CLASS_NAME{
|
||||
public ELEMENT_TYPE[] values = new ELEMENT_TYPE[50];
|
||||
public int size, index;
|
||||
|
||||
public void update(){
|
||||
for(index = 0; index < size; index++){
|
||||
values[index].UPDATE_METHOD_NAME();
|
||||
}
|
||||
}
|
||||
|
||||
public void add(ELEMENT_TYPE building){
|
||||
ELEMENT_TYPE[] items = values;
|
||||
if(size == items.length){
|
||||
int newLength = (int)(size * 1.75f);
|
||||
ELEMENT_TYPE[] newItems = new ELEMENT_TYPE[newLength];
|
||||
System.arraycopy(items, 0, newItems, 0, size);
|
||||
values = items = newItems;
|
||||
}
|
||||
items[building.buildingArrayIndex = size++] = building;
|
||||
}
|
||||
|
||||
public void remove(ELEMENT_TYPE type){
|
||||
int position = type.buildingArrayIndex;
|
||||
|
||||
if(position != -1 && position < size){
|
||||
|
||||
//rarely the entity index is wrong; fallback to slow implementation
|
||||
if(values[position] != type){
|
||||
type.buildingArrayIndex = -1;
|
||||
for(int i = 0; i < size; i++){
|
||||
if(values[position] == type){
|
||||
type.buildingArrayIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//not found in the array (attempt to remove a building that does not exist?)
|
||||
if(type.buildingArrayIndex == -1) return;
|
||||
}
|
||||
|
||||
//swap head with current
|
||||
if(size > 1){
|
||||
var head = values[size - 1];
|
||||
head.buildingArrayIndex = position;
|
||||
values[position] = head;
|
||||
}
|
||||
|
||||
size--;
|
||||
values[size] = null;
|
||||
|
||||
//fix iteration index when removing
|
||||
if(index >= position){
|
||||
index--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
""";
|
||||
|
||||
@Override
|
||||
public void process(RoundEnvironment env) throws Exception{
|
||||
var types = types(BuildingListDefs.class);
|
||||
for(var type : types){
|
||||
for(var listDef : type.annotation(BuildingListDefs.class).value()){
|
||||
String fullName;
|
||||
|
||||
if(!listDef.qualifiedType().isEmpty()){
|
||||
fullName = listDef.qualifiedType();
|
||||
}else{
|
||||
try{
|
||||
fullName = listDef.type().getCanonicalName();
|
||||
}catch(MirroredTypeException e){
|
||||
fullName = e.getTypeMirror().toString();
|
||||
}
|
||||
}
|
||||
|
||||
String simpleName = simpleName(fullName);
|
||||
|
||||
var listMethod = listDef.method();
|
||||
|
||||
String listClassName = (simpleName.endsWith("Build") ? simpleName.replace("Build","") : simpleName) + "List";
|
||||
String resultClass = template
|
||||
.replaceAll("ELEMENT_TYPE", fullName)
|
||||
.replaceAll("CLASS_NAME", listClassName)
|
||||
.replaceAll("UPDATE_METHOD_NAME", listMethod)
|
||||
;
|
||||
|
||||
JavaFileObject object = filer.createSourceFile(packageName + "." + listClassName);
|
||||
Writer stream = object.openWriter();
|
||||
stream.write(resultClass);
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6401,9 +6401,10 @@ public class Blocks{
|
||||
repairSpeed = 0.45f;
|
||||
repairRadius = 60f;
|
||||
beamWidth = 0.73f;
|
||||
powerUse = 1f;
|
||||
pulseRadius = 5f;
|
||||
ambientSoundVolume = 0.9f;
|
||||
|
||||
consumePower(1f);
|
||||
}};
|
||||
|
||||
repairTurret = new RepairTurret("repair-turret"){{
|
||||
@@ -6412,13 +6413,14 @@ public class Blocks{
|
||||
length = 6f;
|
||||
repairSpeed = 3f;
|
||||
repairRadius = 145f;
|
||||
powerUse = 5f;
|
||||
beamWidth = 1.1f;
|
||||
pulseRadius = 6.1f;
|
||||
coolantUse = 0.16f;
|
||||
coolantMultiplier = 1.6f;
|
||||
acceptCoolant = true;
|
||||
ambientSoundVolume = 1.25f;
|
||||
|
||||
consumePower(5f);
|
||||
}};
|
||||
|
||||
//endregion
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
package mindustry.core;
|
||||
|
||||
import arc.math.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.blocks.distribution.BufferedItemBridge.*;
|
||||
import mindustry.world.blocks.distribution.Conveyor.*;
|
||||
import mindustry.world.blocks.distribution.DirectionLiquidBridge.*;
|
||||
import mindustry.world.blocks.distribution.Duct.*;
|
||||
import mindustry.world.blocks.distribution.DuctBridge.*;
|
||||
import mindustry.world.blocks.distribution.DuctRouter.*;
|
||||
import mindustry.world.blocks.distribution.ItemBridge.*;
|
||||
import mindustry.world.blocks.distribution.Junction.*;
|
||||
import mindustry.world.blocks.distribution.Router.*;
|
||||
import mindustry.world.blocks.distribution.StackConveyor.*;
|
||||
import mindustry.world.blocks.liquid.Conduit.*;
|
||||
import mindustry.world.blocks.liquid.LiquidBridge.*;
|
||||
import mindustry.world.blocks.liquid.LiquidRouter.*;
|
||||
import mindustry.world.blocks.power.*;
|
||||
import mindustry.world.blocks.storage.Unloader.*;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
@BuildingListDef(qualifiedType = "mindustry.gen.Building", method = "updateTile")
|
||||
|
||||
@BuildingListDef(type = PowerGraph.class, method = "update")
|
||||
@BuildingListDef(type = ConveyorBuild.class, method = "updateConveyor")
|
||||
@BuildingListDef(type = DuctBuild.class, method = "updateDuct")
|
||||
@BuildingListDef(type = DuctBridgeBuild.class, method = "updateTile")
|
||||
@BuildingListDef(type = JunctionBuild.class, method = "updateJunction")
|
||||
@BuildingListDef(type = RouterBuild.class, method = "updateTile")
|
||||
@BuildingListDef(type = DuctRouterBuild.class, method = "updateTile")
|
||||
@BuildingListDef(type = ItemBridgeBuild.class, method = "update") //TODO: has consume power, meaning updateConsumption needs to be called too (bad)
|
||||
@BuildingListDef(type = BufferedItemBridgeBuild.class, method = "updateTile")
|
||||
@BuildingListDef(type = StackConveyorBuild.class, method = "updateStackConveyor")
|
||||
@BuildingListDef(type = UnloaderBuild.class, method = "updateUnloader")
|
||||
|
||||
@BuildingListDef(type = ConduitBuild.class, method = "updateConduit")
|
||||
@BuildingListDef(type = LiquidRouterBuild.class, method = "updateLiquidRouter")
|
||||
@BuildingListDef(type = LiquidBridgeBuild.class, method = "update") //TODO: has consume power, meaning updateConsumption needs to be called too (bad)
|
||||
@BuildingListDef(type = DirectionLiquidBridgeBuild.class, method = "updateTile")
|
||||
|
||||
/*
|
||||
TODO: make enable/disable just remove them from the list of things that need to update
|
||||
- subpoint: remove all contents of update() as they would no longer be needed
|
||||
|
||||
TODO: remove the 'devirtualized' methods and see if it affects performance at all (check weaker devices too)
|
||||
|
||||
TODO:
|
||||
- refactor checkAllowUpdate in World to not access Groups.build
|
||||
- refactor fog scanning Groups.build (2 different places) and move that into a new thread
|
||||
- finally, remove it from the group list def (footgun avoidance)
|
||||
*
|
||||
*/
|
||||
public class Buildings{
|
||||
public final BuildingList buildings = new BuildingList();
|
||||
|
||||
public final ConveyorList conveyors = new ConveyorList();
|
||||
public final DuctList ducts = new DuctList();
|
||||
public final DuctBridgeList ductBridges = new DuctBridgeList();
|
||||
public final JunctionList junctions = new JunctionList();
|
||||
public final RouterList routers = new RouterList();
|
||||
public final DuctRouterList ductRouters = new DuctRouterList();
|
||||
public final BufferedItemBridgeList bufferedItemBridges = new BufferedItemBridgeList();
|
||||
public final ItemBridgeList itemBridges = new ItemBridgeList();
|
||||
public final StackConveyorList stackConveyors = new StackConveyorList();
|
||||
public final UnloaderList unloaders = new UnloaderList();
|
||||
|
||||
public final ConduitList conduits = new ConduitList();
|
||||
public final LiquidRouterList liquidRouters = new LiquidRouterList();
|
||||
public final LiquidBridgeList liquidBridges = new LiquidBridgeList();
|
||||
public final DirectionLiquidBridgeList directionLiquidBridges = new DirectionLiquidBridgeList();
|
||||
|
||||
public final PowerGraphList powerGraphs = new PowerGraphList();
|
||||
|
||||
private final Seq<Building> timeScaleBuilds = new Seq<>(false, 20, Building.class);
|
||||
private final Seq<Building> timeScaleQueue = new Seq<>(false, 20, Building.class);
|
||||
private final Seq<Building> ambientSoundBuilds = new Seq<>(false, 20, Building.class);
|
||||
private final Seq<Building> ambientSoundQueue = new Seq<>(false, 20, Building.class);
|
||||
private final Seq<LiquidUpdater> liquidUpdateBuilds = new Seq<>(false, 20, LiquidUpdater.class);
|
||||
|
||||
private final Seq<Future<?>> consFutures = new Seq<>();
|
||||
|
||||
public void update(){
|
||||
|
||||
timeScaleBuilds.addAll(timeScaleQueue);
|
||||
timeScaleQueue.clear();
|
||||
|
||||
ambientSoundBuilds.addAll(ambientSoundQueue);
|
||||
ambientSoundQueue.clear();
|
||||
|
||||
Future<?> updateSound = null;
|
||||
|
||||
if(!headless){
|
||||
updateSound = mainExecutor.submit(() -> {
|
||||
Building[] items = ambientSoundBuilds.items;
|
||||
int len = ambientSoundBuilds.size;
|
||||
for(int i = 0; i < len; i++){
|
||||
var build = items[i];
|
||||
|
||||
if(!build.isValid()){
|
||||
ambientSoundBuilds.remove(i);
|
||||
i --;
|
||||
len --;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(build.shouldAmbientSound()){
|
||||
control.sound.loop(build.block.ambientSound, build, build.block.ambientSoundVolume * build.ambientVolume());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
float delta = Time.delta;
|
||||
var updateTimeScale = Vars.mainExecutor.submit(() -> {
|
||||
Building[] items = timeScaleBuilds.items;
|
||||
int len = timeScaleBuilds.size;
|
||||
for(int i = 0; i < len; i++){
|
||||
var build = items[i];
|
||||
if((build.timeScaleDuration -= delta) <= 0f){
|
||||
build.timeScale = 1f;
|
||||
build.hadTimeScale = false;
|
||||
timeScaleBuilds.remove(i);
|
||||
len --;
|
||||
i --;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var updatePower = mainExecutor.submit(() -> {
|
||||
PerfCounter.powerUpdate.begin();
|
||||
powerGraphs.update();
|
||||
PerfCounter.powerUpdate.end();
|
||||
});
|
||||
|
||||
var updateItems = Vars.mainExecutor.submit(() -> {
|
||||
PerfCounter.itemsUpdate.begin();
|
||||
conveyors.update();
|
||||
ducts.update();
|
||||
ductBridges.update();
|
||||
junctions.update();
|
||||
routers.update();
|
||||
ductRouters.update();
|
||||
bufferedItemBridges.update();
|
||||
itemBridges.update();
|
||||
stackConveyors.update();
|
||||
unloaders.update();
|
||||
PerfCounter.itemsUpdate.end();
|
||||
});
|
||||
|
||||
var updateLiquids = Vars.mainExecutor.submit(() -> {
|
||||
PerfCounter.liquidsUpdate.begin();
|
||||
conduits.update();
|
||||
liquidRouters.update();
|
||||
liquidBridges.update();
|
||||
directionLiquidBridges.update();
|
||||
|
||||
{
|
||||
LiquidUpdater[] items = liquidUpdateBuilds.items;
|
||||
int len = liquidUpdateBuilds.size;
|
||||
for(int i = 0; i < len; i++){
|
||||
var build = items[i];
|
||||
if(!build.isAdded()){
|
||||
liquidUpdateBuilds.remove(i);
|
||||
len --;
|
||||
i --;
|
||||
}else{
|
||||
build.processLiquids();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PerfCounter.liquidsUpdate.end();
|
||||
});
|
||||
|
||||
Threads.await(updateItems);
|
||||
Threads.await(updateLiquids);
|
||||
Threads.await(updateTimeScale);
|
||||
Threads.await(updatePower);
|
||||
|
||||
{
|
||||
PerfCounter.consumeUpdate.begin();
|
||||
|
||||
consFutures.clear();
|
||||
int chunks = Mathf.clamp(buildings.size / 400, 1, OS.cores);
|
||||
int chunkSize = Math.max(buildings.size / chunks, 1);
|
||||
|
||||
Building[] items = buildings.values;
|
||||
for(int i = 0; i < buildings.size; i += chunkSize){
|
||||
int from = i;
|
||||
int to = Math.min(buildings.size, i + chunkSize);
|
||||
|
||||
consFutures.add(mainExecutor.submit(() -> {
|
||||
for(int index = from; index < to; index++){
|
||||
items[index].updateConsumption();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
Threads.awaitAll(consFutures);
|
||||
PerfCounter.consumeUpdate.end();
|
||||
}
|
||||
|
||||
if(updateSound != null){
|
||||
Threads.await(updateSound);
|
||||
}
|
||||
|
||||
PerfCounter.otherBuildingsUpdate.begin();
|
||||
buildings.update();
|
||||
PerfCounter.otherBuildingsUpdate.end();
|
||||
}
|
||||
|
||||
public void addLiquidUpdater(LiquidUpdater build){
|
||||
liquidUpdateBuilds.add(build);
|
||||
}
|
||||
|
||||
public void addAmbientSound(Building build){
|
||||
if(headless) return;
|
||||
|
||||
ambientSoundQueue.add(build);
|
||||
}
|
||||
|
||||
public void addTimeScaled(Building build){
|
||||
build.hadTimeScale = true;
|
||||
timeScaleQueue.add(build);
|
||||
}
|
||||
|
||||
public void clear(){
|
||||
//TODO: call clear on all the above
|
||||
}
|
||||
}
|
||||
@@ -41,10 +41,12 @@ public class GameState{
|
||||
public MapLocales mapLocales = new MapLocales();
|
||||
/** Global attributes of the environment, calculated by weather. */
|
||||
public Attributes envAttrs = new Attributes();
|
||||
/** Team data. Gets reset every new game. */
|
||||
/** Cached team data. */
|
||||
public Teams teams = new Teams();
|
||||
/** Handles JSON edits of game content. */
|
||||
/** Handles edits of game content and additional image/audio assets. */
|
||||
public DataManager data = new DataManager();
|
||||
/** All buildings in the map. */
|
||||
public Buildings buildings = new Buildings();
|
||||
/** Number of enemies in the game; only used clientside in servers. */
|
||||
public int enemies;
|
||||
/** Map being playtested (not edited!) */
|
||||
|
||||
@@ -302,6 +302,7 @@ public class Logic implements ApplicationListener{
|
||||
Events.fire(new ResetEvent());
|
||||
world.tiles = new Tiles(0, 0);
|
||||
|
||||
state.buildings.clear();
|
||||
state.data.unload();
|
||||
State prev = state.getState();
|
||||
//recreate gamestate - sets state to menu
|
||||
@@ -564,6 +565,11 @@ public class Logic implements ApplicationListener{
|
||||
state.envAttrs.add(state.rules.attributes);
|
||||
Groups.weather.each(w -> state.envAttrs.add(w.weather.attrs, w.opacity));
|
||||
|
||||
//TODO: possible side effects of buildings before after all bullets do?
|
||||
PerfCounter.buildingUpdate.begin();
|
||||
state.buildings.update();
|
||||
PerfCounter.buildingUpdate.end();
|
||||
|
||||
PerfCounter.entityUpdate.begin();
|
||||
Groups.update();
|
||||
PerfCounter.entityUpdate.end();
|
||||
|
||||
@@ -8,13 +8,19 @@ public enum PerfCounter{
|
||||
frame,
|
||||
update,
|
||||
entityUpdate,
|
||||
buildingUpdate,
|
||||
itemsUpdate,
|
||||
powerUpdate,
|
||||
liquidsUpdate,
|
||||
consumeUpdate,
|
||||
otherBuildingsUpdate,
|
||||
ui,
|
||||
render;
|
||||
|
||||
public static final PerfCounter[] all = values();
|
||||
|
||||
static final int meanWindow = 30;
|
||||
static final int refreshTimeMillis = 500;
|
||||
static final int meanWindow = 120;
|
||||
static final int refreshTimeMillis = 100;
|
||||
|
||||
private long valueRefreshTime;
|
||||
private float refreshValue;
|
||||
|
||||
@@ -467,7 +467,7 @@ public class World{
|
||||
for(var build : team.buildings){
|
||||
//reset map-area-based disabled blocks that were not in the previous map area
|
||||
if(!build.enabled && build.block.autoResetEnabled && !Rect.contains(x, y, w, h, build.tile.x, build.tile.y)){
|
||||
build.enabled = true;
|
||||
build.setEnabled(true);
|
||||
}
|
||||
|
||||
//if the map area contracts, disable the block
|
||||
|
||||
@@ -94,7 +94,7 @@ public class DrawOperation{
|
||||
Block block = content.block(to);
|
||||
tile.setBlock(block, tile.team(), tile.build == null ? 0 : tile.build.rotation);
|
||||
if(tile.build != null){
|
||||
tile.build.enabled = true;
|
||||
tile.build.setEnabled(true);
|
||||
}
|
||||
}
|
||||
case opRotation -> {
|
||||
|
||||
@@ -208,12 +208,10 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
float oldDelta = Time.delta;
|
||||
Time.delta = deltaScl;
|
||||
|
||||
Seq<Building> builds = new Seq<>();
|
||||
Time.clear();
|
||||
|
||||
world.tiles.eachTile(t -> {
|
||||
if(t.build != null && t.isCenter() && t.block().update && t.build.allowUpdate()){
|
||||
builds.add(t.build);
|
||||
if(t.build != null && t.isCenter()){
|
||||
t.build.updateProximity();
|
||||
}
|
||||
});
|
||||
@@ -230,10 +228,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
}
|
||||
}
|
||||
Time.update();
|
||||
for(var build : builds){
|
||||
build.update();
|
||||
}
|
||||
Groups.powerGraph.update();
|
||||
state.buildings.update();
|
||||
Groups.bullet.update(); //needed for mass drivers...
|
||||
}
|
||||
|
||||
@@ -350,7 +345,6 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
}
|
||||
}
|
||||
|
||||
Groups.build.clear();
|
||||
Groups.weather.clear();
|
||||
logic.play();
|
||||
|
||||
|
||||
@@ -8,12 +8,11 @@ class GroupDefs<G>{
|
||||
@GroupDef(value = Playerc.class, mapping = true) G player;
|
||||
@GroupDef(value = Bulletc.class, spatial = true, collide = true) G bullet;
|
||||
@GroupDef(value = Unitc.class, spatial = true, mapping = true) G unit;
|
||||
@GroupDef(value = Buildingc.class, update = true) G build;
|
||||
@GroupDef(value = Buildingc.class) G build;
|
||||
@GroupDef(value = Syncc.class, mapping = true) G sync;
|
||||
@GroupDef(value = Drawc.class) G draw;
|
||||
@GroupDef(value = Firec.class) G fire;
|
||||
@GroupDef(value = Puddlec.class) G puddle;
|
||||
@GroupDef(value = WeatherStatec.class) G weather;
|
||||
@GroupDef(value = WorldLabelc.class, mapping = true) G label;
|
||||
@GroupDef(value = PowerGraphUpdaterc.class) G powerGraph;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ import java.util.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
@EntityDef(value = {Buildingc.class}, excludeGroups = {"all"}, isFinal = false, genio = false, serialize = false)
|
||||
@EntityDef(value = {Buildingc.class}, excludeGroups = {"all", "build"}, isFinal = false, genio = false, serialize = false)
|
||||
@Component(base = true, genInterface = false)
|
||||
abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, QuadTreeObject, Displayable, Sized, Senseable, Controllable, Settable{
|
||||
//region vars and initialization
|
||||
@@ -58,6 +58,9 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
static final BuildDamageEvent bulletDamageEvent = new BuildDamageEvent();
|
||||
static int sleepingEntities = 0;
|
||||
|
||||
transient int buildingArrayIndex = -1;
|
||||
|
||||
@Import boolean added;
|
||||
@Import float x, y, health, maxHealth;
|
||||
@Import Team team;
|
||||
@Import boolean dead;
|
||||
@@ -94,8 +97,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
transient float lastHealTime = -120f * 10f;
|
||||
transient Color suppressColor = Pal.sapBullet;
|
||||
|
||||
transient volatile boolean hadTimeScale = false;
|
||||
transient float timeScale = 1f, timeScaleDuration;
|
||||
|
||||
private transient float lastDamageTime = -recentDamageTime;
|
||||
private transient float timeScale = 1f, timeScaleDuration;
|
||||
private transient float dumpAccum;
|
||||
|
||||
private transient boolean sleeping;
|
||||
@@ -154,11 +159,46 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
return self();
|
||||
}
|
||||
|
||||
@Replace
|
||||
@Override
|
||||
public void add(){
|
||||
//there is no need for a 'is added' guard since it is injected regardless of whether the method is replaced
|
||||
|
||||
addToList();
|
||||
if(power != null){
|
||||
power.graph.checkAdd();
|
||||
power.graph.addUpdate();
|
||||
}
|
||||
|
||||
//note: removal is automatic and thus not necessary in remove()
|
||||
if(block.ambientSound != Sounds.none){
|
||||
state.buildings.addAmbientSound(self());
|
||||
}
|
||||
|
||||
if(this instanceof LiquidUpdater l){
|
||||
state.buildings.addLiquidUpdater(l);
|
||||
}
|
||||
|
||||
added = true;
|
||||
}
|
||||
|
||||
@Replace
|
||||
@Override
|
||||
public void remove(){
|
||||
removeFromList();
|
||||
added = false;
|
||||
}
|
||||
|
||||
public void removeFromList(){
|
||||
state.buildings.buildings.remove(self());
|
||||
}
|
||||
|
||||
public void addToList(){
|
||||
state.buildings.buildings.add(self());
|
||||
}
|
||||
|
||||
//used in clear()
|
||||
public void markRemoved(){
|
||||
added = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -459,12 +499,16 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
|
||||
/** Sets the time scale of the building to the given intensity, unless it's above that value */
|
||||
public void applyBoost(float intensity, float duration){
|
||||
if(!block.canOverdrive) return;
|
||||
if(!block.canOverdrive || duration <= 0f) return;
|
||||
|
||||
//do not refresh time scale when getting a lower intensity
|
||||
if(intensity >= this.timeScale - 0.001f){
|
||||
timeScaleDuration = Math.max(timeScaleDuration, duration);
|
||||
}
|
||||
timeScale = Math.max(timeScale, intensity);
|
||||
if(!hadTimeScale){
|
||||
state.buildings.addTimeScaled(self());
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets the time scale of the building to the given intensity, unless it's below that value */
|
||||
@@ -474,6 +518,9 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
timeScaleDuration = Math.max(timeScaleDuration, duration);
|
||||
}
|
||||
timeScale = Math.min(timeScale, intensity);
|
||||
if(!hadTimeScale){
|
||||
state.buildings.addTimeScaled(self());
|
||||
}
|
||||
}
|
||||
|
||||
public void applyHealSuppression(float amount){
|
||||
@@ -2236,30 +2283,30 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
|
||||
public void checkAllowUpdate(){
|
||||
if(!allowUpdate()){
|
||||
enabled = false;
|
||||
setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enable){
|
||||
if(this.enabled == enable) return;
|
||||
|
||||
if(block.update && block.noUpdateDisabled){
|
||||
if(enable){
|
||||
add();
|
||||
}else{
|
||||
remove();
|
||||
}
|
||||
}
|
||||
this.enabled = enable;
|
||||
}
|
||||
|
||||
@Final
|
||||
@Replace
|
||||
@Override
|
||||
public void update(){
|
||||
|
||||
//TODO refactor to separate loop?
|
||||
if((timeScaleDuration -= Time.delta) <= 0f){
|
||||
timeScale = 1f;
|
||||
}
|
||||
|
||||
//TODO separate multithreaded system for sound? AudioSource, etc
|
||||
if(!headless && block.ambientSound != Sounds.none && shouldAmbientSound()){
|
||||
control.sound.loop(block.ambientSound, self(), block.ambientSoundVolume * ambientVolume());
|
||||
}
|
||||
|
||||
updateConsumption();
|
||||
|
||||
if(enabled || !block.noUpdateDisabled){
|
||||
updateTile();
|
||||
}
|
||||
updateTile();
|
||||
}
|
||||
|
||||
/** When a block is newly revealed outside of camera view range, it is updated on the minimap. */
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
package mindustry.entities.comp;
|
||||
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.blocks.power.*;
|
||||
|
||||
@EntityDef(value = PowerGraphUpdaterc.class, serialize = false, genio = false)
|
||||
@Component
|
||||
abstract class PowerGraphUpdaterComp implements Entityc{
|
||||
public transient PowerGraph graph;
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
graph.update();
|
||||
}
|
||||
}
|
||||
@@ -332,7 +332,7 @@ public abstract class SaveVersion extends SaveFileReader{
|
||||
//set block only if this is the center; otherwise, it's handled elsewhere
|
||||
if(isCenter){
|
||||
tile.setBlock(block);
|
||||
if(tile.build != null) tile.build.enabled = true;
|
||||
if(tile.build != null) tile.build.setEnabled(true);
|
||||
}
|
||||
|
||||
//must be assigned after setBlock, because that can reset data
|
||||
|
||||
@@ -56,7 +56,7 @@ public abstract class LegacySaveVersion extends LegacyRegionSaveVersion{
|
||||
//do not override occupied cells
|
||||
if(!occupied){
|
||||
tile.setBlock(block);
|
||||
if(tile.build != null) tile.build.enabled = true;
|
||||
if(tile.build != null) tile.build.setEnabled(true);
|
||||
}
|
||||
|
||||
if(block.hasBuilding()){
|
||||
|
||||
@@ -101,7 +101,7 @@ public class ShortChunkSaveVersion extends SaveVersion{
|
||||
//set block only if this is the center; otherwise, it's handled elsewhere
|
||||
if(isCenter){
|
||||
tile.setBlock(block);
|
||||
if(tile.build != null) tile.build.enabled = true;
|
||||
if(tile.build != null) tile.build.setEnabled(true);
|
||||
}
|
||||
|
||||
//must be assigned after setBlock, because that can reset data
|
||||
|
||||
@@ -150,6 +150,7 @@ public class ClassMap{
|
||||
classes.put("ExplosionShield", mindustry.world.blocks.ExplosionShield.class);
|
||||
classes.put("ItemSelection", mindustry.world.blocks.ItemSelection.class);
|
||||
classes.put("LaunchAnimator", mindustry.world.blocks.LaunchAnimator.class);
|
||||
classes.put("LiquidUpdater", mindustry.world.blocks.LiquidUpdater.class);
|
||||
classes.put("RotBlock", mindustry.world.blocks.RotBlock.class);
|
||||
classes.put("TileBitmask", mindustry.world.blocks.TileBitmask.class);
|
||||
classes.put("UnitTetherBlock", mindustry.world.blocks.UnitTetherBlock.class);
|
||||
@@ -226,7 +227,7 @@ public class ClassMap{
|
||||
classes.put("DirectionBridge", mindustry.world.blocks.distribution.DirectionBridge.class);
|
||||
classes.put("DirectionBridgeBuild", mindustry.world.blocks.distribution.DirectionBridge.DirectionBridgeBuild.class);
|
||||
classes.put("DirectionLiquidBridge", mindustry.world.blocks.distribution.DirectionLiquidBridge.class);
|
||||
classes.put("DuctBridgeBuild", mindustry.world.blocks.distribution.DirectionLiquidBridge.DuctBridgeBuild.class);
|
||||
classes.put("DirectionLiquidBridgeBuild", mindustry.world.blocks.distribution.DirectionLiquidBridge.DirectionLiquidBridgeBuild.class);
|
||||
classes.put("DirectionalUnloader", mindustry.world.blocks.distribution.DirectionalUnloader.class);
|
||||
classes.put("DirectionalUnloaderBuild", mindustry.world.blocks.distribution.DirectionalUnloader.DirectionalUnloaderBuild.class);
|
||||
classes.put("Duct", mindustry.world.blocks.distribution.Duct.class);
|
||||
|
||||
@@ -566,8 +566,9 @@ public class GameService{
|
||||
}
|
||||
}
|
||||
|
||||
for(var up : Groups.powerGraph){
|
||||
var graph = up.graph();
|
||||
for(int i = 0; i < state.buildings.powerGraphs.size; i++){
|
||||
|
||||
var graph = state.buildings.powerGraphs.values[i];
|
||||
if(graph.all.size > 1 && graph.all.first().team == player.team() && graph.hasPowerBalanceSamples()){
|
||||
float balance = graph.getPowerBalance() * 60f;
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ public class Build{
|
||||
if(tile.team() == Team.derelict && team != Team.derelict && tile.block == result && tile.build != null && tile.block.allowDerelictRepair && state.rules.derelictRepair){
|
||||
tile.build.rotation = rotation;
|
||||
tile.build.changeTeam(team);
|
||||
tile.build.enabled = true;
|
||||
tile.build.setEnabled(true);
|
||||
if(tile.build.power != null){
|
||||
tile.build.power.links.clear();
|
||||
tile.build.powerGraphRemoved();
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package mindustry.world.blocks;
|
||||
|
||||
import mindustry.gen.*;
|
||||
|
||||
public interface LiquidUpdater extends Healthc{
|
||||
void processLiquids();
|
||||
}
|
||||
@@ -624,7 +624,7 @@ public class Turret extends ReloadTurret{
|
||||
}
|
||||
|
||||
protected boolean validateTarget(){
|
||||
return !Units.invalidateTarget(target, canHeal() ? Team.derelict : team, x, y) || isControlled() || logicControlled();
|
||||
return !Units.invalidateTarget(target, canHeal() ? Team.derelict : team, x, y) || unit.isPlayer() || logicControlled();
|
||||
}
|
||||
|
||||
protected boolean canHeal(){
|
||||
|
||||
@@ -6,6 +6,8 @@ import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class BufferedItemBridge extends ItemBridge{
|
||||
public final int timerAccept = timers++;
|
||||
|
||||
@@ -19,7 +21,7 @@ public class BufferedItemBridge extends ItemBridge{
|
||||
hasItems = true;
|
||||
canOverdrive = true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
@@ -28,7 +30,6 @@ public class BufferedItemBridge extends ItemBridge{
|
||||
stats.add(Stat.itemsMoved, displayedSpeed, StatUnit.itemsSecond);
|
||||
}
|
||||
|
||||
|
||||
public class BufferedItemBridgeBuild extends ItemBridgeBuild{
|
||||
ItemBuffer buffer = new ItemBuffer(bufferCapacity);
|
||||
|
||||
@@ -46,12 +47,21 @@ public class BufferedItemBridge extends ItemBridge{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToList(){
|
||||
state.buildings.bufferedItemBridges.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromList(){
|
||||
state.buildings.bufferedItemBridges.remove(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doDump(){
|
||||
dump();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
|
||||
@@ -142,7 +142,7 @@ public class Conveyor extends Block implements Autotiler{
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
int frame = enabled && clogHeat <= 0.5f ? (int)(((Time.time * speed * 8f * timeScale * efficiency)) % 4) : 0;
|
||||
int frame = enabled && clogHeat <= 0.5f ? (int)(((Time.time * speed * 8f * timeScale)) % 4) : 0;
|
||||
|
||||
//draw extra conveyors facing this one for non-square tiling purposes
|
||||
Draw.z(Layer.blockUnder);
|
||||
@@ -250,8 +250,8 @@ public class Conveyor extends Block implements Autotiler{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
public final void updateConveyor(){
|
||||
efficiency = enabled ? 1f : 0f;
|
||||
minitem = 1f;
|
||||
mid = 0;
|
||||
|
||||
@@ -263,7 +263,7 @@ public class Conveyor extends Block implements Autotiler{
|
||||
}
|
||||
|
||||
float nextMax = aligned ? 1f - Math.max(itemSpace - nextc.minitem, 0) : 1f;
|
||||
float moved = speed * edelta();
|
||||
float moved = speed * delta();
|
||||
|
||||
for(int i = len - 1; i >= 0; i--){
|
||||
float nextpos = (i == len - 1 ? 100f : ys[i + 1]) - itemSpace;
|
||||
@@ -297,6 +297,16 @@ public class Conveyor extends Block implements Autotiler{
|
||||
noSleep();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToList(){
|
||||
state.buildings.conveyors.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromList(){
|
||||
state.buildings.conveyors.remove(this);
|
||||
}
|
||||
|
||||
public boolean pass(Item item){
|
||||
if(item != null && next != null && next.team == team && next.acceptItem(this, item)){
|
||||
next.handleItem(this, item);
|
||||
|
||||
@@ -9,6 +9,8 @@ import mindustry.type.*;
|
||||
import mindustry.world.blocks.liquid.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class DirectionLiquidBridge extends DirectionBridge{
|
||||
public final int timerFlow = timers++;
|
||||
|
||||
@@ -33,7 +35,17 @@ public class DirectionLiquidBridge extends DirectionBridge{
|
||||
return new TextureRegion[]{bottomRegion, region, dirRegion};
|
||||
}
|
||||
|
||||
public class DuctBridgeBuild extends DirectionBridgeBuild{
|
||||
public class DirectionLiquidBridgeBuild extends DirectionBridgeBuild{
|
||||
|
||||
@Override
|
||||
public void addToList(){
|
||||
state.buildings.directionLiquidBridges.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromList(){
|
||||
state.buildings.directionLiquidBridges.remove(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawCached(){
|
||||
|
||||
@@ -135,6 +135,16 @@ public class Duct extends Block implements Autotiler{
|
||||
public @Nullable Building next;
|
||||
public @Nullable DuctBuild nextc;
|
||||
|
||||
@Override
|
||||
public void addToList(){
|
||||
state.buildings.ducts.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromList(){
|
||||
state.buildings.ducts.remove(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
draw(false);
|
||||
@@ -189,8 +199,7 @@ public class Duct extends Block implements Autotiler{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
public final void updateDuct(){
|
||||
progress += edelta() / speed * 2f;
|
||||
|
||||
if(current != null && next != null){
|
||||
|
||||
@@ -2,9 +2,10 @@ package mindustry.world.blocks.distribution;
|
||||
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class DuctBridge extends DirectionBridge{
|
||||
public float speed = 5f;
|
||||
|
||||
@@ -26,6 +27,16 @@ public class DuctBridge extends DirectionBridge{
|
||||
public class DuctBridgeBuild extends DirectionBridgeBuild{
|
||||
public float progress = 0f;
|
||||
|
||||
@Override
|
||||
public void addToList(){
|
||||
state.buildings.ductBridges.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromList(){
|
||||
state.buildings.ductBridges.remove(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
var link = lastLink = findLink();
|
||||
|
||||
@@ -97,6 +97,16 @@ public class DuctRouter extends Block{
|
||||
drawItemSelection(sortItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToList(){
|
||||
state.buildings.ductRouters.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromList(){
|
||||
state.buildings.ductRouters.remove(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
progress += edelta() / speed * 2f;
|
||||
|
||||
@@ -315,6 +315,16 @@ public class ItemBridge extends Block{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToList(){
|
||||
state.buildings.itemBridges.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromList(){
|
||||
state.buildings.itemBridges.remove(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
if(timer(timerCheckMoved, 30f)){
|
||||
|
||||
@@ -51,8 +51,16 @@ public class Junction extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
public void addToList(){
|
||||
state.buildings.junctions.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromList(){
|
||||
state.buildings.junctions.remove(this);
|
||||
}
|
||||
|
||||
public final void updateJunction(){
|
||||
for(int i = 0; i < 4; i++){
|
||||
if(buffer.indexes[i] > 0){
|
||||
if(buffer.indexes[i] > capacity) buffer.indexes[i] = capacity;
|
||||
|
||||
@@ -9,6 +9,8 @@ import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class Router extends Block{
|
||||
public float speed = 8f;
|
||||
|
||||
@@ -51,6 +53,16 @@ public class Router extends Block{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToList(){
|
||||
state.buildings.routers.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromList(){
|
||||
state.buildings.routers.remove(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
if(lastItem == null && items.any()){
|
||||
|
||||
@@ -7,6 +7,7 @@ import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
@@ -265,7 +266,18 @@ public class StackConveyor extends Block implements Autotiler{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
public void addToList(){
|
||||
Vars.state.buildings.stackConveyors.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromList(){
|
||||
Vars.state.buildings.stackConveyors.remove(this);
|
||||
}
|
||||
|
||||
public final void updateStackConveyor(){
|
||||
updateConsumption();
|
||||
|
||||
//the item still needs to be "reeled" in when disabled
|
||||
float eff = enabled ? (efficiency + baseEfficiency) : 1f;
|
||||
|
||||
|
||||
@@ -245,8 +245,9 @@ public class Conduit extends LiquidBlock implements Autotiler{
|
||||
&& (tile == null || source == this || (source.relativeTo(tile.x, tile.y) + 2) % 4 != rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
public final void updateConduit(){
|
||||
if(!noUpdateDisabled) return;
|
||||
|
||||
smoothLiquid = Mathf.lerpDelta(smoothLiquid, liquids.currentAmount() / liquidCapacity, 0.05f);
|
||||
|
||||
if(liquids.currentAmount() > 0.0001f && timer(timerFlow, 1)){
|
||||
@@ -257,6 +258,16 @@ public class Conduit extends LiquidBlock implements Autotiler{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToList(){
|
||||
state.buildings.conduits.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromList(){
|
||||
state.buildings.conduits.remove(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Building next(){
|
||||
|
||||
@@ -4,6 +4,8 @@ import mindustry.gen.*;
|
||||
import mindustry.world.blocks.distribution.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class LiquidBridge extends ItemBridge{
|
||||
|
||||
public LiquidBridge(String name){
|
||||
@@ -18,6 +20,16 @@ public class LiquidBridge extends ItemBridge{
|
||||
|
||||
public class LiquidBridgeBuild extends ItemBridgeBuild{
|
||||
|
||||
@Override
|
||||
public void addToList(){
|
||||
state.buildings.liquidBridges.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromList(){
|
||||
state.buildings.liquidBridges.remove(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTransport(Building other){
|
||||
if(warmup >= 0.25f){
|
||||
|
||||
@@ -4,6 +4,8 @@ import arc.graphics.g2d.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class LiquidRouter extends LiquidBlock{
|
||||
public float liquidPadding = 0f;
|
||||
|
||||
@@ -21,11 +23,21 @@ public class LiquidRouter extends LiquidBlock{
|
||||
}
|
||||
|
||||
public class LiquidRouterBuild extends LiquidBuild{
|
||||
@Override
|
||||
public void updateTile(){
|
||||
|
||||
public final void updateLiquidRouter(){
|
||||
dumpLiquid(liquids.current());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToList(){
|
||||
state.buildings.liquidRouters.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromList(){
|
||||
state.buildings.liquidRouters.remove(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
Draw.rect(bottomRegion, x, y);
|
||||
|
||||
@@ -96,7 +96,7 @@ public class LogicBlock extends Block{
|
||||
if(oldSize > entity.links.size){ //check whether any were removed
|
||||
//re-enable the target when unlinking
|
||||
if(lbuild.block.autoResetEnabled && lbuild.lastDisabler == entity){
|
||||
lbuild.enabled = true;
|
||||
lbuild.setEnabled(true);
|
||||
}
|
||||
}else{
|
||||
entity.links.add(new LogicLink(x, y, entity.findLinkName(lbuild.block), true));
|
||||
@@ -456,7 +456,7 @@ public class LogicBlock extends Block{
|
||||
|
||||
for(var link : executor.links){
|
||||
if(!link.enabled && link.lastDisabler == this){
|
||||
link.enabled = true;
|
||||
link.setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ public class SwitchBlock extends Block{
|
||||
group = BlockGroup.logic;
|
||||
envEnabled = Env.any;
|
||||
|
||||
config(Boolean.class, (SwitchBuild entity, Boolean b) -> entity.enabled = b);
|
||||
config(Boolean.class, (SwitchBuild entity, Boolean b) -> entity.setEnabled(b));
|
||||
}
|
||||
|
||||
public boolean accessible(){
|
||||
|
||||
@@ -135,8 +135,6 @@ public class PayloadConveyor extends Block{
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
if(!enabled) return;
|
||||
|
||||
if(item != null){
|
||||
item.update(null, this);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package mindustry.world.blocks.power;
|
||||
import arc.math.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.gen.*;
|
||||
|
||||
public class PowerGraph{
|
||||
@@ -17,7 +18,11 @@ public class PowerGraph{
|
||||
public final Seq<Building> batteries = new Seq<>(false, 16, Building.class);
|
||||
public final Seq<Building> all = new Seq<>(false, 16, Building.class);
|
||||
|
||||
private final @Nullable PowerGraphUpdater entity;
|
||||
public int buildingArrayIndex = -1;
|
||||
|
||||
private boolean added;
|
||||
private final boolean shouldUpdate;
|
||||
|
||||
private final WindowedMean powerBalance = new WindowedMean(60);
|
||||
private float lastPowerProduced, lastPowerNeeded, lastPowerStored;
|
||||
private float lastScaledPowerIn, lastScaledPowerOut, lastCapacity;
|
||||
@@ -28,14 +33,12 @@ public class PowerGraph{
|
||||
private static int lastGraphID;
|
||||
|
||||
public PowerGraph(){
|
||||
entity = PowerGraphUpdater.create();
|
||||
entity.graph = this;
|
||||
graphID = lastGraphID++;
|
||||
this(true);
|
||||
}
|
||||
|
||||
public PowerGraph(boolean noEntity){
|
||||
entity = null;
|
||||
public PowerGraph(boolean shouldUpdate){
|
||||
graphID = lastGraphID++;
|
||||
this.shouldUpdate = shouldUpdate;
|
||||
}
|
||||
|
||||
public int getID(){
|
||||
@@ -216,8 +219,8 @@ public class PowerGraph{
|
||||
public void update(){
|
||||
if(!consumers.isEmpty() && consumers.first().cheating()){
|
||||
//when cheating, just set status to 1
|
||||
for(Building tile : consumers){
|
||||
tile.power.status = 1f;
|
||||
for(int i = 0; i < consumers.size; i++){
|
||||
consumers.items[i].power.status = 1f;
|
||||
}
|
||||
|
||||
lastPowerNeeded = lastPowerProduced = 1f;
|
||||
@@ -266,12 +269,12 @@ public class PowerGraph{
|
||||
}
|
||||
|
||||
//other entity should be removed as the graph was merged
|
||||
if(graph.entity != null) graph.entity.remove();
|
||||
graph.removeUpdate();
|
||||
|
||||
for(Building tile : graph.all){
|
||||
add(tile);
|
||||
}
|
||||
checkAdd();
|
||||
addUpdate();
|
||||
}
|
||||
|
||||
public void add(Building build){
|
||||
@@ -280,7 +283,7 @@ public class PowerGraph{
|
||||
if(build.power.graph != this || !build.power.init){
|
||||
//any old graph that is added here MUST be invalid, remove it
|
||||
if(build.power.graph != null && build.power.graph != this){
|
||||
if(build.power.graph.entity != null) build.power.graph.entity.remove();
|
||||
build.power.graph.removeUpdate();
|
||||
}
|
||||
|
||||
build.power.graph = this;
|
||||
@@ -300,8 +303,18 @@ public class PowerGraph{
|
||||
}
|
||||
}
|
||||
|
||||
public void checkAdd(){
|
||||
if(entity != null) entity.add();
|
||||
public void addUpdate(){
|
||||
if(added || !shouldUpdate) return;
|
||||
|
||||
added = true;
|
||||
Vars.state.buildings.powerGraphs.add(this);
|
||||
}
|
||||
|
||||
public void removeUpdate(){
|
||||
if(!added) return;
|
||||
|
||||
added = false;
|
||||
Vars.state.buildings.powerGraphs.remove(this);
|
||||
}
|
||||
|
||||
public void clear(){
|
||||
@@ -309,8 +322,8 @@ public class PowerGraph{
|
||||
producers.clear();
|
||||
consumers.clear();
|
||||
batteries.clear();
|
||||
//nothing left
|
||||
if(entity != null) entity.remove();
|
||||
|
||||
removeUpdate();
|
||||
}
|
||||
|
||||
public void reflow(Building tile){
|
||||
@@ -320,7 +333,7 @@ public class PowerGraph{
|
||||
while(queue.size > 0){
|
||||
Building child = queue.removeFirst();
|
||||
add(child);
|
||||
checkAdd();
|
||||
addUpdate();
|
||||
for(Building next : child.getPowerConnections(outArray2)){
|
||||
if(closedSet.add(next.pos())){
|
||||
queue.addLast(next);
|
||||
@@ -348,7 +361,7 @@ public class PowerGraph{
|
||||
|
||||
//create graph for this branch
|
||||
PowerGraph graph = new PowerGraph();
|
||||
graph.checkAdd();
|
||||
graph.addUpdate();
|
||||
graph.add(other);
|
||||
//add to queue for BFS
|
||||
queue.clear();
|
||||
@@ -373,7 +386,7 @@ public class PowerGraph{
|
||||
}
|
||||
|
||||
//implied empty graph here
|
||||
if(entity != null) entity.remove();
|
||||
removeUpdate();
|
||||
}
|
||||
|
||||
public int getId(){
|
||||
|
||||
@@ -39,7 +39,6 @@ public class Fracker extends SolidPump{
|
||||
}else{
|
||||
warmup = Mathf.lerpDelta(warmup, 0f, 0.02f);
|
||||
lastPump = 0f;
|
||||
dumpLiquid(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import mindustry.logic.*;
|
||||
import mindustry.mod.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.blocks.liquid.Conduit.*;
|
||||
import mindustry.world.draw.*;
|
||||
import mindustry.world.meta.*;
|
||||
@@ -183,7 +184,7 @@ public class GenericCrafter extends Block{
|
||||
}
|
||||
}
|
||||
|
||||
public class GenericCrafterBuild extends Building{
|
||||
public class GenericCrafterBuild extends Building implements LiquidUpdater{
|
||||
public float progress;
|
||||
public float totalProgress;
|
||||
public float warmup;
|
||||
@@ -321,7 +322,10 @@ public class GenericCrafter extends Block{
|
||||
dump(output.item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processLiquids(){
|
||||
if(outputLiquids != null){
|
||||
for(int i = 0; i < outputLiquids.length; i++){
|
||||
int dir = liquidOutputDirections.length > i ? liquidOutputDirections[i] : -1;
|
||||
|
||||
@@ -9,6 +9,7 @@ import mindustry.game.*;
|
||||
import mindustry.logic.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.blocks.liquid.*;
|
||||
import mindustry.world.draw.*;
|
||||
import mindustry.world.meta.*;
|
||||
@@ -107,7 +108,7 @@ public class Pump extends LiquidBlock{
|
||||
return tile != null && tile.floor().liquidDrop != null;
|
||||
}
|
||||
|
||||
public class PumpBuild extends LiquidBuild{
|
||||
public class PumpBuild extends LiquidBuild implements LiquidUpdater{
|
||||
public float warmup, totalProgress;
|
||||
public float consTimer;
|
||||
public float amount = 0f;
|
||||
@@ -174,7 +175,10 @@ public class Pump extends LiquidBlock{
|
||||
}
|
||||
|
||||
totalProgress += warmup * Time.delta;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processLiquids(){
|
||||
if(liquidDrop != null){
|
||||
dumpLiquid(liquidDrop);
|
||||
}
|
||||
|
||||
@@ -136,7 +136,10 @@ public class SolidPump extends Pump{
|
||||
}
|
||||
|
||||
pumpTime += warmup * edelta();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processLiquids(){
|
||||
dumpLiquid(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,7 @@ public class PowerSource extends PowerNode{
|
||||
@Override
|
||||
public void onProximityUpdate(){
|
||||
super.onProximityUpdate();
|
||||
if(!allowUpdate()){
|
||||
enabled = false;
|
||||
}
|
||||
checkAllowUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -8,6 +8,7 @@ import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import arc.util.pooling.*;
|
||||
import arc.util.pooling.Pool.*;
|
||||
import mindustry.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.gen.*;
|
||||
@@ -159,8 +160,17 @@ public class Unloader extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
if(((unloadTimer += delta()) < speed) || (possibleBlocks.size < 2)) return;
|
||||
public void addToList(){
|
||||
state.buildings.unloaders.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromList(){
|
||||
state.buildings.unloaders.remove(this);
|
||||
}
|
||||
|
||||
public final void updateUnloader(){
|
||||
if(!enabled || ((unloadTimer += delta()) < speed) || (possibleBlocks.size < 2)) return;
|
||||
Item item = null;
|
||||
boolean any = false;
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ public class RepairTurret extends Block{
|
||||
|
||||
public float repairRadius = 50f;
|
||||
public float repairSpeed = 0.3f;
|
||||
public float powerUse;
|
||||
public float length = 5f;
|
||||
public float beamWidth = 1f;
|
||||
public float pulseRadius = 6f;
|
||||
@@ -86,7 +85,6 @@ public class RepairTurret extends Block{
|
||||
consume(new ConsumeCoolant(coolantUse)).optional(true, true);
|
||||
}
|
||||
|
||||
consumePowerCond(powerUse, (RepairPointBuild entity) -> entity.target != null);
|
||||
updateClipRadius(repairRadius + tilesize);
|
||||
super.init();
|
||||
}
|
||||
|
||||
@@ -34,7 +34,9 @@ public class ConsumeItemExplode extends ConsumeItemFilter{
|
||||
|
||||
if(item != null){
|
||||
if(Vars.state.rules.reactorExplosions && Mathf.chance(build.delta() * baseChance * Mathf.clamp(item.explosiveness - threshold))){
|
||||
build.damage(damage);
|
||||
//this can be called in a different thread, so post() it. this is bad for performance, but exploding is just a funny gimmick mechanic anyway, and should not happen in most real games
|
||||
Core.app.post(() -> build.damage(damage));
|
||||
|
||||
explodeEffect.at(build.x + Mathf.range(build.block.size * tilesize / 2f), build.y + Mathf.range(build.block.size * tilesize / 2f));
|
||||
Events.fire(Trigger.blastGenerator);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,9 @@ public class ConsumePayloadDynamic extends Consume{
|
||||
@Override
|
||||
public float efficiency(Building build){
|
||||
float mult = multiplier.get(build);
|
||||
for(PayloadStack stack : payloads.get(build)){
|
||||
var stacks = payloads.get(build);
|
||||
for(int i = 0; i < stacks.size; i ++){
|
||||
var stack = stacks.get(i);
|
||||
if(!build.getPayloads().contains(stack.item, Math.round(stack.amount * mult))){
|
||||
return 0f;
|
||||
}
|
||||
@@ -30,7 +32,9 @@ public class ConsumePayloadDynamic extends Consume{
|
||||
@Override
|
||||
public void trigger(Building build){
|
||||
float mult = multiplier.get(build);
|
||||
for(PayloadStack stack : payloads.get(build)){
|
||||
var stacks = payloads.get(build);
|
||||
for(int i = 0; i < stacks.size; i ++){
|
||||
var stack = stacks.get(i);
|
||||
build.getPayloads().remove(stack.item, Math.round(stack.amount * mult));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,14 @@ import arc.struct.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.blocks.payloads.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
public class ConsumePayloads extends Consume{
|
||||
public Seq<PayloadStack> payloads;
|
||||
public PayloadStack[] payloads;
|
||||
|
||||
public ConsumePayloads(Seq<PayloadStack> payloads){
|
||||
this.payloads = payloads;
|
||||
this.payloads = payloads.toArray(Payload.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user