Merge branch 'master' of https://github.com/Anuken/Mindustry into 7.0-features

 Conflicts:
	core/src/mindustry/mod/ClassMap.java
This commit is contained in:
Anuken
2021-07-04 09:52:57 -04:00
34 changed files with 168 additions and 135 deletions

View File

@@ -285,7 +285,7 @@ public class BlockIndexer{
for(int i = 0; i < activeTeams.size; i++){
Team enemy = activeTeams.items[i];
if(enemy == team || team == Team.derelict) continue;
if(enemy == team || (team == Team.derelict && !state.rules.coreCapture)) continue;
Building entity = indexer.findTile(enemy, x, y, range, pred, true);
if(entity != null){
@@ -360,7 +360,7 @@ public class BlockIndexer{
private void process(Tile tile){
var team = tile.team();
//only process entity changes with centered tiles
if(tile.isCenter() && team != Team.derelict){
if(tile.isCenter() && tile.build != null){
var data = team.data();
if(tile.block().flags.size() > 0 && tile.isCenter()){
TileArray[] map = getFlagged(team);

View File

@@ -119,9 +119,11 @@ public class Pathfinder implements Runnable{
}
}
int tid = tile.getTeamID();
return PathTile.get(
tile.build == null || !solid || tile.block() instanceof CoreBlock ? 0 : Math.min((int)(tile.build.health / 40), 80),
tile.getTeamID(),
tid == 0 && tile.build != null && state.rules.coreCapture ? 255 : tid, //use teamid = 255 when core capture is enabled to mark out derelict structures
solid,
tile.floor().isLiquid,
tile.staticDarkness() >= 2 || (tile.floor().solid && tile.block() == Blocks.air),

View File

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

View File

@@ -2147,25 +2147,25 @@ public class Blocks implements ContentList{
}};
repairPoint = new RepairPoint("repair-point"){{
requirements(Category.units, with(Items.lead, 25, Items.copper, 25, Items.silicon, 20));
repairSpeed = 0.5f;
repairRadius = 65f;
requirements(Category.units, with(Items.lead, 30, Items.copper, 30, Items.silicon, 20));
repairSpeed = 0.45f;
repairRadius = 60f;
beamWidth = 0.73f;
powerUse = 1f;
pulseRadius = 5f;
}};
repairTurret = new RepairPoint("repair-turret"){{
requirements(Category.units, with(Items.silicon, 90, Items.thorium, 80, Items.plastanium, 80));
requirements(Category.units, with(Items.silicon, 90, Items.thorium, 80, Items.plastanium, 60));
size = 2;
length = 6f;
repairSpeed = 3.25f;
repairRadius = 140f;
repairSpeed = 3f;
repairRadius = 145f;
powerUse = 5f;
beamWidth = 1.1f;
pulseRadius = 6.1f;
coolantUse = 0.16f;
coolantMultiplier = 1.5f;
coolantMultiplier = 1.6f;
acceptCoolant = true;
}};

View File

@@ -87,7 +87,7 @@ public class UnitTypes implements ContentList{
mace = new UnitType("mace"){{
speed = 0.45f;
hitSize = 10f;
health = 530;
health = 540;
armor = 4f;
immunities.add(StatusEffects.burning);
@@ -96,7 +96,7 @@ public class UnitTypes implements ContentList{
top = false;
shootSound = Sounds.flame;
shootY = 2f;
reload = 12f;
reload = 11f;
recoil = 1f;
ejectEffect = Fx.none;
bullet = new BulletType(4.1f, 32f){{
@@ -1125,10 +1125,10 @@ public class UnitTypes implements ContentList{
BulletType fragBullet = new FlakBulletType(4f, 5){{
shootEffect = Fx.shootBig;
ammoMultiplier = 4f;
splashDamage = 50f;
splashDamage = 60f;
splashDamageRadius = 25f;
collidesGround = true;
lifetime = 38f;
lifetime = 47f;
status = StatusEffects.blasted;
statusDuration = 60f;
@@ -1148,12 +1148,12 @@ public class UnitTypes implements ContentList{
rotate = true;
bullet = new LaserBulletType(){{
damage = 100f;
damage = 110f;
sideAngle = 20f;
sideWidth = 1.5f;
sideLength = 80f;
width = 25f;
length = 200f;
length = 230f;
shootEffect = Fx.shockwave;
colors = new Color[]{Color.valueOf("ec7458aa"), Color.valueOf("ff9c5a"), Color.white};
}};

View File

@@ -247,11 +247,11 @@ public class Logic implements ApplicationListener{
Events.fire(new GameOverEvent(state.rules.waveTeam));
}else if(state.rules.attackMode){
//count # of teams alive
int countAlive = state.teams.getActive().count(TeamData::hasCore);
int countAlive = state.teams.getActive().count(t -> t.hasCore() && t.team != Team.derelict);
if((countAlive <= 1 || (!state.rules.pvp && state.rules.defaultTeam.core() == null)) && !state.gameOver){
//find team that won
TeamData left = state.teams.getActive().find(TeamData::hasCore);
TeamData left = state.teams.getActive().find(t -> t.hasCore() && t.team != Team.derelict);
Events.fire(new GameOverEvent(left == null ? Team.derelict : left.team));
state.gameOver = true;
}

View File

@@ -114,22 +114,6 @@ public class Rules{
/** special tags for additional info. */
public StringMap tags = new StringMap();
/** A team-specific ruleset. */
public static class TeamRule{
/** Whether to use building AI. */
public boolean ai;
/** TODO Tier of blocks/designs that the AI uses for building. [0, 1] */
public float aiTier = 1f;
/** Whether, when AI is enabled, ships should be spawned from the core. */
public boolean aiCoreSpawn = true;
/** If true, blocks don't require power or resources. */
public boolean cheat;
/** If true, resources are not consumed when building. */
public boolean infiniteResources;
/** If true, this team has infinite unit ammo. */
public boolean infiniteAmmo;
}
/** Copies this ruleset exactly. Not efficient at all, do not use often. */
public Rules copy(){
return JsonIO.copy(this);
@@ -150,6 +134,22 @@ public class Rules{
}
}
/** A team-specific ruleset. */
public static class TeamRule{
/** Whether to use building AI. */
public boolean ai;
/** TODO Tier of blocks/designs that the AI uses for building. [0, 1] */
public float aiTier = 1f;
/** Whether, when AI is enabled, ships should be spawned from the core. */
public boolean aiCoreSpawn = true;
/** If true, blocks don't require power or resources. */
public boolean cheat;
/** If true, resources are not consumed when building. */
public boolean infiniteResources;
/** If true, this team has infinite unit ammo. */
public boolean infiniteAmmo;
}
/** A simple map for storing TeamRules in an efficient way without hashing. */
public static class TeamRules implements JsonSerializable{
final TeamRule[] values = new TeamRule[Team.all.length];

View File

@@ -97,7 +97,7 @@ public class Team implements Comparable<Team>{
}
public boolean isEnemy(Team other){
return state.teams.areEnemies(this, other);
return this != other;
}
public Seq<CoreBuild> cores(){

View File

@@ -49,7 +49,7 @@ public class Teams{
public boolean eachEnemyCore(Team team, Boolf<CoreBuild> ret){
for(TeamData data : active){
if(areEnemies(team, data.team)){
if(team != data.team){
for(CoreBuild tile : data.cores){
if(ret.get(tile)){
return true;
@@ -62,7 +62,7 @@ public class Teams{
public void eachEnemyCore(Team team, Cons<Building> ret){
for(TeamData data : active){
if(areEnemies(team, data.team)){
if(team != data.team){
for(Building tile : data.cores){
ret.get(tile);
}
@@ -91,11 +91,6 @@ public class Teams{
return get(team).active();
}
/** Returns whether {@param other} is an enemy of {@param #team}. */
public boolean areEnemies(Team team, Team other){
return team != other;
}
public boolean canInteract(Team team, Team other){
return team == other || other == Team.derelict;
}
@@ -216,7 +211,7 @@ public class Teams{
Seq<Team> enemies = new Seq<>();
for(TeamData other : active){
if(areEnemies(data.team, other.team)){
if(data.team != other.team){
enemies.add(other.team);
}
}

View File

@@ -339,7 +339,7 @@ public class BlockRenderer{
Draw.z(Layer.block);
}
if(renderer.drawStatus && block.consumes.any()){
if(entity.team == player.team() && renderer.drawStatus && block.consumes.any()){
entity.drawStatus();
}
}

View File

@@ -1242,12 +1242,14 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
diagonal = !diagonal;
}
int endRotation = -1;
if(diagonal){
var start = world.build(startX, startY);
var end = world.build(endX, endY);
if(block != null && start instanceof ChainedBuilding && end instanceof ChainedBuilding
&& block.canReplace(end.block) && block.canReplace(start.block)){
points = Placement.upgradeLine(startX, startY, endX, endY);
endRotation = end.rotation;
}else{
points = Placement.pathfindLine(block != null && block.conveyorPlacement, startX, startY, endX, endY);
}
@@ -1281,6 +1283,8 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
int result = baseRotation;
if(next != null){
result = Tile.relativeTo(point.x, point.y, next.x, next.y);
}else if(endRotation != -1){
result = endRotation;
}else if(block.conveyorPlacement && i > 0){
Point2 prev = points.get(i - 1);
result = Tile.relativeTo(prev.x, prev.y, point.x, point.y);

View File

@@ -167,6 +167,7 @@ public class ClassMap{
classes.put("StackConveyor", mindustry.world.blocks.distribution.StackConveyor.class);
classes.put("StackConveyorBuild", mindustry.world.blocks.distribution.StackConveyor.StackConveyorBuild.class);
classes.put("AirBlock", mindustry.world.blocks.environment.AirBlock.class);
classes.put("Bush", mindustry.world.blocks.environment.Bush.class);
classes.put("Cliff", mindustry.world.blocks.environment.Cliff.class);
classes.put("DoubleOverlayFloor", mindustry.world.blocks.environment.DoubleOverlayFloor.class);
classes.put("Floor", mindustry.world.blocks.environment.Floor.class);
@@ -175,15 +176,19 @@ public class ClassMap{
classes.put("Prop", mindustry.world.blocks.environment.Prop.class);
classes.put("ShallowLiquid", mindustry.world.blocks.environment.ShallowLiquid.class);
classes.put("SpawnBlock", mindustry.world.blocks.environment.SpawnBlock.class);
classes.put("StaticClusterWall", mindustry.world.blocks.environment.StaticClusterWall.class);
classes.put("StaticTree", mindustry.world.blocks.environment.StaticTree.class);
classes.put("StaticWall", mindustry.world.blocks.environment.StaticWall.class);
classes.put("TreeBlock", mindustry.world.blocks.environment.TreeBlock.class);
classes.put("WallOreBlock", mindustry.world.blocks.environment.WallOreBlock.class);
classes.put("WavingProp", mindustry.world.blocks.environment.WavingProp.class);
classes.put("WobbleProp", mindustry.world.blocks.environment.WobbleProp.class);
classes.put("BlockLoader", BlockLoader.class);
classes.put("BlockLoaderBuild", BlockLoader.BlockLoaderBuild.class);
classes.put("BlockUnloader", BlockUnloader.class);
classes.put("BlockUnloaderBuild", BlockUnloader.BlockUnloaderBuild.class);
classes.put("BlockForge", mindustry.world.blocks.experimental.BlockForge.class);
classes.put("BlockForgeBuild", mindustry.world.blocks.experimental.BlockForge.BlockForgeBuild.class);
classes.put("BlockLoader", mindustry.world.blocks.experimental.BlockLoader.class);
classes.put("BlockLoaderBuild", mindustry.world.blocks.experimental.BlockLoader.BlockLoaderBuild.class);
classes.put("BlockUnloader", mindustry.world.blocks.experimental.BlockUnloader.class);
classes.put("BlockUnloaderBuild", mindustry.world.blocks.experimental.BlockUnloader.BlockUnloaderBuild.class);
classes.put("LegacyBlock", mindustry.world.blocks.legacy.LegacyBlock.class);
classes.put("LegacyMechPad", mindustry.world.blocks.legacy.LegacyMechPad.class);
classes.put("LegacyMechPadBuild", mindustry.world.blocks.legacy.LegacyMechPad.LegacyMechPadBuild.class);
@@ -219,8 +224,12 @@ public class ClassMap{
classes.put("BallisticSiloBuild", mindustry.world.blocks.payloads.BallisticSilo.BallisticSiloBuild.class);
classes.put("BlockForge", mindustry.world.blocks.payloads.BlockForge.class);
classes.put("BlockForgeBuild", mindustry.world.blocks.payloads.BlockForge.BlockForgeBuild.class);
classes.put("BlockLoader", mindustry.world.blocks.payloads.BlockLoader.class);
classes.put("BlockLoaderBuild", mindustry.world.blocks.payloads.BlockLoader.BlockLoaderBuild.class);
classes.put("BlockProducer", mindustry.world.blocks.payloads.BlockProducer.class);
classes.put("BlockProducerBuild", mindustry.world.blocks.payloads.BlockProducer.BlockProducerBuild.class);
classes.put("BlockUnloader", mindustry.world.blocks.payloads.BlockUnloader.class);
classes.put("BlockUnloaderBuild", mindustry.world.blocks.payloads.BlockUnloader.BlockUnloaderBuild.class);
classes.put("BuildPayload", mindustry.world.blocks.payloads.BuildPayload.class);
classes.put("NuclearWarhead", mindustry.world.blocks.payloads.NuclearWarhead.class);
classes.put("NuclearWarheadBuild", mindustry.world.blocks.payloads.NuclearWarhead.NuclearWarheadBuild.class);
@@ -234,7 +243,7 @@ public class ClassMap{
classes.put("PayloadSource", mindustry.world.blocks.payloads.PayloadSource.class);
classes.put("PayloadSourceBuild", mindustry.world.blocks.payloads.PayloadSource.PayloadSourceBuild.class);
classes.put("PayloadVoid", mindustry.world.blocks.payloads.PayloadVoid.class);
classes.put("BlockLoaderBuild", PayloadVoid.PayloadVoidBuild.class);
classes.put("PayloadVoidBuild", mindustry.world.blocks.payloads.PayloadVoid.PayloadVoidBuild.class);
classes.put("UnitPayload", mindustry.world.blocks.payloads.UnitPayload.class);
classes.put("Battery", mindustry.world.blocks.power.Battery.class);
classes.put("BatteryBuild", mindustry.world.blocks.power.Battery.BatteryBuild.class);
@@ -242,6 +251,7 @@ public class ClassMap{
classes.put("BurnerGeneratorBuild", mindustry.world.blocks.power.BurnerGenerator.BurnerGeneratorBuild.class);
classes.put("ConditionalConsumePower", mindustry.world.blocks.power.ConditionalConsumePower.class);
classes.put("DecayGenerator", mindustry.world.blocks.power.DecayGenerator.class);
classes.put("DynamicConsumePower", mindustry.world.blocks.power.DynamicConsumePower.class);
classes.put("ImpactReactor", mindustry.world.blocks.power.ImpactReactor.class);
classes.put("ImpactReactorBuild", mindustry.world.blocks.power.ImpactReactor.ImpactReactorBuild.class);
classes.put("ItemLiquidGenerator", mindustry.world.blocks.power.ItemLiquidGenerator.class);
@@ -330,6 +340,7 @@ public class ClassMap{
classes.put("DrawCells", mindustry.world.draw.DrawCells.class);
classes.put("DrawCultivator", mindustry.world.draw.DrawCultivator.class);
classes.put("DrawGlow", mindustry.world.draw.DrawGlow.class);
classes.put("DrawLiquid", mindustry.world.draw.DrawLiquid.class);
classes.put("DrawMixer", mindustry.world.draw.DrawMixer.class);
classes.put("DrawRotator", mindustry.world.draw.DrawRotator.class);
classes.put("DrawSmelter", mindustry.world.draw.DrawSmelter.class);

View File

@@ -391,15 +391,7 @@ public class ArcNetProvider implements NetProvider{
//no compression, copy over buffer
if(compression == 0){
buffer.position(0).limit(length);
if(byteBuffer.hasArray()){
buffer.put(byteBuffer.array(), byteBuffer.position(), length);
}else{
byte[] readcopy = new byte[length];
int pos = byteBuffer.position();
byteBuffer.get(readcopy);
byteBuffer.position(pos);
buffer.put(readcopy);
}
buffer.put(byteBuffer.array(), byteBuffer.position(), length);
buffer.position(0);
packet.read(reads.get(), length);
//move read packets forward

View File

@@ -147,26 +147,18 @@ public class CrashSender{
ex(() -> value.addChild("javaVersion", new JsonValue(System.getProperty("java.version"))));
ex(() -> value.addChild("javaArch", new JsonValue(System.getProperty("sun.arch.data.model"))));
boolean[] sent = {false};
Log.info("Sending crash report.");
//post to crash report URL, exit code indicates send success
httpPost(Vars.crashReportURL, value.toJson(OutputType.json), r -> {
new arc.Net().http(new HttpRequest().block(true).method(HttpMethod.POST).content(value.toJson(OutputType.json)).url(Vars.crashReportURL), r -> {
Log.info("Crash sent successfully.");
sent[0] = true;
System.exit(1);
}, t -> {
t.printStackTrace();
sent[0] = true;
Log.info("Crash report not sent.");
System.exit(-1);
});
//sleep until report is sent
try{
while(!sent[0]){
Thread.sleep(30);
}
}catch(InterruptedException ignored){}
ret();
}catch(Throwable death){
death.printStackTrace();
}
@@ -178,10 +170,6 @@ public class CrashSender{
System.exit(1);
}
private static void httpPost(String url, String content, Cons<HttpResponse> success, Cons<Throwable> failure){
new NetJavaImpl().http(new HttpRequest().method(HttpMethod.POST).content(content).url(url), success, failure);
}
private static String parseException(Throwable e){
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);

View File

@@ -9,6 +9,7 @@ import arc.util.async.*;
import mindustry.gen.*;
import mindustry.net.Packets.*;
import mindustry.net.Streamable.*;
import net.jpountz.lz4.*;
import java.io.*;
import java.nio.*;
@@ -33,7 +34,7 @@ public class Net{
private final ObjectMap<Class<?>, Cons> clientListeners = new ObjectMap<>();
private final ObjectMap<Class<?>, Cons2<NetConnection, Object>> serverListeners = new ObjectMap<>();
private final IntMap<StreamBuilder> streams = new IntMap<>();
private final ExecutorService pingExecutor = Threads.executor(Math.max(Runtime.getRuntime().availableProcessors(), 6));
private final ExecutorService pingExecutor = Threads.cachedExecutor();
private final NetProvider provider;
@@ -97,7 +98,7 @@ public class Net{
if(e instanceof BufferUnderflowException || e instanceof BufferOverflowException){
error = Core.bundle.get("error.io");
}else if(error.equals("mismatch") || (e instanceof IndexOutOfBoundsException && e.getStackTrace()[0].getClassName().contains("java.nio"))){
}else if(error.equals("mismatch") || e instanceof LZ4Exception || (e instanceof IndexOutOfBoundsException && e.getStackTrace()[0].getClassName().contains("java.nio"))){
error = Core.bundle.get("error.mismatch");
}else if(error.contains("port out of range") || error.contains("invalid argument") || (error.contains("invalid") && error.contains("address")) || Strings.neatError(e).contains("address associated")){
error = Core.bundle.get("error.invalidaddress");
@@ -325,13 +326,6 @@ public class Net{
pingExecutor.submit(() -> provider.pingHost(address, port, valid, failed));
}
/**
* Pings a host in an new thread. If an error occurred, failed() should be called with the exception.
*/
public void pingHostThread(String address, int port, Cons<Host> valid, Cons<Exception> failed){
Threads.daemon(() -> provider.pingHost(address, port, valid, failed));
}
/**
* Whether the net is active, e.g. whether this is a multiplayer game.
*/

View File

@@ -257,7 +257,7 @@ public class UnitType extends UnlockableContent{
stats.add(Stat.health, health);
stats.add(Stat.armor, armor);
stats.add(Stat.speed, speed);
stats.add(Stat.speed, speed * 60f / tilesize, StatUnit.tilesSecond);
stats.add(Stat.size, hitSize / tilesize, StatUnit.blocksSquared);
stats.add(Stat.itemCapacity, itemCapacity);
stats.add(Stat.range, (int)(maxRange / tilesize), StatUnit.blocks);

View File

@@ -375,7 +375,7 @@ public class JoinDialog extends BaseDialog{
for(String address : group.addresses){
String resaddress = address.contains(":") ? address.split(":")[0] : address;
int resport = address.contains(":") ? Strings.parseInt(address.split(":")[1]) : port;
net.pingHostThread(resaddress, resport, res -> {
net.pingHost(resaddress, resport, res -> {
if(refreshes != cur) return;
res.port = resport;

View File

@@ -20,7 +20,7 @@ public class PayloadConveyor extends Block{
public @Load("@-top") TextureRegion topRegion;
public @Load("@-edge") TextureRegion edgeRegion;
public Interp interp = Interp.pow5;
public float payloadLimit = 2.9f;
public float payloadLimit = 3f;
public PayloadConveyor(String name){
super(name);
@@ -75,7 +75,7 @@ public class PayloadConveyor extends Block{
@Override
public boolean canControlSelect(Player player){
return this.item == null && !player.unit().spawnedByCore && player.unit().hitSize / tilesize <= payloadLimit && player.tileOn().build == this;
return this.item == null && !player.unit().spawnedByCore && player.unit().hitSize / tilesize <= payloadLimit && player.tileOn() != null && player.tileOn().build == this;
}
@Override

View File

@@ -26,6 +26,7 @@ public interface Payload extends Position{
float size();
float x();
float y();
/** @return the items needed to make this payload; may be empty. */
@@ -39,7 +40,7 @@ public interface Payload extends Position{
return false;
}
/** @return whether this payload fits in a given size. 2.5 is the max for a standard 3x3 conveyor. */
/** @return whether this payload fits in a given size. 3 is the max for a standard 3x3 conveyor. */
default boolean fits(float s){
return size() / tilesize <= s;
}

View File

@@ -30,6 +30,7 @@ public class Separator extends Block{
solid = true;
hasItems = true;
hasLiquids = true;
sync = true;
}
@Override
@@ -45,6 +46,12 @@ public class Separator extends Block{
public float progress;
public float totalProgress;
public float warmup;
public int seed;
@Override
public void created(){
seed = Mathf.randomSeed(tile.pos(), 0, Integer.MAX_VALUE - 1);
}
@Override
public boolean shouldAmbientSound(){
@@ -91,7 +98,7 @@ public class Separator extends Block{
int sum = 0;
for(ItemStack stack : results) sum += stack.amount;
int i = Mathf.random(sum);
int i = Mathf.randomSeed(seed++, 0, sum);
int count = 0;
Item item = null;
@@ -121,11 +128,19 @@ public class Separator extends Block{
return !consumes.itemFilters.get(item.id);
}
//TODO write seed in 128 release, don't write it now for compatibility with 127.x
//@Override
//public byte version(){
// return 1;
//}
@Override
public void write(Writes write){
super.write(write);
write.f(progress);
write.f(warmup);
//TODO see above
//write.i(seed);
}
@Override
@@ -133,6 +148,8 @@ public class Separator extends Block{
super.read(read, revision);
progress = read.f();
warmup = read.f();
//TODO see above
//if(revision == 1) seed = read.i();
}
}
}

View File

@@ -10,6 +10,7 @@ import java.util.*;
public enum StatUnit{
blocks,
blocksSquared,
tilesSecond,
powerSecond,
liquidSecond,
itemsSecond,