Merge remote-tracking branch 'upstream/master' into unit-stats

This commit is contained in:
Leonwang4234
2020-11-09 21:52:42 -08:00
244 changed files with 467 additions and 367 deletions

View File

@@ -67,7 +67,7 @@ public class Vars implements Loadable{
/** URL of the github issue report template.*/
public static final String reportIssueURL = "https://github.com/Anuken/Mindustry/issues/new?labels=bug&template=bug_report.md";
/** list of built-in servers.*/
public static final Seq<String> defaultServers = Seq.with();
public static final Seq<ServerGroup> defaultServers = Seq.with();
/** maximum distance between mine and core that supports automatic transferring */
public static final float mineTransferRange = 220f;
/** max chat message length */

View File

@@ -445,13 +445,12 @@ public class Pathfinder implements Runnable{
public void getPositions(IntSeq out){
out.add(Point2.pack(World.toTile(position.getX()), World.toTile(position.getY())));
}
}
/**
* Data for a flow field to some set of destinations.
* Concrete subclasses must specify a way to fetch costs and destinations.
* */
*/
public static abstract class Flowfield{
/** Refresh rate in milliseconds. Return any number <= 0 to disable. */
protected int refreshRate;

View File

@@ -17,10 +17,8 @@ import arc.struct.*;
* @author davebaol
*/
public class Formation{
/** A list of slots assignments. */
public Seq<SlotAssignment> slotAssignments;
/** The anchor point of this formation. */
public Vec3 anchor;
/** The formation pattern */
@@ -138,7 +136,6 @@ public class Formation{
* @return {@code false} if no more slots are available; {@code true} otherwise.
*/
public boolean addMember(FormationMember member){
// Check if the pattern supports one more slot
if(pattern.supportsSlots(slotAssignments.size + 1)){
// Add a new slot assignment

View File

@@ -16,8 +16,9 @@ public class FreeSlotAssignmentStrategy implements SlotAssignmentStrategy{
public void updateSlotAssignments(Seq<SlotAssignment> assignments){
// A very simple assignment algorithm: we simply go through
// each assignment in the list and assign sequential slot numbers
for(int i = 0; i < assignments.size; i++)
for(int i = 0; i < assignments.size; i++){
assignments.get(i).slotNumber = i;
}
}
@Override

View File

@@ -51,7 +51,6 @@ public class SoftRoleSlotAssignmentStrategy extends BoundedSlotAssignmentStrateg
@Override
public void updateSlotAssignments(Seq<SlotAssignment> assignments){
// Holds a list of member and slot data for each member.
Seq<MemberAndSlots> memberData = new Seq<>();
@@ -125,7 +124,6 @@ public class SoftRoleSlotAssignmentStrategy extends BoundedSlotAssignmentStrateg
// Some sensible action should be taken, such as reporting to the player.
throw new ArcRuntimeException("SoftRoleSlotAssignmentStrategy cannot find valid slot assignment for member " + memberDatum.member);
}
}
static class CostAndSlot implements Comparable<CostAndSlot>{

View File

@@ -71,7 +71,7 @@ public class BuilderAI extends AIController{
Units.nearby(unit.team, unit.x, unit.y, buildRadius, u -> {
if(found) return;
if(u instanceof Builderc b && u != unit && ((Builderc)u).activelyBuilding()){
if(u instanceof Builderc b && u != unit && b.activelyBuilding()){
BuildPlan plan = b.buildPlan();
Building build = world.build(plan.x, plan.y);
@@ -119,7 +119,7 @@ public class BuilderAI extends AIController{
public boolean useFallback(){
return state.rules.waves && unit.team == state.rules.waveTeam && !unit.team.rules().ai;
}
@Override
public boolean shouldShoot(){
return !((Builderc)unit).isBuilding();

View File

@@ -2,17 +2,13 @@ package mindustry.ai.types;
import arc.math.*;
import arc.math.geom.*;
import arc.struct.*;
import arc.util.*;
import mindustry.ai.formations.*;
import mindustry.entities.units.*;
import mindustry.gen.*;
import mindustry.type.*;
import mindustry.world.*;
import mindustry.world.blocks.storage.CoreBlock.*;
public class FormationAI extends AIController implements FormationMember{
private static Seq<Tile> tiles = new Seq<>();
public Unit leader;
private Vec3 target = new Vec3();
@@ -30,9 +26,8 @@ public class FormationAI extends AIController implements FormationMember{
@Override
public void updateUnit(){
UnitType type = unit.type;
if(leader.dead){
if(leader == null || leader.dead){
unit.resetController();
return;
}

View File

@@ -104,9 +104,7 @@ public class LogicAI extends AIController{
//look where moving if there's nothing to aim at
if(!shoot){
if(unit.moving()){
unit.lookAt(unit.vel().angle());
}
unit.lookAt(unit.prefRotation());
}else if(unit.hasWeapons()){ //if there is, look at the object
unit.lookAt(unit.mounts[0].aimX, unit.mounts[0].aimY);
}

View File

@@ -79,5 +79,4 @@ public class MinerAI extends AIController{
@Override
protected void updateTargeting(){
}
}

View File

@@ -36,12 +36,11 @@ public class RepairAI extends AIController{
Building target = Units.findDamagedTile(unit.team, unit.x, unit.y);
if(target instanceof ConstructBuild) target = null;
if(target == null){
super.updateTargeting();
}else{
this.target = target;
}
}
}

View File

@@ -31,7 +31,7 @@ public class SuicideAI extends GroundAI{
if(!Units.invalidateTarget(target, unit, unit.range()) && unit.hasWeapons()){
rotate = true;
shoot = unit.within(target, unit.type.weapons.first().bullet.range() +
(target instanceof Building ? ((Building)target).block.size * Vars.tilesize / 2f : ((Hitboxc)target).hitSize() / 2f));
(target instanceof Building b ? b.block.size * Vars.tilesize / 2f : ((Hitboxc)target).hitSize() / 2f));
if(unit.type.hasWeapons()){
unit.aimLook(Predict.intercept(unit, target, unit.type.weapons.first().bullet.speed));
@@ -68,7 +68,6 @@ public class SuicideAI extends GroundAI{
unit.moveAt(vec.set(target).sub(unit).limit(unit.speed()));
}
}
}
if(!moveToTarget){

View File

@@ -41,7 +41,7 @@ public class LoopControl{
data.soundID = -1;
return;
}
sound.setPan(data.soundID, pan, data.curVolume);
sound.set(data.soundID, pan, data.curVolume);
}
data.volume = 0f;

View File

@@ -6,6 +6,7 @@ import arc.audio.SoloudAudio.*;
import arc.math.*;
import arc.struct.*;
import arc.util.*;
import mindustry.content.*;
import mindustry.game.EventType.*;
import mindustry.gen.*;
@@ -13,12 +14,14 @@ import static mindustry.Vars.*;
/** Controls playback of multiple music tracks.*/
public class MusicControl{
protected static final float finTime = 120f, foutTime = 120f, musicInterval = 60 * 60 * 3f, musicChance = 0.6f, musicWaveChance = 0.5f;
protected static final float finTime = 120f, foutTime = 120f, musicInterval = 60 * 60 * 3f, musicChance = 0.6f, musicWaveChance = 0.46f;
/** normal, ambient music, plays at any time */
public Seq<Music> ambientMusic = Seq.with();
/** darker music, used in times of conflict */
public Seq<Music> darkMusic = Seq.with();
/** music used explicitly after boss spawns */
public Seq<Music> bossMusic = Seq.with();
protected Music lastRandomPlayed;
protected Interval timer = new Interval();
@@ -35,8 +38,12 @@ public class MusicControl{
Events.on(ClientLoadEvent.class, e -> reload());
//only run music 10 seconds after a wave spawns
Events.on(WaveEvent.class, e -> Time.run(60f * 10f, () -> {
if(Mathf.chance(musicWaveChance)){
Events.on(WaveEvent.class, e -> Time.run(Mathf.random(8f, 15f) * 60f, () -> {
boolean boss = state.rules.spawns.contains(group -> group.getSpawned(state.wave - 2) > 0 && group.effect == StatusEffects.boss);
if(boss){
playOnce(bossMusic.random(lastRandomPlayed));
}else if(Mathf.chance(musicWaveChance)){
playRandom();
}
}));
@@ -45,8 +52,9 @@ public class MusicControl{
protected void reload(){
current = null;
fade = 0f;
ambientMusic = Seq.with(Musics.game1, Musics.game3, Musics.game4, Musics.game6);
darkMusic = Seq.with(Musics.game2, Musics.game5, Musics.game7);
ambientMusic = Seq.with(Musics.game1, Musics.game3, Musics.game6, Musics.game8, Musics.game9);
darkMusic = Seq.with(Musics.game2, Musics.game5, Musics.game7, Musics.game4);
bossMusic = Seq.with(Musics.boss1, Musics.boss2, Musics.game2, Musics.game5);
}
public void stop(){

View File

@@ -23,7 +23,6 @@ public class SoundLoop{
if(id < 0){
if(play){
id = sound.loop(sound.calcVolume(x, y) * volume * baseVolume, 1f, sound.calcPan(x, y));
Log.info("playing, id = @", id);
}
}else{
//fade the sound in or out
@@ -38,7 +37,7 @@ public class SoundLoop{
}
}
sound.setPan(id, sound.calcPan(x, y), sound.calcVolume(x, y) * volume * baseVolume);
sound.set(id, sound.calcPan(x, y), sound.calcVolume(x, y) * volume * baseVolume);
}
}

View File

@@ -389,7 +389,6 @@ public class Fx{
float ang = Mathf.angle(x, y);
lineAngle(e.x + x, e.y + y, ang, e.fout() * 3 + 1f);
});
}),
hitBulletBig = new Effect(13, e -> {
@@ -400,7 +399,6 @@ public class Fx{
float ang = Mathf.angle(x, y);
lineAngle(e.x + x, e.y + y, ang, e.fout() * 4 + 1.5f);
});
}),
hitFlameSmall = new Effect(14, e -> {
@@ -411,7 +409,6 @@ public class Fx{
float ang = Mathf.angle(x, y);
lineAngle(e.x + x, e.y + y, ang, e.fout() * 3 + 1f);
});
}),
hitLiquid = new Effect(16, e -> {
@@ -420,7 +417,6 @@ public class Fx{
randLenVectors(e.id, 5, e.fin() * 15f, e.rotation, 60f, (x, y) -> {
Fill.circle(e.x + x, e.y + y, e.fout() * 2f);
});
}),
hitLancer = new Effect(12, e -> {
@@ -431,7 +427,6 @@ public class Fx{
float ang = Mathf.angle(x, y);
lineAngle(e.x + x, e.y + y, ang, e.fout() * 4 + 1f);
});
}),
hitMeltdown = new Effect(12, e -> {
@@ -442,7 +437,6 @@ public class Fx{
float ang = Mathf.angle(x, y);
lineAngle(e.x + x, e.y + y, ang, e.fout() * 4 + 1f);
});
}),
hitMeltHeal = new Effect(12, e -> {
@@ -453,7 +447,6 @@ public class Fx{
float ang = Mathf.angle(x, y);
lineAngle(e.x + x, e.y + y, ang, e.fout() * 4 + 1f);
});
}),
instBomb = new Effect(15f, 100f, e -> {
@@ -553,8 +546,8 @@ public class Fx{
}),
flakExplosion = new Effect(20, e -> {
color(Pal.bulletYellow);
e.scaled(6, i -> {
stroke(3f * i.fout());
Lines.circle(e.x, e.y, 3f + i.fin() * 10f);
@@ -572,12 +565,11 @@ public class Fx{
randLenVectors(e.id + 1, 4, 1f + 23f * e.finpow(), (x, y) -> {
lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + e.fout() * 3f);
});
}),
plasticExplosion = new Effect(24, e -> {
color(Pal.plastaniumFront);
e.scaled(7, i -> {
stroke(3f * i.fout());
Lines.circle(e.x, e.y, 3f + i.fin() * 24f);
@@ -595,12 +587,11 @@ public class Fx{
randLenVectors(e.id + 1, 4, 1f + 25f * e.finpow(), (x, y) -> {
lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + e.fout() * 3f);
});
}),
plasticExplosionFlak = new Effect(28, e -> {
color(Pal.plastaniumFront);
e.scaled(7, i -> {
stroke(3f * i.fout());
Lines.circle(e.x, e.y, 3f + i.fin() * 34f);
@@ -618,12 +609,11 @@ public class Fx{
randLenVectors(e.id + 1, 4, 1f + 30f * e.finpow(), (x, y) -> {
lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + e.fout() * 3f);
});
}),
blastExplosion = new Effect(22, e -> {
color(Pal.missileYellow);
e.scaled(6, i -> {
stroke(3f * i.fout());
Lines.circle(e.x, e.y, 3f + i.fin() * 15f);
@@ -641,12 +631,11 @@ public class Fx{
randLenVectors(e.id + 1, 4, 1f + 23f * e.finpow(), (x, y) -> {
lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + e.fout() * 3f);
});
}),
sapExplosion = new Effect(25, e -> {
color(Pal.sapBullet);
e.scaled(6, i -> {
stroke(3f * i.fout());
Lines.circle(e.x, e.y, 3f + i.fin() * 80f);
@@ -664,12 +653,11 @@ public class Fx{
randLenVectors(e.id + 1, 8, 1f + 60f * e.finpow(), (x, y) -> {
lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + e.fout() * 3f);
});
}),
massiveExplosion = new Effect(30, e -> {
color(Pal.missileYellow);
e.scaled(7, i -> {
stroke(3f * i.fout());
Lines.circle(e.x, e.y, 4f + i.fin() * 30f);
@@ -687,7 +675,6 @@ public class Fx{
randLenVectors(e.id + 1, 6, 1f + 29f * e.finpow(), (x, y) -> {
lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + e.fout() * 4f);
});
}),
artilleryTrail = new Effect(50, e -> {
@@ -712,8 +699,8 @@ public class Fx{
}),
flakExplosionBig = new Effect(30, e -> {
color(Pal.bulletYellowBack);
e.scaled(6, i -> {
stroke(3f * i.fout());
Lines.circle(e.x, e.y, 3f + i.fin() * 25f);
@@ -731,7 +718,6 @@ public class Fx{
randLenVectors(e.id + 1, 4, 1f + 23f * e.finpow(), (x, y) -> {
lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + e.fout() * 3f);
});
}),
burning = new Effect(35f, e -> {
@@ -740,7 +726,6 @@ public class Fx{
randLenVectors(e.id, 3, 2f + e.fin() * 7f, (x, y) -> {
Fill.circle(e.x + x, e.y + y, 0.1f + e.fout() * 1.4f);
});
}),
fire = new Effect(50f, e -> {
@@ -761,7 +746,6 @@ public class Fx{
randLenVectors(e.id, 1, 2f + e.fin() * 7f, (x, y) -> {
Fill.circle(e.x + x, e.y + y, 0.2f + e.fslope() * 1.5f);
});
}),
steam = new Effect(35f, e -> {
@@ -770,7 +754,6 @@ public class Fx{
randLenVectors(e.id, 2, 2f + e.fin() * 7f, (x, y) -> {
Fill.circle(e.x + x, e.y + y, 0.2f + e.fslope() * 1.5f);
});
}),
fireballsmoke = new Effect(25f, e -> {
@@ -779,7 +762,6 @@ public class Fx{
randLenVectors(e.id, 1, 2f + e.fin() * 7f, (x, y) -> {
Fill.circle(e.x + x, e.y + y, 0.2f + e.fout() * 1.5f);
});
}),
ballfire = new Effect(25f, e -> {
@@ -788,7 +770,6 @@ public class Fx{
randLenVectors(e.id, 2, 2f + e.fin() * 7f, (x, y) -> {
Fill.circle(e.x + x, e.y + y, 0.2f + e.fout() * 1.5f);
});
}),
freezing = new Effect(40f, e -> {
@@ -797,7 +778,6 @@ public class Fx{
randLenVectors(e.id, 2, 1f + e.fin() * 2f, (x, y) -> {
Fill.circle(e.x + x, e.y + y, e.fout() * 1.2f);
});
}),
melting = new Effect(40f, e -> {
@@ -806,7 +786,6 @@ public class Fx{
randLenVectors(e.id, 2, 1f + e.fin() * 3f, (x, y) -> {
Fill.circle(e.x + x, e.y + y, .2f + e.fout() * 1.2f);
});
}),
wet = new Effect(80f, e -> {
@@ -815,7 +794,7 @@ public class Fx{
Fill.circle(e.x, e.y, e.fout() * 1f);
}),
muddy = new Effect(80f, e -> {
color(Color.valueOf("432722"));
alpha(Mathf.clamp(e.fin() * 2f));
@@ -829,7 +808,6 @@ public class Fx{
randLenVectors(e.id, 2, 1f + e.fin() * 2f, (x, y) -> {
Fill.square(e.x + x, e.y + y, e.fslope() * 1.1f, 45f);
});
}),
sporeSlowed = new Effect(40f, e -> {
@@ -844,7 +822,6 @@ public class Fx{
randLenVectors(e.id, 2, 1f + e.fin() * 2f, (x, y) -> {
Fill.circle(e.x + x, e.y + y, e.fout() * 1f);
});
}),
overdriven = new Effect(20f, e -> {
@@ -853,7 +830,6 @@ public class Fx{
randLenVectors(e.id, 2, 1f + e.fin() * 2f, (x, y) -> {
Fill.square(e.x + x, e.y + y, e.fout() * 2.3f + 0.5f);
});
}),
overclocked = new Effect(50f, e -> {
@@ -962,7 +938,6 @@ public class Fx{
randLenVectors(e.id + 1, 9, 1f + 23f * e.finpow(), (x, y) -> {
lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + e.fout() * 3f);
});
}),
blockExplosionSmoke = new Effect(30, e -> {
@@ -972,7 +947,6 @@ public class Fx{
Fill.circle(e.x + x, e.y + y, e.fout() * 3f);
Fill.circle(e.x + x / 2f, e.y + y / 2f, e.fout() * 1f);
});
}),
shootSmall = new Effect(8, e -> {
@@ -1002,7 +976,6 @@ public class Fx{
randLenVectors(e.id, 5, e.finpow() * 6f, e.rotation, 20f, (x, y) -> {
Fill.circle(e.x + x, e.y + y, e.fout() * 1.5f);
});
}),
shootBig = new Effect(9, e -> {
@@ -1025,7 +998,6 @@ public class Fx{
randLenVectors(e.id, 8, e.finpow() * 19f, e.rotation, 10f, (x, y) -> {
Fill.circle(e.x + x, e.y + y, e.fout() * 2f + 0.2f);
});
}),
shootBigSmoke2 = new Effect(18f, e -> {
@@ -1034,7 +1006,6 @@ public class Fx{
randLenVectors(e.id, 9, e.finpow() * 23f, e.rotation, 20f, (x, y) -> {
Fill.circle(e.x + x, e.y + y, e.fout() * 2.4f + 0.2f);
});
}),
shootSmallFlame = new Effect(32f, 80f, e -> {
@@ -1043,7 +1014,6 @@ public class Fx{
randLenVectors(e.id, 8, e.finpow() * 60f, e.rotation, 10f, (x, y) -> {
Fill.circle(e.x + x, e.y + y, 0.65f + e.fout() * 1.5f);
});
}),
shootPyraFlame = new Effect(33f, 80f, e -> {
@@ -1052,7 +1022,6 @@ public class Fx{
randLenVectors(e.id, 10, e.finpow() * 70f, e.rotation, 10f, (x, y) -> {
Fill.circle(e.x + x, e.y + y, 0.65f + e.fout() * 1.6f);
});
}),
shootLiquid = new Effect(40f, 80f, e -> {
@@ -1061,7 +1030,6 @@ public class Fx{
randLenVectors(e.id, 6, e.finpow() * 60f, e.rotation, 11f, (x, y) -> {
Fill.circle(e.x + x, e.y + y, 0.5f + e.fout() * 2.5f);
});
}),
casing1 = new Effect(30f, e -> {
@@ -1197,7 +1165,6 @@ public class Fx{
for(int i : Mathf.signs){
Drawf.tri(e.x, e.y, 4f * e.fout(), 29f, e.rotation + 90f * i);
}
}),
lancerLaserShootSmoke = new Effect(26f, e -> {
@@ -1207,7 +1174,6 @@ public class Fx{
randLenVectors(e.id, 7, length, e.rotation, 0f, (x, y) -> {
lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), e.fout() * 9f);
});
}),
lancerLaserCharge = new Effect(38f, e -> {
@@ -1216,7 +1182,6 @@ public class Fx{
randLenVectors(e.id, 2, 1f + 20f * e.fout(), e.rotation, 120f, (x, y) -> {
lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), e.fslope() * 3f + 1f);
});
}),
lancerLaserChargeBegin = new Effect(60f, e -> {
@@ -1233,7 +1198,6 @@ public class Fx{
randLenVectors(e.id, 2, 1f + 20f * e.fout(), e.rotation, 120f, (x, y) -> {
Drawf.tri(e.x + x, e.y + y, e.fslope() * 3f + 1, e.fslope() * 3f + 1, Mathf.angle(x, y));
});
}),
sparkShoot = new Effect(12f, e -> {
@@ -1243,7 +1207,6 @@ public class Fx{
randLenVectors(e.id, 7, 25f * e.finpow(), e.rotation, 3f, (x, y) -> {
lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), e.fslope() * 5f + 0.5f);
});
}),
lightningShoot = new Effect(12f, e -> {
@@ -1372,21 +1335,21 @@ public class Fx{
Fill.square(e.x + x, e.y + y, e.fout() * 2.5f + 0.5f, 45);
});
}),
pulverizeSmall = new Effect(30, e -> {
randLenVectors(e.id, 3, e.fin() * 5f, (x, y) -> {
color(Pal.stoneGray);
Fill.square(e.x + x, e.y + y, e.fout() * 1f + 0.5f, 45);
});
}),
pulverizeMedium = new Effect(30, e -> {
randLenVectors(e.id, 5, 3f + e.fin() * 8f, (x, y) -> {
color(Pal.stoneGray);
Fill.square(e.x + x, e.y + y, e.fout() * 1f + 0.5f, 45);
});
}),
producesmoke = new Effect(12, e -> {
randLenVectors(e.id, 8, 4f + e.fin() * 18f, (x, y) -> {
color(Color.white, Pal.accent, e.fin());
@@ -1401,21 +1364,21 @@ public class Fx{
Fill.circle(e.x + x, e.y + y, 0.5f + fout * 4f);
});
}),
smeltsmoke = new Effect(15, e -> {
randLenVectors(e.id, 6, 4f + e.fin() * 5f, (x, y) -> {
color(Color.white, e.color, e.fin());
Fill.square(e.x + x, e.y + y, 0.5f + e.fout() * 2f, 45);
});
}),
formsmoke = new Effect(40, e -> {
randLenVectors(e.id, 6, 5f + e.fin() * 8f, (x, y) -> {
color(Pal.plasticSmoke, Color.lightGray, e.fin());
Fill.square(e.x + x, e.y + y, 0.2f + e.fout() * 2f, 45);
});
}),
blastsmoke = new Effect(26, e -> {
randLenVectors(e.id, 12, 1f + e.fin() * 23f, (x, y) -> {
float size = 2f + e.fout() * 6f;
@@ -1423,7 +1386,7 @@ public class Fx{
Fill.circle(e.x + x, e.y + y, size/2f);
});
}),
lava = new Effect(18, e -> {
randLenVectors(e.id, 3, 1f + e.fin() * 10f, (x, y) -> {
float size = e.fslope() * 4f;
@@ -1431,50 +1394,58 @@ public class Fx{
Fill.circle(e.x + x, e.y + y, size/2f);
});
}),
dooropen = new Effect(10, e -> {
stroke(e.fout() * 1.6f);
Lines.square(e.x, e.y, tilesize / 2f + e.fin() * 2f);
}),
doorclose = new Effect(10, e -> {
stroke(e.fout() * 1.6f);
Lines.square(e.x, e.y, tilesize / 2f + e.fout() * 2f);
}),
dooropenlarge = new Effect(10, e -> {
stroke(e.fout() * 1.6f);
Lines.square(e.x, e.y, tilesize + e.fin() * 2f);
}),
doorcloselarge = new Effect(10, e -> {
stroke(e.fout() * 1.6f);
Lines.square(e.x, e.y, tilesize + e.fout() * 2f);
}),
purify = new Effect(10, e -> {
color(Color.royal, Color.gray, e.fin());
stroke(2f);
Lines.spikes(e.x, e.y, e.fin() * 4f, 2, 6);
}),
purifyoil = new Effect(10, e -> {
color(Color.black, Color.gray, e.fin());
stroke(2f);
Lines.spikes(e.x, e.y, e.fin() * 4f, 2, 6);
}),
purifystone = new Effect(10, e -> {
color(Color.orange, Color.gray, e.fin());
stroke(2f);
Lines.spikes(e.x, e.y, e.fin() * 4f, 2, 6);
}),
generate = new Effect(11, e -> {
color(Color.orange, Color.yellow, e.fin());
stroke(1f);
Lines.spikes(e.x, e.y, e.fin() * 5f, 2, 8);
}),
mine = new Effect(20, e -> {
randLenVectors(e.id, 6, 3f + e.fin() * 6f, (x, y) -> {
color(e.color, Color.lightGray, e.fin());
Fill.square(e.x + x, e.y + y, e.fout() * 2f, 45);
});
}),
mineBig = new Effect(30, e -> {
randLenVectors(e.id, 6, 4f + e.fin() * 8f, (x, y) -> {
color(e.color, Color.lightGray, e.fin());
@@ -1488,12 +1459,14 @@ public class Fx{
Fill.square(e.x + x, e.y + y, e.fout() * 2f + 0.5f, 45);
});
}),
smelt = new Effect(20, e -> {
randLenVectors(e.id, 6, 2f + e.fin() * 5f, (x, y) -> {
color(Color.white, e.color, e.fin());
Fill.square(e.x + x, e.y + y, 0.5f + e.fout() * 2f, 45);
});
}),
teleportActivate = new Effect(50, e -> {
color(e.color);
@@ -1507,8 +1480,8 @@ public class Fx{
randLenVectors(e.id, 30, 4f + 40f * e.fin(), (x, y) -> {
lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), e.fin() * 4f + 1f);
});
}),
teleport = new Effect(60, e -> {
color(e.color);
stroke(e.fin() * 2f);
@@ -1517,8 +1490,8 @@ public class Fx{
randLenVectors(e.id, 20, 6f + 20f * e.fout(), (x, y) -> {
lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), e.fin() * 4f + 1f);
});
}),
teleportOut = new Effect(20, e -> {
color(e.color);
stroke(e.fout() * 2f);
@@ -1527,7 +1500,6 @@ public class Fx{
randLenVectors(e.id, 20, 4f + 20f * e.fin(), (x, y) -> {
lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), e.fslope() * 4f + 1f);
});
}),
ripple = new Effect(30, e -> {
@@ -1611,7 +1583,6 @@ public class Fx{
float radius = unit.hitSize() * 1.3f;
e.scaled(16f, c -> {
color(Pal.shield);
stroke(c.fout() * 2f + 0.1f);

View File

@@ -21,7 +21,7 @@ public class UnitTypes implements ContentList{
public static @EntityDef({Unitc.class, Mechc.class}) UnitType mace, dagger, crawler, fortress, scepter, reign;
//mech + builder + miner
public static @EntityDef({Unitc.class, Mechc.class, Builderc.class, Minerc.class}) UnitType nova, pulsar, quasar;
public static @EntityDef({Unitc.class, Mechc.class, Builderc.class}) UnitType nova, pulsar, quasar;
//mech
public static @EntityDef({Unitc.class, Mechc.class}) UnitType vela;
@@ -35,23 +35,23 @@ public class UnitTypes implements ContentList{
//air (no special traits)
public static @EntityDef({Unitc.class}) UnitType flare, eclipse, horizon, zenith, antumbra;
//air + mining
public static @EntityDef({Unitc.class, Minerc.class}) UnitType mono;
//air, legacy mining
public static @EntityDef(value = {Unitc.class}, legacy = true) UnitType mono;
//air + building + mining
public static @EntityDef({Unitc.class, Builderc.class, Minerc.class}) UnitType poly;
public static @EntityDef({Unitc.class, Builderc.class}) UnitType poly;
//air + building + mining + payload
public static @EntityDef({Unitc.class, Builderc.class, Minerc.class, Payloadc.class}) UnitType mega;
public static @EntityDef({Unitc.class, Builderc.class, Payloadc.class}) UnitType mega;
//air + building + payload
public static @EntityDef({Unitc.class, Builderc.class, Payloadc.class}) UnitType quad;
public static @EntityDef(value = {Unitc.class, Builderc.class, Payloadc.class}, legacy = true) UnitType quad;
//air + building + payload
public static @EntityDef({Unitc.class, Builderc.class, Payloadc.class, AmmoDistributec.class}) UnitType oct;
//air + building + mining
public static @EntityDef({Unitc.class, Builderc.class, Minerc.class}) UnitType alpha, beta, gamma;
public static @EntityDef({Unitc.class, Builderc.class}) UnitType alpha, beta, gamma;
//water
public static @EntityDef({Unitc.class, WaterMovec.class}) UnitType risso, minke, bryde, sei, omura;
@@ -928,7 +928,7 @@ public class UnitTypes implements ContentList{
smokeEffect = Fx.shootSmallSmoke;
ammoMultiplier = 2;
}};
shootSound = Sounds.shoot;
shootSound = Sounds.pew;
}});
}};
@@ -1216,7 +1216,7 @@ public class UnitTypes implements ContentList{
reload = 30f;
ejectEffect = Fx.none;
recoil = 2f;
shootSound = Sounds.pew;
shootSound = Sounds.missile;
shots = 1;
velocityRnd = 0.5f;
inaccuracy = 15f;
@@ -1232,6 +1232,7 @@ public class UnitTypes implements ContentList{
smokeEffect = Fx.hitLaser;
hitEffect = despawnEffect = Fx.hitLaser;
frontColor = Color.white;
hitSound = Sounds.none;
healPercent = 5.5f;
collidesTeam = true;

View File

@@ -160,8 +160,8 @@ public class ContentLoader{
public void removeLast(){
if(lastAdded != null && contentMap[lastAdded.getContentType().ordinal()].peek() == lastAdded){
contentMap[lastAdded.getContentType().ordinal()].pop();
if(lastAdded instanceof MappableContent){
contentNameMap[lastAdded.getContentType().ordinal()].remove(((MappableContent)lastAdded).name);
if(lastAdded instanceof MappableContent c){
contentNameMap[lastAdded.getContentType().ordinal()].remove(c.name);
}
}
}

View File

@@ -12,6 +12,7 @@ import arc.util.*;
import mindustry.audio.*;
import mindustry.content.*;
import mindustry.core.GameState.*;
import mindustry.ctype.*;
import mindustry.entities.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
@@ -290,7 +291,7 @@ public class Control implements ApplicationListener, Loadable{
//reset win wave??
state.rules.winWave = state.rules.attackMode ? -1 : sector.preset != null ? sector.preset.captureWave : 40;
//kill all units, since they should be dead anwyay
//kill all units, since they should be dead anyway
Groups.unit.clear();
Groups.fire.clear();
@@ -400,8 +401,8 @@ public class Control implements ApplicationListener, Loadable{
try{
SaveIO.save(control.saves.getCurrent().file);
Log.info("Saved on exit.");
}catch(Throwable e){
e.printStackTrace();
}catch(Throwable t){
Log.err(t);
}
}

View File

@@ -326,5 +326,4 @@ public class Logic implements ApplicationListener{
public boolean isWaitingWave(){
return (state.rules.waitEnemies || (state.wave >= state.rules.winWave && state.rules.winWave > 0)) && state.enemies > 0;
}
}

View File

@@ -32,7 +32,7 @@ import static mindustry.Vars.*;
public class NetClient implements ApplicationListener{
private static final float dataTimeout = 60 * 18;
private static final float playerSyncTime = 2;
public final static float viewScale = 2f;
public static final float viewScale = 2f;
private long ping;
private Interval timer = new Interval(5);
@@ -234,7 +234,7 @@ public class NetClient implements ApplicationListener{
ui.join.connect(ip, port);
}
@Remote(targets = Loc.client)
public static void ping(Player player, long time){
Call.pingResponse(player.con, time);
@@ -439,7 +439,7 @@ public class NetClient implements ApplicationListener{
tile.build.readAll(Reads.get(input), tile.build.version());
}
}catch(Exception e){
e.printStackTrace();
Log.err(e);
}
}
@@ -577,8 +577,8 @@ public class NetClient implements ApplicationListener{
//prevent buffer overflow by checking config length
for(int i = 0; i < usedRequests; i++){
BuildPlan plan = player.builder().plans().get(i);
if(plan.config instanceof byte[]){
int length = ((byte[])plan.config).length;
if(plan.config instanceof byte[] b){
int length = b.length;
totalLength += length;
}
@@ -604,7 +604,7 @@ public class NetClient implements ApplicationListener{
unit.x, unit.y,
player.unit().aimX(), player.unit().aimY(),
unit.rotation,
unit instanceof Mechc ? ((Mechc)unit).baseRotation() : 0,
unit instanceof Mechc m ? m.baseRotation() : 0,
unit.vel.x, unit.vel.y,
player.miner().mineTile(),
player.boosting, player.shooting, ui.chatfrag.shown(), control.input.isBuilding,

View File

@@ -164,7 +164,7 @@ public class NetServer implements ApplicationListener{
info.id = packet.uuid;
admins.save();
Call.infoMessage(con, "You are not whitelisted here.");
Log.info("&lcDo &lywhitelist-add @&lc to whitelist the player &lb'@'", packet.uuid, packet.name);
info("&lcDo &lywhitelist-add @&lc to whitelist the player &lb'@'", packet.uuid, packet.name);
con.kick(KickReason.whitelist);
return;
}
@@ -226,8 +226,8 @@ public class NetServer implements ApplicationListener{
writeBuffer.reset();
player.write(outputBuffer);
}catch(Throwable t){
t.printStackTrace();
con.kick(KickReason.nameEmpty);
err(t);
return;
}
@@ -248,10 +248,10 @@ public class NetServer implements ApplicationListener{
try{
RemoteReadServer.readPacket(packet.reader(), packet.type, con.player);
}catch(ValidateException e){
Log.debug("Validation failed for '@': @", e.player, e.getMessage());
debug("Validation failed for '@': @", e.player, e.getMessage());
}catch(RuntimeException e){
if(e.getCause() instanceof ValidateException v){
Log.debug("Validation failed for '@': @", v.player, v.getMessage());
debug("Validation failed for '@': @", v.player, v.getMessage());
}else{
throw e;
}
@@ -305,7 +305,7 @@ public class NetServer implements ApplicationListener{
player.sendMessage("[scarlet]You must be admin to use this command.");
return;
}
Groups.player.each(Player::admin, a -> a.sendMessage(args[0], player, "[#" + Pal.adminChat.toString() + "]<A>" + NetClient.colorizeName(player.id, player.name)));
});
@@ -418,7 +418,7 @@ public class NetServer implements ApplicationListener{
VoteSession session = new VoteSession(currentlyKicking, found);
session.vote(player, 1);
vtime.reset();
vtime.reset();
currentlyKicking[0] = session;
}
}else{
@@ -493,7 +493,7 @@ public class NetServer implements ApplicationListener{
data.stream = new ByteArrayInputStream(stream.toByteArray());
player.con.sendStream(data);
Log.debug("Packed @ bytes of world data.", stream.size());
debug("Packed @ bytes of world data.", stream.size());
}
public void addPacketHandler(String type, Cons2<Player, String> handler){
@@ -505,7 +505,7 @@ public class NetServer implements ApplicationListener{
}
public static void onDisconnect(Player player, String reason){
//singleplayer multiplayer wierdness
//singleplayer multiplayer weirdness
if(player.con == null){
player.remove();
return;
@@ -519,7 +519,7 @@ public class NetServer implements ApplicationListener{
}
String message = Strings.format("&lb@&fi&lk has disconnected. &fi&lk[&lb@&fi&lk] (@)", player.name, player.uuid(), reason);
if(Config.showConnectMessages.bool()) Log.info(message);
if(Config.showConnectMessages.bool()) info(message);
}
player.remove();
@@ -539,7 +539,7 @@ public class NetServer implements ApplicationListener{
public static void serverPacketUnreliable(Player player, String type, String contents){
serverPacketReliable(player, type, contents);
}
private static boolean invalid(float f){
return Float.isInfinite(f) || Float.isNaN(f);
}
@@ -702,15 +702,14 @@ public class NetServer implements ApplicationListener{
@Remote(targets = Loc.client, called = Loc.server)
public static void adminRequest(Player player, Player other, AdminAction action){
if(!player.admin){
Log.warn("ACCESS DENIED: Player @ / @ attempted to perform admin action '@' on '@' without proper security access.",
warn("ACCESS DENIED: Player @ / @ attempted to perform admin action '@' on '@' without proper security access.",
player.name, player.con.address, action.name(), other == null ? null : other.name);
return;
}
if(other == null || ((other.admin && !player.isLocal()) && other != player)){
Log.warn("@ attempted to perform admin action on nonexistant or admin player.", player.name);
warn("@ attempted to perform admin action on nonexistant or admin player.", player.name);
return;
}
@@ -722,10 +721,10 @@ public class NetServer implements ApplicationListener{
netServer.admins.banPlayerIP(other.con.address);
netServer.admins.banPlayerID(other.con.uuid);
other.kick(KickReason.banned);
Log.info("&lc@ has banned @.", player.name, other.name);
info("&lc@ has banned @.", player.name, other.name);
}else if(action == AdminAction.kick){
other.kick(KickReason.kick);
Log.info("&lc@ has kicked @.", player.name, other.name);
info("&lc@ has kicked @.", player.name, other.name);
}else if(action == AdminAction.trace){
TraceInfo info = new TraceInfo(other.con.address, other.uuid(), other.con.modclient, other.con.mobile);
if(player.con != null){
@@ -733,7 +732,7 @@ public class NetServer implements ApplicationListener{
}else{
NetClient.traceInfo(other, info);
}
Log.info("&lc@ has requested trace info of @.", player.name, other.name);
info("&lc@ has requested trace info of @.", player.name, other.name);
}
}
@@ -748,7 +747,7 @@ public class NetServer implements ApplicationListener{
if(Config.showConnectMessages.bool()){
Call.sendMessage("[accent]" + player.name + "[accent] has connected.");
String message = Strings.format("&lb@&fi&lk has connected. &fi&lk[&lb@&fi&lk]", player.name, player.uuid());
Log.info(message);
info(message);
}
if(!Config.motd.string().equalsIgnoreCase("off")){
@@ -773,7 +772,6 @@ public class NetServer implements ApplicationListener{
@Override
public void update(){
if(!headless && !closing && net.server() && state.isMenu()){
closing = true;
ui.loadfrag.show("@server.closing");
@@ -799,7 +797,7 @@ public class NetServer implements ApplicationListener{
net.host(Config.port.num());
info("Opened a server on port @.", Config.port.num());
}catch(BindException e){
Log.err("Unable to host: Port already in use! Make sure no other servers are running on the same port in your network.");
err("Unable to host: Port already in use! Make sure no other servers are running on the same port in your network.");
state.set(State.menu);
}catch(IOException e){
err(e);
@@ -915,7 +913,6 @@ public class NetServer implements ApplicationListener{
}
String checkColor(String str){
for(int i = 1; i < str.length(); i++){
if(str.charAt(i) == ']'){
String color = str.substring(1, i);
@@ -941,7 +938,6 @@ public class NetServer implements ApplicationListener{
}
void sync(){
try{
Groups.player.each(p -> !p.isLocal(), player -> {
if(player.con == null || !player.con.isConnected()){
@@ -965,7 +961,7 @@ public class NetServer implements ApplicationListener{
}
}catch(IOException e){
e.printStackTrace();
Log.err(e);
}
}

View File

@@ -139,9 +139,9 @@ public class Renderer implements ApplicationListener{
}
bloom = new Bloom(true);
}catch(Throwable e){
e.printStackTrace();
settings.put("bloom", false);
ui.showErrorMessage("@error.bloom");
Log.err(e);
}
}
@@ -364,5 +364,4 @@ public class Renderer implements ApplicationListener{
buffer.dispose();
}
}

View File

@@ -104,7 +104,7 @@ public class UI implements ApplicationListener, Loadable{
Tooltips.getInstance().textProvider = text -> new Tooltip(t -> t.background(Styles.black5).margin(4f).add(text));
Core.settings.setErrorHandler(e -> {
e.printStackTrace();
Log.err(e);
Core.app.post(() -> showErrorMessage("Failed to access local storage.\nSettings will not be saved."));
});

View File

@@ -46,6 +46,10 @@ public class Version{
}
}
public static String buildString(){
return build < 0 ? "custom" : build + (revision == 0 ? "" : "." + revision);
}
/** get menu version without colors */
public static String combined(){
if(build == -1){

View File

@@ -445,7 +445,6 @@ public class World{
int err = dx - dy;
int e2;
while(true){
if(cons.accept(x0, y0)) return true;
if(x0 == x1 && y0 == y1) return false;

View File

@@ -126,7 +126,7 @@ public abstract class UnlockableContent extends MappableContent{
}
public boolean unlocked(){
if(net != null && net.client()) return state.rules.researched.contains(name);
if(net != null && net.client()) return alwaysUnlocked || state.rules.researched.contains(name);
return unlocked || alwaysUnlocked;
}

View File

@@ -404,7 +404,7 @@ public class MapGenerateDialog extends BaseDialog{
});
}catch(Exception e){
generating = false;
e.printStackTrace();
Log.err(e);
}
world.setGenerating(false);
});

View File

@@ -408,8 +408,7 @@ public class Damage{
}
@Struct
static
class PropCellStruct{
static class PropCellStruct{
byte x;
byte y;
short damage;

View File

@@ -115,7 +115,6 @@ public class EntityCollisions{
@SuppressWarnings("unchecked")
public <T extends Hitboxc> void updatePhysics(EntityGroup<T> group){
QuadTree tree = group.tree();
tree.clear();
@@ -141,7 +140,6 @@ public class EntityCollisions{
}
private void checkCollide(Hitboxc a, Hitboxc b){
a.hitbox(this.r1);
b.hitbox(this.r2);
@@ -218,7 +216,6 @@ public class EntityCollisions{
@SuppressWarnings("unchecked")
public <T extends Hitboxc> void collide(EntityGroup<T> groupa){
groupa.each(solid -> {
solid.hitbox(r1);
r1.x += (solid.lastX() - solid.getX());

View File

@@ -183,8 +183,7 @@ public class EntityGroup<T extends Entityc> implements Iterable<T>{
array.each(Entityc::remove);
array.clear();
if(map != null)
map.clear();
if(map != null) map.clear();
clearing = false;
}

View File

@@ -28,7 +28,6 @@ public class StatusFieldAbility extends Ability{
timer += Time.delta;
if(timer >= reload){
Units.nearby(unit.team, unit.x, unit.y, range, other -> {
other.apply(effect, duration);
});

View File

@@ -34,7 +34,6 @@ public class UnitSpawnAbility extends Ability{
timer += Time.delta;
if(timer >= spawnTime && Units.canCreate(unit.team, type)){
float x = unit.x + Angles.trnsx(unit.rotation, spawnY, spawnX), y = unit.y + Angles.trnsy(unit.rotation, spawnY, spawnX);
spawnEffect.at(x, y);
Unit u = type.create(unit.team);

View File

@@ -165,7 +165,7 @@ public abstract class BulletType extends Content{
if(makeFire && tile.team != b.team){
Fires.create(tile.tile);
}
if(healPercent > 0f && tile.team == b.team && !(tile.block instanceof ConstructBlock)){
Fx.healBlockFull.at(tile.x, tile.y, tile.block.size, Pal.heal);
tile.heal(healPercent / 100f * tile.maxHealth());
@@ -213,9 +213,9 @@ public abstract class BulletType extends Content{
if(status != StatusEffects.none){
Damage.status(b.team, x, y, splashDamageRadius, status, statusDuration, collidesAir, collidesGround);
}
if(healPercent > 0f){
indexer.eachBlock(b.team, x, y, splashDamageRadius, other -> other.damaged(), other -> {
indexer.eachBlock(b.team, x, y, splashDamageRadius, Building::damaged, other -> {
Fx.healBlockFull.at(other.x, other.y, other.block.size, Pal.heal);
other.heal(healPercent / 100f * other.maxHealth());
});
@@ -253,8 +253,8 @@ public abstract class BulletType extends Content{
public void init(Bullet b){
if(killShooter && b.owner() instanceof Healthc){
((Healthc)b.owner()).kill();
if(killShooter && b.owner() instanceof Healthc h){
h.kill();
}
if(instantDisappear){

View File

@@ -62,17 +62,15 @@ public class SapBulletType extends BulletType{
if(target != null){
float result = Math.min(target.health(), damage);
if(b.owner instanceof Healthc){
((Healthc)b.owner).heal(result * sapStrength);
if(b.owner instanceof Healthc h){
h.heal(result * sapStrength);
}
}
if(target instanceof Hitboxc hit){
hit.collision(b, hit.x(), hit.y());
b.collision(hit, hit.x(), hit.y());
}else if(target instanceof Building tile){
if(tile.collide(b)){
tile.collision(b);
hit(b, tile.x, tile.y);

View File

@@ -27,7 +27,7 @@ abstract class BuilderComp implements Unitc{
@Import float x, y, rotation;
@SyncLocal Queue<BuildPlan> plans = new Queue<>();
@SyncLocal Queue<BuildPlan> plans = new Queue<>(1);
@SyncLocal transient boolean updateBuilding = true;
@Override
@@ -35,7 +35,6 @@ abstract class BuilderComp implements Unitc{
if(!updateBuilding) return;
float finalPlaceDst = state.rules.infiniteResources ? Float.MAX_VALUE : buildingRange;
boolean infinite = state.rules.infiniteResources || team().rules().infiniteResources;
Iterator<BuildPlan> it = plans.iterator();
@@ -69,10 +68,6 @@ abstract class BuilderComp implements Unitc{
Tile tile = world.tile(current.x, current.y);
if(within(tile, finalPlaceDst)){
lookAt(angleTo(tile));
}
if(!(tile.block() instanceof ConstructBlock)){
if(!current.initialized && !current.breaking && Build.validPlace(current.block, team(), current.x, current.y, current.rotation)){
boolean hasAll = infinite || !Structs.contains(current.block.requirements, i -> core != null && !core.items.has(i.item));
@@ -188,6 +183,10 @@ abstract class BuilderComp implements Unitc{
}
boolean activelyBuilding(){
//not actively building when not near the build plan
if(isBuilding() && !within(buildPlan(), state.rules.infiniteResources ? Float.MAX_VALUE : buildingRange)){
return false;
}
return isBuilding() && updateBuilding;
}

View File

@@ -16,8 +16,8 @@ import mindustry.world.*;
import static mindustry.Vars.*;
@Component
abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
@Import float x, y, rotation;
abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc{
@Import float x, y, rotation, hitSize;
@Import UnitType type;
transient float mineTimer;
@@ -28,7 +28,7 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
}
public boolean offloadImmediately(){
return isPlayer();
return this.<Unit>self().isPlayer();
}
boolean mining(){
@@ -63,7 +63,6 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
mineTimer = 0f;
}else if(mining()){
Item item = mineTile.drop();
lookAt(angleTo(mineTile.worldx(), mineTile.worldy()));
mineTimer += Time.delta *type.mineSpeed;
if(Mathf.chance(0.06 * Time.delta)){
@@ -88,13 +87,17 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
mineTimer = 0f;
}
}
if(!headless){
loops.play(type.mineSound, this, type.mineSoundVolume);
}
}
}
@Override
public void draw(){
if(!mining()) return;
float focusLen = hitSize() / 2f + Mathf.absin(Time.time(), 1.1f, 0.5f);
float focusLen = hitSize / 2f + Mathf.absin(Time.time(), 1.1f, 0.5f);
float swingScl = 12f, swingMag = tilesize / 8f;
float flashScl = 0.3f;

View File

@@ -31,7 +31,7 @@ import mindustry.world.blocks.payloads.*;
import static mindustry.Vars.*;
@Component(base = true)
abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, Itemsc, Rotc, Unitc, Weaponsc, Drawc, Boundedc, Syncc, Shieldc, Commanderc, Displayable, Senseable, Ranged{
abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, Itemsc, Rotc, Unitc, Weaponsc, Drawc, Boundedc, Syncc, Shieldc, Commanderc, Displayable, Senseable, Ranged, Minerc{
@Import boolean hovering, dead;
@Import float x, y, rotation, elevation, maxHealth, drag, armor, hitSize, health, ammo, minFormationSpeed;
@@ -84,6 +84,18 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
controlling().each(cons);
}
/** @return where the unit wants to look at. */
public float prefRotation(){
if(this instanceof Builderc builder && builder.activelyBuilding()){
return angleTo(builder.buildPlan());
}else if(mineTile() != null){
return angleTo(mineTile());
}else if(moving()){
return vel().angle();
}
return rotation;
}
@Override
public float range(){
return type.range;

View File

@@ -61,13 +61,10 @@ public class AIController implements UnitController{
}
protected void updateVisuals(){
if(unit.isFlying()){
unit.wobble();
if(unit.moving()){
unit.lookAt(unit.vel.angle());
}
unit.lookAt(unit.prefRotation());
}
}

View File

@@ -9,7 +9,7 @@ import mindustry.world.*;
import static mindustry.Vars.*;
/** Class for storing build requests. Can be either a place or remove request. */
public class BuildPlan{
public class BuildPlan implements Position{
/** Position and rotation of this request. */
public int x, y, rotation;
/** Block being placed. If null, this is a breaking request.*/
@@ -127,11 +127,11 @@ public class BuildPlan{
}
public float drawx(){
return x*tilesize + block.offset;
return x*tilesize + (block == null ? 0 : block.offset);
}
public float drawy(){
return y*tilesize + block.offset;
return y*tilesize + (block == null ? 0 : block.offset);
}
public @Nullable Tile tile(){
@@ -142,6 +142,16 @@ public class BuildPlan{
return world.build(x, y);
}
@Override
public float getX(){
return drawx();
}
@Override
public float getY(){
return drawy();
}
@Override
public String toString(){
return "BuildRequest{" +

View File

@@ -77,7 +77,6 @@ public class Saves{
}
public void update(){
if(current != null && state.isGame()
&& !(state.isPaused() && Core.scene.hasDialog())){
if(lastTimestamp != 0){
@@ -93,8 +92,8 @@ public class Saves{
try{
current.save();
}catch(Throwable e){
e.printStackTrace();
}catch(Throwable t){
Log.err(t);
}
Time.runTask(3f, () -> saving = false);
@@ -218,7 +217,7 @@ public class Saves{
previewFile().writePNG(renderer.minimap.getPixmap());
requestedPreview = false;
}catch(Throwable t){
t.printStackTrace();
Log.err(t);
}
});
}

View File

@@ -133,10 +133,10 @@ public class Teams{
private void count(Unit unit){
unit.team.data().updateCount(unit.type, 1);
if(unit instanceof Payloadc){
((Payloadc)unit).payloads().each(p -> {
if(p instanceof UnitPayload){
count(((UnitPayload)p).unit);
if(unit instanceof Payloadc payloadc){
payloadc.payloads().each(p -> {
if(p instanceof UnitPayload payload){
count(payload.unit);
}
});
}

View File

@@ -463,7 +463,7 @@ public class LoadRenderer implements Disposable{
Font font = assets.get("tech");
font.setColor(Pal.accent);
Draw.color(Color.black);
font.draw(red + "[[[[ " + key + " ]]\n"+orange+"<" + Version.modifier + " " + (Version.build == 0 ? " [init]" : Version.build == -1 ? " custom" : " " + Version.build) + ">", w/2f, h/2f + 110*s, Align.center);
font.draw(red + "[[[[ " + key + " ]]\n" + orange + "<" + Version.modifier + " " + (Version.build == 0 ? "[init]" : Version.buildString()) + ">", w/2f, h/2f + 110*s, Align.center);
}
Draw.flush();

View File

@@ -188,23 +188,23 @@ public class PlanetGrid{
}
static int pos(Ptile t, Ptile n){
for(int i = 0; i < t.edgeCount; i++)
if(t.tiles[i] == n)
return i;
for(int i = 0; i < t.edgeCount; i++){
if(t.tiles[i] == n) return i;
}
return -1;
}
static int pos(Ptile t, Corner c){
for(int i = 0; i < t.edgeCount; i++)
if(t.corners[i] == c)
return i;
for(int i = 0; i < t.edgeCount; i++){
if(t.corners[i] == c) return i;
}
return -1;
}
static int pos(Corner c, Corner n){
for(int i = 0; i < 3; i++)
if(c.corners[i] == n)
return i;
for(int i = 0; i < 3; i++){
if(c.corners[i] == n) return i;
}
return -1;
}

View File

@@ -18,10 +18,10 @@ import mindustry.type.*;
public class PlanetRenderer implements Disposable{
public static final float outlineRad = 1.17f, camLength = 4f;
public static final Color
outlineColor = Pal.accent.cpy().a(1f),
hoverColor = Pal.accent.cpy().a(0.5f),
borderColor = Pal.accent.cpy().a(0.3f),
shadowColor = new Color(0, 0, 0, 0.7f);
outlineColor = Pal.accent.cpy().a(1f),
hoverColor = Pal.accent.cpy().a(0.5f),
borderColor = Pal.accent.cpy().a(0.3f),
shadowColor = new Color(0, 0, 0, 0.7f);
private static final Seq<Vec3> points = new Seq<>();
@@ -119,7 +119,7 @@ public class PlanetRenderer implements Disposable{
public void renderPlanet(Planet planet){
if(!planet.visible()) return;
//render planet at offsetted position in the world
planet.draw(cam.combined, planet.getTransform(mat));

View File

@@ -47,7 +47,6 @@ public class DesktopInput extends InputHandler{
@Override
public void buildUI(Group group){
group.fill(t -> {
t.visible(() -> Core.settings.getBool("hints") && ui.hudfrag.shown && !player.dead() && !player.unit().spawnedByCore() && !(Core.settings.getBool("hints") && lastSchematic != null && !selectRequests.isEmpty()));
t.bottom();
@@ -482,8 +481,8 @@ public class DesktopInput extends InputHandler{
deleting = true;
}else if(selected != null){
//only begin shooting if there's no cursor event
if(!tileTapped(selected.build) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && (player.builder().plans().size == 0 || !player.builder().updateBuilding()) && !droppingItem &&
!tryBeginMine(selected) && player.miner().mineTile() == null && !Core.scene.hasKeyboard()){
if(!tileTapped(selected.build) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && !player.builder().activelyBuilding() && !droppingItem &&
!tryBeginMine(selected) && player.miner().mineTile() == null && !Core.scene.hasKeyboard()){
player.shooting = shouldShoot;
}
}else if(!Core.scene.hasKeyboard()){ //if it's out of bounds, shooting is just fine
@@ -621,9 +620,7 @@ public class DesktopInput extends InputHandler{
if(aimCursor){
unit.lookAt(mouseAngle);
}else{
if(!movement.isZero()){
unit.lookAt(unit.vel.isZero() ? movement.angle() : unit.vel.angle());
}
unit.lookAt(unit.prefRotation());
}
if(omni){
@@ -644,7 +641,6 @@ public class DesktopInput extends InputHandler{
//update payload input
if(unit instanceof Payloadc){
if(Core.input.keyTap(Binding.pickupCargo)){
tryPickupPayload();
}

View File

@@ -128,7 +128,9 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
!netServer.admins.allowAction(player, ActionType.withdrawItem, tile.tile(), action -> {
action.item = item;
action.itemAmount = amount;
}))) throw new ValidateException(player, "Player cannot request items.");
}))){
throw new ValidateException(player, "Player cannot request items.");
}
//remove item for every controlling unit
player.unit().eachGroup(unit -> {
@@ -931,11 +933,11 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
boolean canMine(Tile tile){
return !Core.scene.hasMouse()
&& tile.drop() != null
&& player.miner().validMine(tile)
&& !(tile.floor().playerUnmineable && tile.overlay().itemDrop == null)
&& player.unit().acceptsItem(tile.drop())
&& tile.block() == Blocks.air;
&& tile.drop() != null
&& player.miner().validMine(tile)
&& !(tile.floor().playerUnmineable && tile.overlay().itemDrop == null)
&& player.unit().acceptsItem(tile.drop())
&& tile.block() == Blocks.air;
}
/** Returns the tile at the specified MOUSE coordinates. */
@@ -984,7 +986,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
public @Nullable Unit selectedUnit(){
Unit unit = Units.closest(player.team(), Core.input.mouseWorld().x, Core.input.mouseWorld().y, 40f, u -> u.isAI());
Unit unit = Units.closest(player.team(), Core.input.mouseWorld().x, Core.input.mouseWorld().y, 40f, Unitc::isAI);
if(unit != null){
unit.hitbox(Tmp.r1);
Tmp.r1.grow(6f);
@@ -1042,7 +1044,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
public boolean canShoot(){
return block == null && !onConfigurable() && !isDroppingItem() && !(player.builder().updateBuilding() && player.builder().isBuilding()) &&
return block == null && !onConfigurable() && !isDroppingItem() && !player.builder().activelyBuilding() &&
!(player.unit() instanceof Mechc && player.unit().isFlying());
}
@@ -1160,7 +1162,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
if(block instanceof PowerNode){
Seq<Point2> skip = new Seq<>();
for(int i = 1; i < points.size; i++){
int overlaps = 0;
Point2 point = points.get(i);

View File

@@ -327,7 +327,6 @@ public class MobileInput extends InputHandler implements GestureListener{
@Override
public void drawTop(){
//draw schematic selection
if(mode == schematicSelect){
drawSelection(lineStartX, lineStartY, lastLineX, lastLineY, Vars.maxSchematicSize);
@@ -866,9 +865,7 @@ public class MobileInput extends InputHandler implements GestureListener{
if(aimCursor){
unit.lookAt(mouseAngle);
}else{
if(unit.moving()){
unit.lookAt(unit.vel.angle());
}
unit.lookAt(unit.prefRotation());
}
if(payloadTarget != null && unit instanceof Payloadc pay){

View File

@@ -188,7 +188,6 @@ public class Placement{
* @param maxLength maximum length of area
*/
public static NormalizeResult normalizeArea(int tilex, int tiley, int endx, int endy, int rotation, boolean snap, int maxLength){
if(snap){
if(Math.abs(tilex - endx) > Math.abs(tiley - endy)){
endy = tiley;

View File

@@ -2,6 +2,7 @@ package mindustry.io.legacy;
import arc.*;
import arc.struct.*;
import arc.util.*;
import mindustry.*;
import mindustry.ctype.*;
import mindustry.ui.dialogs.JoinDialog.*;
@@ -77,8 +78,7 @@ public class LegacyIO{
}
}
}catch(Exception e){
e.printStackTrace();
Log.err(e);
}
}
}

View File

@@ -26,7 +26,6 @@ public abstract class LegacySaveVersion extends SaveVersion{
if(!generating) context.begin();
try{
context.resize(width, height);
//read floor and create tiles first

View File

@@ -283,7 +283,7 @@ public class LCanvas extends Table{
t.add().growX();
t.button(Icon.copy, Styles.logici, () -> {
}).padRight(6).get().tapped(() -> copy());
}).padRight(6).get().tapped(this::copy);
t.button(Icon.cancel, Styles.logici, () -> {
remove();

View File

@@ -1,14 +1,13 @@
package mindustry.logic;
import arc.graphics.*;
import mindustry.graphics.*;
public enum LCategory{
blocks(Pal.accentBack),
control(Color.cyan.cpy().shiftSaturation(-0.6f).mul(0.7f)),
operations(Pal.place.cpy().shiftSaturation(-0.5f).mul(0.7f)),
io(Pal.remove.cpy().shiftSaturation(-0.5f).mul(0.7f)),
units(Pal.bulletYellowBack.cpy().shiftSaturation(-0.3f).mul(0.8f));
blocks(Color.valueOf("d4816b")),
control(Color.valueOf("6bb2b2")),
operations(Color.valueOf("877bad")),
io(Color.valueOf("a08a8a")),
units(Color.valueOf("c7b59d"));
public final Color color;

View File

@@ -32,15 +32,15 @@ public class LExecutor{
//special variables
public static final int
varCounter = 0,
varTime = 1,
varUnit = 2,
varThis = 3;
varCounter = 0,
varTime = 1,
varUnit = 2,
varThis = 3;
public static final int
maxGraphicsBuffer = 256,
maxDisplayBuffer = 1024,
maxTextBuffer = 256;
maxGraphicsBuffer = 256,
maxDisplayBuffer = 1024,
maxTextBuffer = 256;
public LInstruction[] instructions = {};
public Var[] vars = {};
@@ -61,8 +61,9 @@ public class LExecutor{
vars[varTime].numval = Time.millis();
//reset to start
if(vars[varCounter].numval >= instructions.length
|| vars[varCounter].numval < 0) vars[varCounter].numval = 0;
if(vars[varCounter].numval >= instructions.length || vars[varCounter].numval < 0){
vars[varCounter].numval = 0;
}
if(vars[varCounter].numval < instructions.length){
instructions[(int)(vars[varCounter].numval++)].run(this);
@@ -84,9 +85,9 @@ public class LExecutor{
dest.constant = var.constant;
if(var.value instanceof Number){
if(var.value instanceof Number number){
dest.isobj = false;
dest.numval = ((Number)var.value).doubleValue();
dest.numval = number.doubleValue();
}else{
dest.isobj = true;
dest.objval = var.value;
@@ -98,7 +99,7 @@ public class LExecutor{
public @Nullable Building building(int index){
Object o = vars[index].objval;
return vars[index].isobj && o instanceof Building ? (Building)o : null;
return vars[index].isobj && o instanceof Building building ? building : null;
}
public @Nullable Object obj(int index){

View File

@@ -123,8 +123,8 @@ public class ModLoadingSound implements Sound{
}
@Override
public void setPan(int soundId, float pan, float volume){
sound.setPan(soundId, pan, volume);
public void set(int soundId, float pan, float volume){
sound.set(soundId, pan, volume);
}
@Override

View File

@@ -134,7 +134,7 @@ public class Mods implements Loadable{
}catch(IOException e){
Core.app.post(() -> {
Log.err("Error packing images for mod: @", mod.meta.name);
e.printStackTrace();
Log.err(e);
if(!headless) ui.showException(e);
});
break;

View File

@@ -254,8 +254,7 @@ public class Administration{
public boolean unbanPlayerID(String id){
PlayerInfo info = getCreateInfo(id);
if(!info.banned)
return false;
if(!info.banned) return false;
info.banned = false;
bannedIPs.removeAll(info.ips, false);

View File

@@ -254,8 +254,9 @@ public class Net{
}else if(clientListeners.get(object.getClass()) != null){
if(clientLoaded || ((object instanceof Packet) && ((Packet)object).isImportant())){
if(clientListeners.get(object.getClass()) != null)
if(clientListeners.get(object.getClass()) != null){
clientListeners.get(object.getClass()).get(object);
}
Pools.free(object);
}else if(!((object instanceof Packet) && ((Packet)object).isUnimportant())){
packetQueue.add(object);
@@ -273,8 +274,9 @@ public class Net{
public void handleServerReceived(NetConnection connection, Object object){
if(serverListeners.get(object.getClass()) != null){
if(serverListeners.get(object.getClass()) != null)
if(serverListeners.get(object.getClass()) != null){
serverListeners.get(object.getClass()).get(connection, object);
}
Pools.free(object);
}else{
Log.err("Unhandled packet type: '@'!", object.getClass());

View File

@@ -0,0 +1,28 @@
package mindustry.net;
import arc.*;
public class ServerGroup{
public String name;
public String[] addresses;
public ServerGroup(String name, String[] addresses){
this.name = name;
this.addresses = addresses;
}
public ServerGroup(){
}
public boolean hidden(){
return Core.settings.getBool(key() + "-hidden", false);
}
public void setHidden(boolean hidden){
Core.settings.put(key() + "-hidden", hidden);
}
String key(){
return "server-" + (name.isEmpty() ? addresses.length == 0 ? "" : addresses[0] : name);
}
}

View File

@@ -55,6 +55,12 @@ public class ItemSeq implements Iterable<ItemStack>, Serializable{
return out;
}
public void min(int number){
for(Item item : Vars.content.items()){
set(item, Math.min(get(item), number));
}
}
public boolean has(Item item){
return values[item.id] > 0;
}

View File

@@ -81,6 +81,8 @@ public class UnitType extends UnlockableContent{
public AmmoType ammoType = AmmoTypes.copper;
public int mineTier = -1;
public float buildSpeed = 1f, mineSpeed = 1f;
public Sound mineSound = Sounds.minebeam;
public float mineSoundVolume = 0.6f;
/** This is a VERY ROUGH estimate of unit DPS. */
public float dpsEstimate = -1;

View File

@@ -27,7 +27,7 @@ public class Styles{
public static Drawable black, black9, black8, black6, black3, black5, none, flatDown, flatOver;
public static ButtonStyle defaultb, waveb;
public static TextButtonStyle defaultt, squaret, nodet, cleart, discordt, infot, clearPartialt, clearTogglet, clearToggleMenut, togglet, transt, fullTogglet, logict;
public static ImageButtonStyle defaulti, nodei, righti, emptyi, emptytogglei, selecti, logici, geni, colori, cleari, clearFulli, clearPartiali, clearPartial2i, clearTogglei, clearTransi, clearToggleTransi, clearTogglePartiali;
public static ImageButtonStyle defaulti, nodei, righti, emptyi, emptytogglei, selecti, logici, geni, colori, accenti, cleari, clearFulli, clearPartiali, clearPartial2i, clearTogglei, clearTransi, clearToggleTransi, clearTogglePartiali;
public static ScrollPaneStyle defaultPane, horizontalPane, smallPane;
public static KeybindDialogStyle defaultKeybindDialog;
public static SliderStyle defaultSlider, vSlider;
@@ -213,6 +213,11 @@ public class Styles{
//imageDownColor = Pal.accent;
imageUpColor = Color.white;
}};
accenti = new ImageButtonStyle(){{
//imageDownColor = Pal.accent;
imageUpColor = Color.lightGray;
imageDownColor = Color.white;
}};
cleari = new ImageButtonStyle(){{
down = flatOver;
up = black;

View File

@@ -31,6 +31,7 @@ public class JoinDialog extends BaseDialog{
Table hosts = new Table();
int totalHosts;
int refreshes;
boolean showHidden;
public JoinDialog(){
super("@joingame");
@@ -252,9 +253,9 @@ public class JoinDialog extends BaseDialog{
hosts.clear();
section("@servers.local", local);
section("@servers.remote", remote);
section("@servers.global", global);
section("@servers.local", local, false);
section("@servers.remote", remote, false);
section("@servers.global", global, true);
ScrollPane pane = new ScrollPane(hosts);
pane.setFadeScrollBars(false);
@@ -302,12 +303,21 @@ public class JoinDialog extends BaseDialog{
});
}
void section(String label, Table servers){
void section(String label, Table servers, boolean eye){
Collapser coll = new Collapser(servers, Core.settings.getBool("collapsed-" + label, false));
coll.setDuration(0.1f);
hosts.table(name -> {
name.add(label).pad(10).growX().left().color(Pal.accent);
if(eye){
name.button(Icon.eyeSmall, Styles.emptyi, () -> {
showHidden = !showHidden;
refreshGlobal();
}).update(i -> i.getStyle().imageUp = (showHidden ? Icon.eyeSmall : Icon.eyeOffSmall))
.size(40f).right().padRight(3).tooltip("@servers.showhidden");
}
name.button(Icon.downOpen, Styles.emptyi, () -> {
coll.toggle(false);
Core.settings.put("collapsed-" + label, coll.isCollapsed());
@@ -334,17 +344,62 @@ public class JoinDialog extends BaseDialog{
global.clear();
global.background(null);
for(String host : defaultServers){
String resaddress = host.contains(":") ? host.split(":")[0] : host;
int resport = host.contains(":") ? Strings.parseInt(host.split(":")[1]) : port;
net.pingHost(resaddress, resport, res -> {
if(refreshes != cur) return;
res.port = resport;
addGlobalHost(res);
}, e -> {});
for(ServerGroup group : defaultServers){
boolean hidden = group.hidden();
if(hidden && !showHidden){
continue;
}
//table containing all groups
global.table(g -> {
for(String address : group.addresses){
String resaddress = address.contains(":") ? address.split(":")[0] : address;
int resport = address.contains(":") ? Strings.parseInt(address.split(":")[1]) : port;
net.pingHost(resaddress, resport, res -> {
if(refreshes != cur) return;
res.port = resport;
//add header
if(g.getChildren().isEmpty()){
g.table(head -> {
if(!group.name.isEmpty()){
head.add(group.name).color(Color.lightGray).padRight(4);
}
head.image().height(3f).growX().color(Color.lightGray);
//button for showing/hiding servers
ImageButton[] image = {null};
image[0] = head.button(hidden ? Icon.eyeOffSmall : Icon.eyeSmall, Styles.accenti, () -> {
group.setHidden(!group.hidden());
image[0].getStyle().imageUp = group.hidden() ? Icon.eyeOffSmall : Icon.eyeSmall;
if(group.hidden() && !showHidden){
g.remove();
}
}).size(40f).get();
image[0].addListener(new Tooltip(t -> t.background(Styles.black6).margin(4).label(() -> !group.hidden() ? "@server.shown" : "@server.hidden")));
}).width(targetWidth()).padBottom(-2).row();
}
addGlobalHost(res, g);
g.margin(5f);
g.pack();
}, e -> {});
}
}).row();
}
}
void addGlobalHost(Host host, Table container){
global.background(null);
float w = targetWidth();
container.button(b -> buildServer(host, b), Styles.cleart, () -> {
Events.fire(new ClientPreConnectEvent(host));
safeConnect(host.address, host.port, host.version);
}).width(w).row();
}
void finishLocalHosts(){
if(totalHosts == 0){
local.clear();
@@ -367,26 +422,10 @@ public class JoinDialog extends BaseDialog{
local.row();
TextButton button = local.button("", Styles.cleart, () -> {
local.button(b -> buildServer(host, b), Styles.cleart, () -> {
Events.fire(new ClientPreConnectEvent(host));
safeConnect(host.address, host.port, host.version);
}).width(w).pad(5f).get();
button.clearChildren();
buildServer(host, button);
}
void addGlobalHost(Host host){
global.background(null);
float w = targetWidth();
global.row();
TextButton button = global.button("", Styles.cleart, () -> {
Events.fire(new ClientPreConnectEvent(host));
safeConnect(host.address, host.port, host.version);
}).width(w).pad(5f).get();
button.clearChildren();
buildServer(host, button);
}).width(w);
}
public void connect(String ip, int port){
@@ -439,18 +478,28 @@ public class JoinDialog extends BaseDialog{
//get servers
Core.net.httpGet(becontrol.active() ? serverJsonBeURL : serverJsonV6URL, result -> {
try{
Jval val = Jval.read(result.getResultAsString());
Core.app.post(() -> {
try{
defaultServers.clear();
val.asArray().each(child -> defaultServers.add(child.getString("address", "<invalid>")));
val.asArray().each(child -> {
String name = child.getString("name", "");
String[] addresses;
if(child.has("addresses") || (child.has("address") && child.get("address").isArray())){
addresses = (child.has("addresses") ? child.get("addresses") : child.get("address")).asArray().map(Jval::asString).toArray(String.class);
}else{
addresses = new String[]{child.getString("address", "<invalid>")};
}
defaultServers.add(new ServerGroup(name, addresses));
});
Log.info("Fetched @ global servers.", defaultServers.size);
}catch(Throwable ignored){
Log.err("Failed to parse community servers.");
}
});
}catch(Throwable e){
Log.err("Failed to fetch community servers.");
Log.err("Failed to fetch communitycommunity servers.");
}
}, t -> {});
}

View File

@@ -42,6 +42,13 @@ public class LaunchLoadoutDialog extends BaseDialog{
//updates sum requirements
Runnable update = () -> {
int cap = selected.findCore().itemCapacity;
//cap resources based on core type
ItemSeq resources = universe.getLaunchResources();
resources.min(cap);
universe.updateLaunchResources(resources);
total.clear();
selected.requirements().each(total::add);
universe.getLaunchResources().each(total::add);
@@ -79,7 +86,7 @@ public class LaunchLoadoutDialog extends BaseDialog{
ItemSeq stacks = universe.getLaunchResources();
Seq<ItemStack> out = stacks.toSeq();
loadout.show(core.itemCapacity, out, UnlockableContent::unlocked, out::clear, () -> {}, () -> {
loadout.show(selected.findCore().itemCapacity, out, UnlockableContent::unlocked, out::clear, () -> {}, () -> {
universe.updateLaunchResources(new ItemSeq(out));
update.run();
rebuildItems.run();

View File

@@ -429,7 +429,7 @@ public class SettingsMenuDialog extends SettingsDialog{
}
});
graphics.checkPref("linear", true, b -> {
graphics.checkPref("linear", !mobile, b -> {
for(Texture tex : Core.atlas.getTextures()){
TextureFilter filter = b ? TextureFilter.linear : TextureFilter.nearest;
tex.setFilter(filter, filter);

View File

@@ -108,7 +108,6 @@ public class MenuFragment extends Fragment{
editor = new MobileButton(Icon.terrain, "@editor", () -> checkPlay(ui.maps::show)),
tools = new MobileButton(Icon.settings, "@settings", ui.settings::show),
mods = new MobileButton(Icon.book, "@mods", ui.mods::show),
donate = new MobileButton(Icon.link, "@website", () -> Core.app.openURI("https://anuke.itch.io/mindustry")),
exit = new MobileButton(Icon.exit, "@quit", () -> Core.app.exit());
if(!Core.graphics.isPortrait()){
@@ -195,6 +194,7 @@ public class MenuFragment extends Fragment{
}
private void checkPlay(Runnable run){
if(!mods.hasContentErrors()){
run.run();
}else{

View File

@@ -42,7 +42,7 @@ public class Conveyor extends Block implements Autotiler{
conveyorPlacement = true;
ambientSound = Sounds.conveyor;
ambientSoundVolume = 0.002f;
ambientSoundVolume = 0.0015f;
unloadable = false;
noUpdateDisabled = false;
}