Merging changes from private branch

This commit is contained in:
Anuken
2025-04-04 11:47:35 -04:00
parent cf5c6d0905
commit b7dbe54d76
161 changed files with 2484 additions and 1137 deletions

View File

@@ -16,7 +16,6 @@ import arc.util.*;
import arc.util.io.*;
import mindustry.*;
import mindustry.annotations.Annotations.*;
import mindustry.audio.*;
import mindustry.content.*;
import mindustry.core.*;
import mindustry.ctype.*;
@@ -47,7 +46,7 @@ import java.util.*;
import static mindustry.Vars.*;
@EntityDef(value = {Buildingc.class}, isFinal = false, genio = false, serialize = false)
@Component(base = true)
@Component(base = true, genInterface = false)
abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, QuadTreeObject, Displayable, Sized, Senseable, Controllable, Settable{
//region vars and initialization
static final float timeToSleep = 60f * 1, recentDamageTime = 60f * 5f;
@@ -63,7 +62,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
transient Tile tile;
transient Block block;
transient Seq<Building> proximity = new Seq<>(6);
transient Seq<Building> proximity = new Seq<>(true, 6, Building.class);
transient int cdump;
transient int rotation;
transient float payloadRotation;
@@ -99,8 +98,6 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
private transient float timeScale = 1f, timeScaleDuration;
private transient float dumpAccum;
private transient @Nullable SoundLoop sound;
private transient boolean sleeping;
private transient float sleepTime;
private transient boolean initialized;
@@ -126,6 +123,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
add();
}
checkAllowUpdate();
created();
return self();
@@ -136,10 +134,6 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
this.block = block;
this.team = team;
if(block.loopSound != Sounds.none){
sound = new SoundLoop(block.loopSound, block.loopSoundVolume);
}
health = block.health;
maxHealth(block.health);
timer(new Interval(block.timers));
@@ -342,13 +336,14 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
public @Nullable Tile findClosestEdge(Position to, Boolf<Tile> solid){
if(to == null) return null;
Tile best = null;
float mindst = 0f;
for(var point : Edges.getEdges(block.size)){
Tile other = Vars.world.tile(tile.x + point.x, tile.y + point.y);
if(other != null && !solid.get(other) && (best == null || to.dst2(other) < mindst)){
best = other;
mindst = other.dst2(other);
mindst = other.dst2(to);
}
}
return best;
@@ -473,6 +468,15 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
return lastDamageTime + recentDamageTime >= Time.time;
}
public void eachEdge(Cons<Tile> cons){
for(var edge : block.getEdges()){
Tile other = world.tile(tile.x + edge.x, tile.y + edge.y);
if(other != null){
cons.get(other);
}
}
}
public Building nearby(int dx, int dy){
return world.build(tile.x + dx, tile.y + dy);
}
@@ -809,6 +813,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
return false;
}
public boolean canBeReplaced(Block other){
return other.canReplace(block);
}
public void handleItem(Building source, Item item){
items.add(item, 1);
}
@@ -1066,7 +1074,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
public void incrementDump(int prox){
cdump = ((cdump + 1) % prox);
//this is possible if transferring an item changed a block
if(prox != 0){
cdump = ((cdump + 1) % prox);
}
}
/** Used for dumping items. */
@@ -1092,6 +1103,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
/** Called after this building is created in the world. May be called multiple times, or when adjacent buildings change. */
//TODO ??? this is just onProximityUpdate ?
public void onProximityAdded(){
if(power != null){
updatePowerGraph();
@@ -1156,16 +1168,6 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
return getProgressIncrease(1f) / edelta();
}
/** @return whether this block should play its active sound.*/
public boolean shouldActiveSound(){
return false;
}
/** @return volume cale of active sound. */
public float activeSoundVolume(){
return 1f;
}
/** @return whether this block should play its idle sound.*/
public boolean shouldAmbientSound(){
return shouldConsume();
@@ -1315,14 +1317,23 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
public void onRemoved(){
}
/** Called every frame a unit is on this */
/** Called every frame a unit is on this. Hovering/flying/steppy units do not apply. */
public void unitOn(Unit unit){
}
/** Called every frame a unit is on this. Applies to any unit. */
public void unitOnAny(Unit unit){
}
/** Called when a unit that spawned at this tile is removed. */
public void unitRemoved(Unit unit){
}
/** Called when a puddle is on this building. Only called at an interval (40 ticks). */
public void puddleOn(Puddle puddle){
}
/** Called when arbitrary configuration is applied to a tile. */
public void configured(@Nullable Unit builder, @Nullable Object value){
//null is of type void.class; anonymous classes use their superclass.
@@ -1372,6 +1383,19 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
return block.itemCapacity;
}
public void splashLiquid(Liquid liquid, float 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.tileWorld(x + Mathf.range(block.size * tilesize / 2), y + Mathf.range(block.size * tilesize / 2));
if(other != null){
Puddles.deposit(other, liquid, splash);
}
});
}
}
/** Called when a block begins (not finishes!) deconstruction. The building is still present at this point. */
public void onDeconstructed(@Nullable Unit builder){
//deposit non-incinerable liquid on ground
@@ -1383,9 +1407,6 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
/** Called when the block is destroyed. The tile is still intact at this stage. */
public void onDestroyed(){
if(sound != null){
sound.stop();
}
float explosiveness = block.baseExplosiveness;
float flammability = 0f;
@@ -1411,22 +1432,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
if(block.hasLiquids && state.rules.damageExplosions){
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.tileWorld(x + Mathf.range(block.size * tilesize / 2), y + Mathf.range(block.size * tilesize / 2));
if(other != null){
Puddles.deposit(other, liquid, splash);
}
});
}
});
liquids.each(this::splashLiquid);
}
//cap explosiveness so fluid tanks/vaults don't instakill units
Damage.dynamicExplosion(x, y, flammability, explosiveness * 3.5f, power, tilesize * block.size / 2f, state.rules.damageExplosions, block.destroyEffect);
Damage.dynamicExplosion(x, y, flammability, explosiveness * 3.5f, power, tilesize * block.size / 2f, state.rules.damageExplosions, block.destroyEffect, block.baseShake);
if(block.createRubble && !floor().solid && !floor().isLiquid){
Effect.rubble(x, y, block.size);
@@ -1657,8 +1667,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
damage = Damage.applyArmor(damage, block.armor);
}
damage(other.team, damage);
Events.fire(bulletDamageEvent.set(self(), other));
damage(other, other.team, damage);
if(health <= 0 && !wasDead){
Events.fire(new BuildingBulletDestroyEvent(self(), other));
@@ -1681,6 +1690,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
/** Changes this building's team in a safe manner. */
public void changeTeam(Team next){
if(this.team == next) return;
if(block.forceTeam != null) team = block.forceTeam;
Team last = this.team;
boolean was = isValid();
@@ -1693,10 +1703,12 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
indexer.addIndex(tile);
Events.fire(teamChangeEvent.set(last, self()));
}
checkAllowUpdate();
}
public boolean canPickup(){
return true;
return block.canPickup;
}
/** Called right before this building is picked up. */
@@ -1764,6 +1776,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
}
public void onNearbyBuildAdded(Building other){}
public void consume(){
for(Consume cons : block.consumers){
cons.trigger(self());
@@ -2094,22 +2108,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
return true;
}
@Override
public void remove(){
stopSound();
}
public void stopSound(){
if(sound != null){
sound.stop();
}
}
@Override
public void killed(){
dead = true;
Events.fire(new BlockDestroyEvent(tile));
block.destroySound.at(tile);
block.destroySound.at(tile, Mathf.random(block.destroyPitchMin, block.destroyPitchMax));
onDestroyed();
if(tile != emptyTile){
tile.remove();
@@ -2118,48 +2121,44 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
afterDestroyed();
}
public void checkAllowUpdate(){
if(!allowUpdate()){
enabled = false;
}
}
@Final
@Replace
@Override
public void update(){
//TODO should just avoid updating buildings instead
if(state.isEditor()) return;
//TODO refactor to timestamp-based system?
if((timeScaleDuration -= Time.delta) <= 0f || !block.canOverdrive){
timeScale = 1f;
}
if(!allowUpdate()){
enabled = false;
}
if(!headless && !wasVisible && state.rules.fog && !inFogTo(player.team())){
visibleFlags |= (1L << player.team().id);
wasVisible = true;
renderer.blocks.updateShadow(self());
renderer.minimap.update(tile);
}
//TODO separate system for sound? AudioSource, etc
if(!headless){
if(sound != null){
sound.update(x, y, shouldActiveSound(), activeSoundVolume());
}
if(block.ambientSound != Sounds.none && shouldAmbientSound()){
control.sound.loop(block.ambientSound, self(), block.ambientSoundVolume * ambientVolume());
}
//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();
//TODO just handle per-block instead
if(enabled || !block.noUpdateDisabled){
updateTile();
}
}
/** When a block is newly revealed outside of camera view range, it is updated on the minimap. */
public void updateFogVisibility(){
if(!wasVisible && !inFogTo(player.team())){
visibleFlags |= (1L << player.team().id);
wasVisible = true;
renderer.blocks.updateShadow(self());
renderer.minimap.update(tile);
}
}
@Override
public void hitbox(Rect out){
out.setCentered(x, y, block.size * tilesize, block.size * tilesize);