Merge branch 'master' into balancing-payload_system

This commit is contained in:
SomeonesShade
2025-06-30 18:15:08 +08:00
committed by GitHub
138 changed files with 1357 additions and 471 deletions

View File

@@ -57,6 +57,8 @@ public class ConstructBlock extends Block{
@Remote(called = Loc.server)
public static void deconstructFinish(Tile tile, Block block, Unit builder){
if(tile == null) return;
Team team = tile.team();
if(!headless && fogControl.isVisibleTile(Vars.player.team(), tile.x, tile.y)){
block.breakEffect.at(tile.drawx(), tile.drawy(), block.size, block.mapColor);

View File

@@ -0,0 +1,23 @@
package mindustry.world.blocks;
public class TileBitmask{
/** Autotile bitmasks for 8-directional sprites (see <a href="https://github.com/GglLfr/tile-gen">tile-gen</a>)*/
public static final int[] values = {
39, 36, 39, 36, 27, 16, 27, 24, 39, 36, 39, 36, 27, 16, 27, 24,
38, 37, 38, 37, 17, 41, 17, 43, 38, 37, 38, 37, 26, 21, 26, 25,
39, 36, 39, 36, 27, 16, 27, 24, 39, 36, 39, 36, 27, 16, 27, 24,
38, 37, 38, 37, 17, 41, 17, 43, 38, 37, 38, 37, 26, 21, 26, 25,
3, 4, 3, 4, 15, 40, 15, 20, 3, 4, 3, 4, 15, 40, 15, 20,
5, 28, 5, 28, 29, 10, 29, 23, 5, 28, 5, 28, 31, 11, 31, 32,
3, 4, 3, 4, 15, 40, 15, 20, 3, 4, 3, 4, 15, 40, 15, 20,
2, 30, 2, 30, 9, 46, 9, 22, 2, 30, 2, 30, 14, 44, 14, 6,
39, 36, 39, 36, 27, 16, 27, 24, 39, 36, 39, 36, 27, 16, 27, 24,
38, 37, 38, 37, 17, 41, 17, 43, 38, 37, 38, 37, 26, 21, 26, 25,
39, 36, 39, 36, 27, 16, 27, 24, 39, 36, 39, 36, 27, 16, 27, 24,
38, 37, 38, 37, 17, 41, 17, 43, 38, 37, 38, 37, 26, 21, 26, 25,
3, 0, 3, 0, 15, 42, 15, 12, 3, 0, 3, 0, 15, 42, 15, 12,
5, 8, 5, 8, 29, 35, 29, 33, 5, 8, 5, 8, 31, 34, 31, 7,
3, 0, 3, 0, 15, 42, 15, 12, 3, 0, 3, 0, 15, 42, 15, 12,
2, 1, 2, 1, 9, 45, 9, 19, 2, 1, 2, 1, 14, 18, 14, 13,
};
}

View File

@@ -223,7 +223,7 @@ public class Accelerator extends Block{
}
public boolean canLaunch(){
return isValid() && state.isCampaign() && efficiency > 0f && power.graph.getBatteryStored() >= powerBufferRequirement-0.00001f && progress >= 1f && !launching;
return isValid() && !net.client() && state.isCampaign() && efficiency > 0f && power.graph.getBatteryStored() >= powerBufferRequirement-0.00001f && progress >= 1f && !launching;
}
@Override

View File

@@ -383,21 +383,24 @@ public class LandingPad extends Block{
t.background(Styles.black6);
t.button(Icon.downOpen, Styles.clearNonei, 40f, () -> {
if(config != null && state.isCampaign()){
for(Sector sector : state.getPlanet().sectors){
if(sector.hasBase() && sector != state.getSector() && sector.info.destination != state.getSector() && sector.info.hasExport(config)){
sector.info.destination = state.getSector();
sector.saveInfo();
}
}
state.getSector().info.refreshImportRates(state.getPlanet());
if(config == null || !state.isCampaign()) return;
for(Sector sector : state.getPlanet().sectors){
if(!canRedirectExports(sector)) continue;
sector.info.destination = state.getSector();
sector.saveInfo();
}
}).disabled(b -> config == null || !state.isCampaign() || (!state.getPlanet().sectors.contains(s -> s.hasBase() && s.info.hasExport(config) && s.info.destination != state.getSector())))
state.getSector().info.refreshImportRates(state.getPlanet());
}).disabled(button -> config == null || !state.isCampaign() || (!state.getPlanet().sectors.contains(this::canRedirectExports)))
.tooltip("@sectors.redirect").get();
}).fillX().left();
}
}
private boolean canRedirectExports(Sector sector){
return sector.hasBase() && sector != state.getSector() && sector.info.hasExport(config) && sector.info.destination != state.getSector();
}
@Override
public void display(Table table){
super.display(table);
@@ -416,14 +419,13 @@ public class LandingPad extends Block{
int sources = 0;
float perSecond = 0f;
for(var s : state.getPlanet().sectors){
if(s != state.getSector() && s.hasBase() && s.info.destination == state.getSector()){
float amount = s.info.getExport(config);
if(amount > 0){
sources ++;
perSecond += s.info.getExport(config);
}
}
for(var otherSector : state.getPlanet().sectors){
if(otherSector == state.getSector() || !otherSector.hasBase() || otherSector.info.destination != state.getSector()) continue;
float amount = otherSector.info.getExport(config);
if(amount <= 0) continue;
sources ++;
perSecond += amount;
}
String str = Core.bundle.format("landing.sources", sources == 0 ? Core.bundle.get("none") : sources);

View File

@@ -96,8 +96,7 @@ public class DirectionalUnloader extends Block{
front.handleItem(this, item);
back.items.remove(item, 1);
back.itemTaken(item);
offset ++;
offset %= itemc;
offset = item.id + 1;
break;
}
}

View File

@@ -215,7 +215,7 @@ public class MassDriver extends Block{
@Override
public double sense(LAccess sensor){
if(sensor == LAccess.progress) return Mathf.clamp(1f - reloadCounter / reload);
if(sensor == LAccess.progress) return Mathf.clamp(1f - reloadCounter);
return super.sense(sensor);
}
@@ -299,13 +299,13 @@ public class MassDriver extends Block{
bullet.create(this, team,
x + Angles.trnsx(angle, translation), y + Angles.trnsy(angle, translation),
angle, -1f, bulletSpeed, bulletLifetime, data);
angle, totalUsed/2f, bulletSpeed, bulletLifetime, data);
shootEffect.at(x + Angles.trnsx(angle, translation), y + Angles.trnsy(angle, translation), angle);
smokeEffect.at(x + Angles.trnsx(angle, translation), y + Angles.trnsy(angle, translation), angle);
Effect.shake(shake, shake, this);
shootSound.at(tile, Mathf.random(0.9f, 1.1f));
}

View File

@@ -15,6 +15,7 @@ import mindustry.graphics.*;
import mindustry.graphics.MultiPacker.*;
import mindustry.type.*;
import mindustry.world.*;
import mindustry.world.blocks.*;
import java.util.*;
@@ -77,8 +78,11 @@ public class Floor extends Block{
public int blendId = -1;
/** If >0, this floor is drawn as parts of a large texture. */
public int tilingVariants = 0;
/** If true, this floor uses autotiling; variants are not supported. See https://github.com/GglLfr/tile-gen*/
public boolean autotile = false;
protected TextureRegion[][][] tilingRegions;
protected TextureRegion[] autotileRegions;
protected int tilingSize;
protected TextureRegion[][] edges;
protected Seq<Floor> blenders = new Seq<>();
@@ -104,6 +108,10 @@ public class Floor extends Block{
public void load(){
super.load();
if(autotile){
variants = 0;
}
int tsize = (int)(tilesize / Draw.scl);
if(tilingVariants > 0 && !headless){
@@ -132,6 +140,13 @@ public class Floor extends Block{
variantRegions[0] = Core.atlas.find(name);
}
if(autotile){
autotileRegions = new TextureRegion[47];
for(int i = 0; i < 47; i++){
autotileRegions[i] = Core.atlas.find(name + "-" + i);
}
}
if(Core.atlas.has(name + "-edge")){
edges = Core.atlas.find(name + "-edge").split(tsize, tsize);
}
@@ -208,6 +223,17 @@ public class Floor extends Block{
int index = Mathf.randomSeed(Point2.pack(tile.x / tilingSize, tile.y / tilingSize), 0, tilingVariants - 1);
TextureRegion[][] regions = tilingRegions[index];
Draw.rect(regions[tile.x % tilingSize][tilingSize - 1 - tile.y % tilingSize], tile.worldx(), tile.worldy());
}else if(autotile){
int bits = 0;
for(int i = 0; i < 8; i++){
Tile other = tile.nearby(Geometry.d8[i]);
if(other != null && other.floor().blendGroup == blendGroup){
bits |= (1 << i);
}
}
Draw.rect(autotileRegions[TileBitmask.values[bits]], tile.worldx(), tile.worldy());
}else{
Draw.rect(variantRegions[variant(tile.x, tile.y)], tile.worldx(), tile.worldy());
}

View File

@@ -51,7 +51,6 @@ public class SteamVent extends Floor{
parent.drawBase(tile);
if(checkAdjacent(tile)){
Mathf.rand.setSeed(tile.pos());
Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx() - tilesize, tile.worldy() - tilesize);
}
}

View File

@@ -17,6 +17,7 @@ import mindustry.annotations.Annotations.*;
import mindustry.entities.units.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.logic.*;
import mindustry.ui.*;
import mindustry.world.*;
@@ -35,7 +36,7 @@ public class CanvasBlock extends Block{
public @Load("@-corner1") TextureRegion corner1;
public @Load("@-corner2") TextureRegion corner2;
protected @Nullable Pixmap previewPixmap;
protected @Nullable Pixmap previewPixmap; // please use only for previews
protected @Nullable Texture previewTexture;
protected int tempBlend = 0;
@@ -49,7 +50,7 @@ public class CanvasBlock extends Block{
config(byte[].class, (CanvasBuild build, byte[] bytes) -> {
if(build.data.length == bytes.length){
build.data = bytes;
System.arraycopy(bytes, 0, build.data, 0, bytes.length);
build.updateTexture();
}
});
@@ -65,13 +66,15 @@ public class CanvasBlock extends Block{
bitsPerPixel = Mathf.log2(Mathf.nextPowerOfTwo(palette.length));
clipSize = Math.max(clipSize, size * 8 - padding);
previewPixmap = new Pixmap(canvasSize, canvasSize);
}
@Override
public void drawPlanRegion(BuildPlan plan, Eachable<BuildPlan> list){
//only draw the preview in schematics, as it lags otherwise
if(!plan.worldContext && plan.config instanceof byte[] data){
Pixmap pix = makePixmap(data);
Pixmap pix = makePixmap(data, previewPixmap);
if(previewTexture == null){
previewTexture = new Texture(pix);
@@ -123,20 +126,15 @@ public class CanvasBlock extends Block{
}
}
/** returns the same pixmap instance each time, use with care */
public Pixmap makePixmap(byte[] data){
if(previewPixmap == null){
previewPixmap = new Pixmap(canvasSize, canvasSize);
}
public Pixmap makePixmap(byte[] data, Pixmap target){
int bpp = bitsPerPixel;
int pixels = canvasSize * canvasSize;
for(int i = 0; i < pixels; i++){
int bitOffset = i * bpp;
int pal = getByte(data, bitOffset);
previewPixmap.set(i % canvasSize, i / canvasSize, palette[pal]);
target.set(i % canvasSize, i / canvasSize, palette[pal]);
}
return previewPixmap;
return target;
}
protected int getByte(byte[] data, int bitOffset){
@@ -152,11 +150,41 @@ public class CanvasBlock extends Block{
public @Nullable Texture texture;
public byte[] data = new byte[Mathf.ceil(canvasSize * canvasSize * bitsPerPixel / 8f)];
public int blending;
protected boolean updated = false;
public void setPixel(int pos, int index){
if(pos < canvasSize * canvasSize && pos >= 0 && index >= 0 && index < palette.length){
setByte(data, pos * bitsPerPixel, index);
updated = true;
}
}
public void setPixel(int x, int y, int index){
if(x >= 0 && y >= 0 && x < canvasSize && y < canvasSize && index >= 0 && index < palette.length){
setByte(data, (y * canvasSize + x) * bitsPerPixel, index);
updated = true;
}
}
public double getPixel(int pos){
if(pos >= 0 && pos < canvasSize * canvasSize){
return getByte(data, pos * bitsPerPixel);
}
return Double.NaN;
}
public int getPixel(int x, int y){
if(x >= 0 && y >= 0 && x < canvasSize && y < canvasSize){
return getByte(data, (y * canvasSize + x) * bitsPerPixel);
}
return 0;
}
public void updateTexture(){
if(headless) return;
Pixmap pix = makePixmap(data);
Pixmap pix = makePixmap(data, previewPixmap);
if(texture != null){
texture.draw(pix);
}else{
@@ -214,7 +242,8 @@ public class CanvasBlock extends Block{
super.draw();
}
if(texture == null){
if(texture == null || updated){
updated = false;
updateTexture();
}
Tmp.tr1.set(texture);
@@ -237,6 +266,14 @@ public class CanvasBlock extends Block{
}
}
}
@Override
public double sense(LAccess sensor){
return switch(sensor){
case displayWidth, displayHeight -> canvasSize;
default -> super.sense(sensor);
};
}
@Override
public void remove(){
@@ -252,12 +289,17 @@ public class CanvasBlock extends Block{
table.button(Icon.pencil, Styles.cleari, () -> {
Dialog dialog = new Dialog();
Pixmap pix = makePixmap(data);
Pixmap pix = makePixmap(data, new Pixmap(canvasSize, canvasSize));
Texture texture = new Texture(pix);
int[] curColor = {palette[0]};
boolean[] modified = {false};
boolean[] fill = {false};
dialog.hidden(() -> {
texture.dispose();
pix.dispose();
});
dialog.resized(dialog::hide);
dialog.cont.table(Tex.pane, body -> {
@@ -395,7 +437,6 @@ public class CanvasBlock extends Block{
dialog.buttons.button("@ok", Icon.ok, () -> {
if(modified[0]){
configure(packPixmap(pix));
texture.dispose();
}
dialog.hide();
});

View File

@@ -78,6 +78,7 @@ public class LogicDisplay extends Block{
public float stroke = 1f;
public LongQueue commands = new LongQueue(256);
public @Nullable Mat transform;
public long operations;
@Override
public void draw(){
@@ -111,6 +112,7 @@ public class LogicDisplay extends Block{
return switch(sensor){
case displayWidth, displayHeight -> displaySize;
case bufferUsage -> commands.size;
case operations -> operations;
default -> super.sense(sensor);
};
}
@@ -121,6 +123,8 @@ public class LogicDisplay extends Block{
for(int i = 0; i < added; i++){
commands.addLast(graphicsBuffer.items[i]);
}
operations++;
}
public void processCommands(){

View File

@@ -13,6 +13,7 @@ import mindustry.annotations.Annotations.*;
import mindustry.graphics.*;
import mindustry.logic.*;
import mindustry.world.*;
import mindustry.world.blocks.*;
import static mindustry.Vars.*;
@@ -27,25 +28,6 @@ public class TileableLogicDisplay extends LogicDisplay{
public @Load(value = "@-#", length = 47) TextureRegion[] tileRegion;
public @Load("@-back") TextureRegion backRegion;
static final int[] bitmasks = {
39, 36, 39, 36, 27, 16, 27, 24, 39, 36, 39, 36, 27, 16, 27, 24,
38, 37, 38, 37, 17, 41, 17, 43, 38, 37, 38, 37, 26, 21, 26, 25,
39, 36, 39, 36, 27, 16, 27, 24, 39, 36, 39, 36, 27, 16, 27, 24,
38, 37, 38, 37, 17, 41, 17, 43, 38, 37, 38, 37, 26, 21, 26, 25,
3, 4, 3, 4, 15, 40, 15, 20, 3, 4, 3, 4, 15, 40, 15, 20,
5, 28, 5, 28, 29, 10, 29, 23, 5, 28, 5, 28, 31, 11, 31, 32,
3, 4, 3, 4, 15, 40, 15, 20, 3, 4, 3, 4, 15, 40, 15, 20,
2, 30, 2, 30, 9, 46, 9, 22, 2, 30, 2, 30, 14, 44, 14, 6,
39, 36, 39, 36, 27, 16, 27, 24, 39, 36, 39, 36, 27, 16, 27, 24,
38, 37, 38, 37, 17, 41, 17, 43, 38, 37, 38, 37, 26, 21, 26, 25,
39, 36, 39, 36, 27, 16, 27, 24, 39, 36, 39, 36, 27, 16, 27, 24,
38, 37, 38, 37, 17, 41, 17, 43, 38, 37, 38, 37, 26, 21, 26, 25,
3, 0, 3, 0, 15, 42, 15, 12, 3, 0, 3, 0, 15, 42, 15, 12,
5, 8, 5, 8, 29, 35, 29, 33, 5, 8, 5, 8, 31, 34, 31, 7,
3, 0, 3, 0, 15, 42, 15, 12, 3, 0, 3, 0, 15, 42, 15, 12,
2, 1, 2, 1, 9, 45, 9, 19, 2, 1, 2, 1, 14, 18, 14, 13,
};
public TileableLogicDisplay(String name){
super(name);
@@ -247,7 +229,7 @@ public class TileableLogicDisplay extends LogicDisplay{
Draw.z(Layer.block + 0.02f);
Draw.rect(tileRegion[bitmasks[bits]], x, y);
Draw.rect(tileRegion[TileBitmask.values[bits]], x, y);
}
@Override

View File

@@ -48,12 +48,12 @@ public class PayloadConveyor extends Block{
public void drawPlace(int x, int y, int rotation, boolean valid){
super.drawPlace(x, y, rotation, valid);
int ntrns = 1 + size/2;
int ntrns = size;
for(int i = 0; i < 4; i++){
Building other = world.build(x + Geometry.d4x[i] * ntrns, y + Geometry.d4y[i] * ntrns);
if(other != null && other.block.outputsPayload && other.block.size == size){
Drawf.selected(other.tileX(), other.tileY(), other.block, other.team.color);
Tile tile = world.tile(x + Geometry.d4x[i] * ntrns, y + Geometry.d4y[i] * ntrns);
if(tile != null && tile.build != null && tile.isCenter() && tile.build.block.outputsPayload && tile.build.block.size == size && (i == rotation || tile.block().rotate && i == (tile.build.rotation + 2) % 4)){
Drawf.selected(tile.x, tile.y, tile.block(), tile.build.team.color);
}
}
}

View File

@@ -1,6 +1,5 @@
package mindustry.world.blocks.power;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.math.geom.*;
@@ -58,14 +57,30 @@ public class LightBlock extends Block{
Placement.calculateNodes(points, this, rotation, (point, other) -> point.dst2(other) <= placeRadius2);
}
@Override
public int minimapColor(Tile tile){
var build = (LightBuild)tile.build;
//make sure A is 255
return build == null ? 0 : build.color | 0xff;
}
public class LightBuild extends Building{
public int color = Pal.accent.rgba();
public float smoothTime = 1f;
@Override
public void configured(Unit player, Object value){
super.configured(player, value);
if(!headless) renderer.minimap.update(tile);
}
@Override
public void control(LAccess type, double p1, double p2, double p3, double p4){
if(type == LAccess.color){
color = Tmp.c1.fromDouble(p1).rgba8888();
if(!headless) renderer.minimap.update(tile);
}
super.control(type, p1, p2, p3, p4);
@@ -80,11 +95,9 @@ public class LightBlock extends Block{
@Override
public void draw(){
super.draw();
Draw.blend(Blending.additive);
Draw.color(Tmp.c1.set(color), efficiency * 0.3f);
Draw.color(Tmp.c1.set(color).a(0.4f));
Draw.rect(topRegion, x, y);
Draw.color();
Draw.blend();
}
@Override

View File

@@ -328,6 +328,11 @@ public class PowerNode extends PowerBlock{
}
});
//uncomment for debugging connection translation issues in schematics
//Draw.color(Color.red);
//Lines.line(plan.drawx(), plan.drawy(), px * tilesize, py * tilesize);
//Draw.color();
if(otherReq == null || otherReq.block == null) continue;
drawLaser(plan.drawx(), plan.drawy(), otherReq.drawx(), otherReq.drawy(), size, otherReq.block.size);

View File

@@ -262,7 +262,7 @@ public class BeamDrill extends Block{
time %= drillTime;
}
if(timer(timerDump, dumpTime)){
if(timer(timerDump, dumpTime / timeScale)){
dump();
}
}

View File

@@ -80,7 +80,7 @@ public class BurstDrill extends Drill{
if(invertTime > 0f) invertTime -= delta() / invertedTime;
if(timer(timerDump, dumpTime)){
if(timer(timerDump, dumpTime / timeScale)){
dump(items.has(dominantItem) ? dominantItem : null);
}

View File

@@ -286,7 +286,7 @@ public class Drill extends Block{
@Override
public void updateTile(){
if(timer(timerDump, dumpTime)){
if(timer(timerDump, dumpTime / timeScale)){
dump(dominantItem != null && items.has(dominantItem) ? dominantItem : null);
}

View File

@@ -162,7 +162,7 @@ public class Separator extends Block{
}
}
if(timer(timerDump, dumpTime)){
if(timer(timerDump, dumpTime / timeScale)){
dump();
}
}

View File

@@ -216,7 +216,7 @@ public class WallCrafter extends Block{
totalTime += edelta() * warmup * (eff <= 0f ? 0f : 1f);
if(timer(timerDump, dumpTime)){
if(timer(timerDump, dumpTime / timeScale)){
dump(output);
}
}

View File

@@ -60,6 +60,7 @@ public class ConsumePayloadDynamic extends Consume{
var inv = build.getPayloads();
var pay = payloads.get(build);
table.clear();
table.table(c -> {
int i = 0;
for(var stack : pay){

View File

@@ -16,7 +16,7 @@ public class BuildVisibility{
sandboxOnly = new BuildVisibility(() -> Vars.state == null || Vars.state.rules.infiniteResources),
campaignOnly = new BuildVisibility(() -> Vars.state == null || Vars.state.isCampaign()),
legacyLaunchPadOnly = new BuildVisibility(() -> (Vars.state == null || Vars.state.isCampaign() && Vars.state.getPlanet().campaignRules.legacyLaunchPads) && Blocks.advancedLaunchPad != null && Blocks.advancedLaunchPad.unlocked()),
notLegacyLaunchPadOnly = new BuildVisibility(() -> (Vars.state == null || Vars.state.isCampaign() && !Vars.state.getPlanet().campaignRules.legacyLaunchPads)),
notLegacyLaunchPadOnly = new BuildVisibility(() -> (Vars.state == null || Vars.state.rules.infiniteResources || Vars.state.isCampaign() && !Vars.state.getPlanet().campaignRules.legacyLaunchPads)),
lightingOnly = new BuildVisibility(() -> Vars.state == null || Vars.state.rules.lighting || Vars.state.isCampaign()),
ammoOnly = new BuildVisibility(() -> Vars.state == null || Vars.state.rules.unitAmmo),
fogOnly = new BuildVisibility(() -> Vars.state == null || Vars.state.rules.fog || Vars.state.rules.editor);

View File

@@ -710,7 +710,7 @@ public class StatValues{
if(type.status != StatusEffects.none){
sep(bt, (type.status.hasEmoji() ? type.status.emoji() : "") + "[stat]" + type.status.localizedName + (type.status.reactive ? "" : "[lightgray] ~ [stat]" +
((int)(type.statusDuration / 60f)) + "[lightgray] " + Core.bundle.get("unit.seconds"))).with(c -> withTooltip(c, type.status));
Strings.autoFixed(type.statusDuration / 60f, 1) + "[lightgray] " + Core.bundle.get("unit.seconds"))).with(c -> withTooltip(c, type.status));
}
if(!type.targetMissiles){