Merge branch 'master' into master

This commit is contained in:
Felix Corvus
2020-09-19 17:01:57 +03:00
committed by GitHub
134 changed files with 15238 additions and 12129 deletions

View File

@@ -77,7 +77,11 @@ public class EntityProcess extends BaseProcessor{
for(Smethod elem : component.methods()){ for(Smethod elem : component.methods()){
if(elem.is(Modifier.ABSTRACT) || elem.is(Modifier.NATIVE)) continue; if(elem.is(Modifier.ABSTRACT) || elem.is(Modifier.NATIVE)) continue;
//get all statements in the method, store them //get all statements in the method, store them
methodBlocks.put(elem.descString(), elem.tree().getBody().toString()); methodBlocks.put(elem.descString(), elem.tree().getBody().toString()
//replace all self() invocations with this
.replaceAll("this\\.<(.*)>self\\(\\)", "this")
.replaceAll("self\\(\\)", "this")
);
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 984 B

After

Width:  |  Height:  |  Size: 893 B

View File

@@ -4,6 +4,5 @@
flattenPaths: true, flattenPaths: true,
maxWidth: 4096, maxWidth: 4096,
maxHeight: 4096, maxHeight: 4096,
minHeight: 2048,
fast: true fast: true
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -876,9 +876,11 @@ liquid.water.name = Water
liquid.slag.name = Slag liquid.slag.name = Slag
liquid.oil.name = Oil liquid.oil.name = Oil
liquid.cryofluid.name = Cryofluid liquid.cryofluid.name = Cryofluid
item.explosiveness = [lightgray]Explosiveness: {0}% item.explosiveness = [lightgray]Explosiveness: {0}%
item.flammability = [lightgray]Flammability: {0}% item.flammability = [lightgray]Flammability: {0}%
item.radioactivity = [lightgray]Radioactivity: {0}% item.radioactivity = [lightgray]Radioactivity: {0}%
unit.health = [lightgray]Health: {0} unit.health = [lightgray]Health: {0}
unit.speed = [lightgray]Speed: {0} unit.speed = [lightgray]Speed: {0}
unit.weapon = [lightgray]Weapon: {0} unit.weapon = [lightgray]Weapon: {0}
@@ -914,6 +916,8 @@ unit.mega.name = Mega
unit.risso.name = Risso unit.risso.name = Risso
unit.minke.name = Minke unit.minke.name = Minke
unit.bryde.name = Bryde unit.bryde.name = Bryde
unit.sei.name = Sei
unit.omura.name = Omura
unit.alpha.name = Alpha unit.alpha.name = Alpha
unit.beta.name = Beta unit.beta.name = Beta
unit.gamma.name = Gamma unit.gamma.name = Gamma
@@ -979,6 +983,7 @@ block.dune-wall.name = Dune Wall
block.pine.name = Pine block.pine.name = Pine
block.dirt.name = Dirt block.dirt.name = Dirt
block.dirt-wall.name = Dirt Wall block.dirt-wall.name = Dirt Wall
block.mud.name = Mud
block.white-tree-dead.name = White Tree Dead block.white-tree-dead.name = White Tree Dead
block.white-tree.name = White Tree block.white-tree.name = White Tree
block.spore-cluster.name = Spore Cluster block.spore-cluster.name = Spore Cluster

View File

@@ -803,7 +803,7 @@ rules.title.unit = 유닛
rules.title.experimental = 실험적인 기능 rules.title.experimental = 실험적인 기능
rules.title.environment = 환경 rules.title.environment = 환경
rules.lighting = 조명 rules.lighting = 조명
rules.ambientlight = 주변 조명 rules.ambientlight = 자연 조명
rules.solarpowermultiplier = 태양광 발전 배수 rules.solarpowermultiplier = 태양광 발전 배수
content.item.name = 자원 content.item.name = 자원
@@ -856,11 +856,12 @@ unit.crawler.name = 크롤러
unit.atrax.name = 아트락스 unit.atrax.name = 아트락스
unit.spiroct.name = 스피록트 unit.spiroct.name = 스피록트
unit.arkyid.name = 아키드 unit.arkyid.name = 아키드
unit.flare.name = 화염 unit.toxipod.name = 독소포드
unit.horizon.name = 수평선 unit.flare.name = 플레어
unit.zenith.name = 천정 unit.horizon.name = 호라이즌
unit.antumbra.name = 그림자 unit.zenith.name = 제니스
unit.eclipse.name = 일식 unit.antumbra.name = 안텀브라
unit.eclipse.name = 이클립스
unit.mono.name = 모노 unit.mono.name = 모노
unit.poly.name = 폴리 unit.poly.name = 폴리
unit.mega.name = 메가 unit.mega.name = 메가

File diff suppressed because it is too large Load Diff

View File

@@ -91,3 +91,4 @@ GioIacca9
SnakkiZXZ SnakkiZXZ
sk7725 sk7725
The Slaylord The Slaylord
ThePlayerA

View File

@@ -311,3 +311,6 @@
63433=dacite-wall|block-dacite-wall-medium 63433=dacite-wall|block-dacite-wall-medium
63432=dacite-boulder|block-dacite-boulder-medium 63432=dacite-boulder|block-dacite-boulder-medium
63431=large-logic-display|block-large-logic-display-medium 63431=large-logic-display|block-large-logic-display-medium
63430=omura|unit-omura-medium
63429=mud|block-mud-medium
63428=sei|unit-sei-medium

Binary file not shown.

View File

@@ -0,0 +1,29 @@
#define HIGHP
#define NSCALE 180.0 / 2.0
uniform sampler2D u_texture;
uniform sampler2D u_noise;
uniform vec2 u_campos;
uniform vec2 u_resolution;
uniform float u_time;
varying vec2 v_texCoords;
void main(){
vec2 c = v_texCoords.xy;
vec2 coords = vec2(c.x * u_resolution.x + u_campos.x, c.y * u_resolution.y + u_campos.y);
float btime = u_time / 8000000.0;
float noise = sin((texture2D(u_noise, (coords) / NSCALE + vec2(btime) * vec2(-0.9, 0.8)).r + texture2D(u_noise, (coords) / NSCALE + vec2(abs(sin(btime)) * 1.1) * vec2(-0.8, -1.0)).r) / 2.0);
vec4 color = texture2D(u_texture, c);
if(noise > 0.54 && noise < 0.68){
color.rgb *= 1.4;
}else if(!(noise > 0.40 && noise < 0.54)){
color.rgb *= 1.2;
}
gl_FragColor = color;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 811 B

After

Width:  |  Height:  |  Size: 811 B

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 647 KiB

After

Width:  |  Height:  |  Size: 642 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 958 KiB

After

Width:  |  Height:  |  Size: 735 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 365 KiB

After

Width:  |  Height:  |  Size: 1013 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 KiB

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 KiB

After

Width:  |  Height:  |  Size: 325 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 415 KiB

After

Width:  |  Height:  |  Size: 416 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 KiB

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 314 KiB

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 418 KiB

After

Width:  |  Height:  |  Size: 420 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

@@ -33,7 +33,7 @@ public class BlockIndexer{
/** Maps each team ID to a quarant. A quadrant is a grid of bits, where each bit is set if and only if there is a block of that team in that quadrant. */ /** Maps each team ID to a quarant. A quadrant is a grid of bits, where each bit is set if and only if there is a block of that team in that quadrant. */
private GridBits[] structQuadrants; private GridBits[] structQuadrants;
/** Stores all damaged tile entities by team. */ /** Stores all damaged tile entities by team. */
private BuildingArray[] damagedTiles = new BuildingArray[Team.all.length]; private ObjectSet<Building>[] damagedTiles = new ObjectSet[Team.all.length];
/** All ores available on this map. */ /** All ores available on this map. */
private ObjectSet<Item> allOres = new ObjectSet<>(); private ObjectSet<Item> allOres = new ObjectSet<>();
/** Stores teams that are present here as tiles. */ /** Stores teams that are present here as tiles. */
@@ -70,7 +70,7 @@ public class BlockIndexer{
Events.on(WorldLoadEvent.class, event -> { Events.on(WorldLoadEvent.class, event -> {
scanOres.clear(); scanOres.clear();
scanOres.addAll(Item.getAllOres()); scanOres.addAll(Item.getAllOres());
damagedTiles = new BuildingArray[Team.all.length]; damagedTiles = new ObjectSet[Team.all.length];
flagMap = new TileArray[Team.all.length][BlockFlag.all.length]; flagMap = new TileArray[Team.all.length][BlockFlag.all.length];
unitCaps = new int[Team.all.length]; unitCaps = new int[Team.all.length];
activeTeams = new Seq<>(Team.class); activeTeams = new Seq<>(Team.class);
@@ -139,14 +139,14 @@ public class BlockIndexer{
} }
/** Returns all damaged tiles by team. */ /** Returns all damaged tiles by team. */
public BuildingArray getDamaged(Team team){ public ObjectSet<Building> getDamaged(Team team){
returnArray.clear(); breturnArray.clear();
if(damagedTiles[team.id] == null){ if(damagedTiles[team.id] == null){
damagedTiles[team.id] = new BuildingArray(); damagedTiles[team.id] = new ObjectSet<>();
} }
BuildingArray set = damagedTiles[team.id]; ObjectSet<Building> set = damagedTiles[team.id];
for(Building build : set){ for(Building build : set){
if((!build.isValid() || build.team != team || !build.damaged()) || build.block instanceof ConstructBlock){ if((!build.isValid() || build.team != team || !build.damaged()) || build.block instanceof ConstructBlock){
breturnArray.add(build); breturnArray.add(build);
@@ -214,7 +214,7 @@ public class BlockIndexer{
public void notifyTileDamaged(Building entity){ public void notifyTileDamaged(Building entity){
if(damagedTiles[entity.team.id] == null){ if(damagedTiles[entity.team.id] == null){
damagedTiles[entity.team.id] = new BuildingArray(); damagedTiles[entity.team.id] = new ObjectSet<Building>();
} }
damagedTiles[entity.team.id].add(entity); damagedTiles[entity.team.id].add(entity);
@@ -476,35 +476,4 @@ public class BlockIndexer{
return tiles.iterator(); return tiles.iterator();
} }
} }
//TODO copy-pasted code, generics would be nice here
public static class BuildingArray implements Iterable<Building>{
private Seq<Building> tiles = new Seq<>(false, 16);
private IntSet contained = new IntSet();
public void add(Building tile){
if(contained.add(tile.pos())){
tiles.add(tile);
}
}
public void remove(Building tile){
if(contained.remove(tile.pos())){
tiles.remove(tile);
}
}
public int size(){
return tiles.size;
}
public Building first(){
return tiles.first();
}
@Override
public Iterator<Building> iterator(){
return tiles.iterator();
}
}
} }

View File

@@ -59,7 +59,7 @@ public class Pathfinder implements Runnable{
Flowfield[][][] cache; Flowfield[][][] cache;
/** tile data, see PathTileStruct */ /** tile data, see PathTileStruct */
int[][] tiles; int[][] tiles = new int[0][0];
/** unordered array of path data for iteration only. DO NOT iterate or access this in the main thread. */ /** unordered array of path data for iteration only. DO NOT iterate or access this in the main thread. */
Seq<Flowfield> threadList = new Seq<>(), mainList = new Seq<>(); Seq<Flowfield> threadList = new Seq<>(), mainList = new Seq<>();
/** handles task scheduling on the update thread. */ /** handles task scheduling on the update thread. */

View File

@@ -1,7 +1,6 @@
package mindustry.ai.types; package mindustry.ai.types;
import arc.math.*; import arc.math.*;
import arc.util.*;
import mindustry.entities.units.*; import mindustry.entities.units.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.world.meta.*; import mindustry.world.meta.*;
@@ -59,7 +58,7 @@ public class FlyingAI extends AIController{
vec.setAngle(Mathf.slerpDelta(unit.vel().angle(), vec.angle(), 0.6f)); vec.setAngle(Mathf.slerpDelta(unit.vel().angle(), vec.angle(), 0.6f));
} }
vec.setLength(unit.type().speed * Time.delta); vec.setLength(unit.type().speed);
unit.moveAt(vec); unit.moveAt(vec);
} }

View File

@@ -58,6 +58,7 @@ public class FormationAI extends AIController implements FormationMember{
public void removed(Unit unit){ public void removed(Unit unit){
if(formation != null){ if(formation != null){
formation.removeMember(this); formation.removeMember(this);
unit.resetController();
} }
} }

View File

@@ -49,10 +49,10 @@ public class GroundAI extends AIController{
unit.elevation = Mathf.approachDelta(unit.elevation, 0f, 0.08f); unit.elevation = Mathf.approachDelta(unit.elevation, 0f, 0.08f);
} }
if(!Units.invalidateTarget(target, unit, unit.range())){ if(!Units.invalidateTarget(target, unit, unit.range()) && unit.type().rotateShooting){
if(unit.type().hasWeapons()){ if(unit.type().hasWeapons()){
//TODO certain units should not look at the target, e.g. ships //TODO certain units should not look at the target, e.g. ships
unit.aimLook(Predict.intercept(unit, target, unit.type().weapons.first().bullet.speed)); unit.lookAt(Predict.intercept(unit, target, unit.type().weapons.first().bullet.speed));
} }
}else if(unit.moving()){ }else if(unit.moving()){
unit.lookAt(unit.vel().angle()); unit.lookAt(unit.vel().angle());

View File

@@ -12,8 +12,8 @@ public class RepairAI extends AIController{
boolean shoot = false; boolean shoot = false;
if(target != null){ if(target != null){
if(!target.within(unit, unit.type().range)){ if(!target.within(unit, unit.type().range * 0.8f)){
moveTo(target, unit.type().range * 0.9f); moveTo(target, unit.type().range * 0.8f);
}else{ }else{
unit.aim(target); unit.aim(target);
shoot = true; shoot = true;

View File

@@ -35,6 +35,7 @@ public class PhysicsProcess implements AsyncProcess{
refs.removeAll(ref -> { refs.removeAll(ref -> {
if(!ref.entity.isAdded()){ if(!ref.entity.isAdded()){
physics.destroyBody(ref.body); physics.destroyBody(ref.body);
ref.entity.physref(null);
return true; return true;
} }
return false; return false;

View File

@@ -34,7 +34,7 @@ public class Blocks implements ContentList{
public static Block public static Block
//environment //environment
air, spawn, cliff, deepwater, water, taintedWater, tar, slag, stone, craters, charr, sand, darksand, dirt, ice, snow, darksandTaintedWater, air, spawn, cliff, deepwater, water, taintedWater, tar, slag, stone, craters, charr, sand, darksand, dirt, mud, ice, snow, darksandTaintedWater,
dacite, stoneWall, dirtWall, sporeWall, iceWall, daciteWall, sporePine, snowPine, pine, shrubs, whiteTree, whiteTreeDead, sporeCluster, dacite, stoneWall, dirtWall, sporeWall, iceWall, daciteWall, sporePine, snowPine, pine, shrubs, whiteTree, whiteTreeDead, sporeCluster,
iceSnow, sandWater, darksandWater, duneWall, sandWall, moss, sporeMoss, shale, shaleWall, shaleBoulder, sandBoulder, daciteBoulder, grass, salt, iceSnow, sandWater, darksandWater, duneWall, sandWall, moss, sporeMoss, shale, shaleWall, shaleBoulder, sandBoulder, daciteBoulder, grass, salt,
metalFloor, metalFloorDamaged, metalFloor2, metalFloor3, metalFloor5, basalt, magmarock, hotrock, snowWall, boulder, snowBoulder, saltWall, metalFloor, metalFloorDamaged, metalFloor2, metalFloor3, metalFloor5, basalt, magmarock, hotrock, snowWall, boulder, snowBoulder, saltWall,
@@ -260,6 +260,16 @@ public class Blocks implements ContentList{
dirt = new Floor("dirt"); dirt = new Floor("dirt");
mud = new Floor("mud"){{
speedMultiplier = 0.6f;
variants = 3;
status = StatusEffects.muddy;
statusDuration = 30f;
attributes.set(Attribute.water, 2f);
cacheLayer = CacheLayer.mud;
albedo = 0.35f;
}};
((ShallowLiquid)darksandTaintedWater).set(Blocks.taintedWater, Blocks.darksand); ((ShallowLiquid)darksandTaintedWater).set(Blocks.taintedWater, Blocks.darksand);
((ShallowLiquid)sandWater).set(Blocks.water, Blocks.sand); ((ShallowLiquid)sandWater).set(Blocks.water, Blocks.sand);
((ShallowLiquid)darksandWater).set(Blocks.water, Blocks.darksand); ((ShallowLiquid)darksandWater).set(Blocks.water, Blocks.darksand);
@@ -327,7 +337,7 @@ public class Blocks implements ContentList{
duneWall = new StaticWall("dune-wall"){{ duneWall = new StaticWall("dune-wall"){{
variants = 2; variants = 2;
basalt.asFloor().wall = this; basalt.asFloor().wall = darksandWater.asFloor().wall = darksandTaintedWater.asFloor().wall = this;
}}; }};
sandWall = new StaticWall("sand-wall"){{ sandWall = new StaticWall("sand-wall"){{
@@ -1011,7 +1021,7 @@ public class Blocks implements ContentList{
mechanicalPump = new Pump("mechanical-pump"){{ mechanicalPump = new Pump("mechanical-pump"){{
requirements(Category.liquid, with(Items.copper, 15, Items.metaglass, 10)); requirements(Category.liquid, with(Items.copper, 15, Items.metaglass, 10));
pumpAmount = 0.1f; pumpAmount = 0.11f;
}}; }};
rotaryPump = new Pump("rotary-pump"){{ rotaryPump = new Pump("rotary-pump"){{
@@ -1136,7 +1146,7 @@ public class Blocks implements ContentList{
requirements(Category.power, with(Items.copper, 35, Items.graphite, 25, Items.lead, 40, Items.silicon, 30)); requirements(Category.power, with(Items.copper, 35, Items.graphite, 25, Items.lead, 40, Items.silicon, 30));
powerProduction = 5.5f; powerProduction = 5.5f;
itemDuration = 90f; itemDuration = 90f;
consumes.liquid(Liquids.water, 0.06f); consumes.liquid(Liquids.water, 0.07f);
hasLiquids = true; hasLiquids = true;
size = 2; size = 2;
}}; }};
@@ -1269,7 +1279,7 @@ public class Blocks implements ContentList{
hasItems = true; hasItems = true;
consumes.power(0.80f); consumes.power(0.80f);
consumes.liquid(Liquids.water, 0.18f); consumes.liquid(Liquids.water, 0.2f);
}}; }};
oilExtractor = new Fracker("oil-extractor"){{ oilExtractor = new Fracker("oil-extractor"){{
@@ -1645,7 +1655,7 @@ public class Blocks implements ContentList{
}}; }};
spectre = new ItemTurret("spectre"){{ spectre = new ItemTurret("spectre"){{
requirements(Category.turret, with(Items.copper, 350, Items.graphite, 300, Items.surgealloy, 250, Items.plastanium, 175, Items.thorium, 250)); requirements(Category.turret, with(Items.copper, 900, Items.graphite, 300, Items.surgealloy, 250, Items.plastanium, 175, Items.thorium, 250));
ammo( ammo(
Items.graphite, Bullets.standardDenseBig, Items.graphite, Bullets.standardDenseBig,
Items.pyratite, Bullets.standardIncendiaryBig, Items.pyratite, Bullets.standardIncendiaryBig,
@@ -1671,7 +1681,7 @@ public class Blocks implements ContentList{
}}; }};
meltdown = new LaserTurret("meltdown"){{ meltdown = new LaserTurret("meltdown"){{
requirements(Category.turret, with(Items.copper, 250, Items.lead, 350, Items.graphite, 300, Items.surgealloy, 325, Items.silicon, 325)); requirements(Category.turret, with(Items.copper, 1200, Items.lead, 350, Items.graphite, 300, Items.surgealloy, 325, Items.silicon, 325));
shootEffect = Fx.shootBigSmoke2; shootEffect = Fx.shootBigSmoke2;
shootCone = 40f; shootCone = 40f;
recoilAmount = 4f; recoilAmount = 4f;
@@ -1793,6 +1803,7 @@ public class Blocks implements ContentList{
{UnitTypes.zenith, UnitTypes.antumbra}, {UnitTypes.zenith, UnitTypes.antumbra},
{UnitTypes.spiroct, UnitTypes.arkyid}, {UnitTypes.spiroct, UnitTypes.arkyid},
{UnitTypes.fortress, UnitTypes.scepter}, {UnitTypes.fortress, UnitTypes.scepter},
{UnitTypes.bryde, UnitTypes.sei},
}; };
}}; }};
@@ -1811,6 +1822,7 @@ public class Blocks implements ContentList{
{UnitTypes.antumbra, UnitTypes.eclipse}, {UnitTypes.antumbra, UnitTypes.eclipse},
{UnitTypes.arkyid, UnitTypes.toxopid}, {UnitTypes.arkyid, UnitTypes.toxopid},
{UnitTypes.scepter, UnitTypes.reign}, {UnitTypes.scepter, UnitTypes.reign},
{UnitTypes.sei, UnitTypes.omura}
}; };
}}; }};

View File

@@ -269,13 +269,13 @@ public class Bullets implements ContentList{
status = StatusEffects.burning; status = StatusEffects.burning;
}}; }};
missileSurge = new MissileBulletType(3.7f, 20){{ missileSurge = new MissileBulletType(3.7f, 18){{
width = 8f; width = 8f;
height = 8f; height = 8f;
shrinkY = 0f; shrinkY = 0f;
drag = -0.01f; drag = -0.01f;
splashDamageRadius = 28f; splashDamageRadius = 25f;
splashDamage = 35f; splashDamage = 25f;
hitEffect = Fx.blastExplosion; hitEffect = Fx.blastExplosion;
despawnEffect = Fx.blastExplosion; despawnEffect = Fx.blastExplosion;
lightning = 2; lightning = 2;

View File

@@ -687,6 +687,13 @@ public class Fx{
Fill.circle(e.x, e.y, e.fout() * 1f); Fill.circle(e.x, e.y, e.fout() * 1f);
}), }),
muddy = new Effect(80f, e -> {
color(Color.valueOf("432722"));
alpha(Mathf.clamp(e.fin() * 2f));
Fill.circle(e.x, e.y, e.fout() * 1f);
}),
sapped = new Effect(40f, e -> { sapped = new Effect(40f, e -> {
color(Pal.sap); color(Pal.sap);
@@ -989,6 +996,53 @@ public class Fx{
}).ground(400f), }).ground(400f),
railShoot = new Effect(24f, e -> {
e.scaled(10f, b -> {
color(Color.white, Color.lightGray, b.fin());
stroke(b.fout() * 3f + 0.2f);
Lines.circle(b.x, b.y, b.fin() * 50f);
});
color(Pal.orangeSpark);
for(int i : Mathf.signs){
Drawf.tri(e.x, e.y, 13f * e.fout(), 85f, e.rotation + 90f * i);
}
}),
railTrail = new Effect(16f, e -> {
color(Pal.orangeSpark);
for(int i : Mathf.signs){
Drawf.tri(e.x, e.y, 10f * e.fout(), 24f, e.rotation + 90 + 90f * i);
}
}),
railHit = new Effect(18f, 200f, e -> {
if(true){
color(Pal.orangeSpark);
for(int i : Mathf.signs){
Drawf.tri(e.x, e.y, 10f * e.fout(), 60f, e.rotation + 140f * i);
}
}else{
e.scaled(7f, b -> {
color(Color.white, Color.lightGray, b.fin());
stroke(b.fout() * 2f + 0.2f);
Lines.circle(b.x, b.y, b.fin() * 28f);
});
color(Pal.orangeSpark);
float rot = e.rotation + Mathf.randomSeedRange(e.id, 20f);
float w = 9f * e.fout();
Drawf.tri(e.x, e.y, w, 100f, rot);
Drawf.tri(e.x, e.y, w, 10f, rot + 180f);
}
}),
lancerLaserShoot = new Effect(21f, e -> { lancerLaserShoot = new Effect(21f, e -> {
color(Pal.lancerLaser); color(Pal.lancerLaser);
@@ -1000,7 +1054,7 @@ public class Fx{
lancerLaserShootSmoke = new Effect(26f, e -> { lancerLaserShootSmoke = new Effect(26f, e -> {
color(Color.white); color(Color.white);
float length = e.data == null ? 70f : (Float)e.data; float length = e.data == null || !(e.data instanceof Float) ? 70f : (Float)e.data;
randLenVectors(e.id, 7, length, e.rotation, 0f, (x, y) -> { randLenVectors(e.id, 7, length, e.rotation, 0f, (x, y) -> {
lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), e.fout() * 9f); lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), e.fout() * 9f);
@@ -1070,6 +1124,15 @@ public class Fx{
}); });
}), }),
cloudsmoke = new Effect(70, e -> {
randLenVectors(e.id, 12, 15f + e.fin() * 45f, (x, y) -> {
float size = e.fslope() * 2f;
color(Color.gray);
alpha(e.fslope());
Fill.circle(e.x + x, e.y + y, size);
});
}),
nuclearcloud = new Effect(90, 200f, e -> { nuclearcloud = new Effect(90, 200f, e -> {
randLenVectors(e.id, 10, e.finpow() * 90f, (x, y) -> { randLenVectors(e.id, 10, e.finpow() * 90f, (x, y) -> {
float size = e.fout() * 14f; float size = e.fout() * 14f;
@@ -1295,10 +1358,11 @@ public class Fx{
}), }),
//TODO fix false in constructor
ripple = new Effect(30, e -> { ripple = new Effect(30, e -> {
e.lifetime = 30f*e.rotation;
color(Tmp.c1.set(e.color).mul(1.5f)); color(Tmp.c1.set(e.color).mul(1.5f));
stroke(e.fout() + 0.4f); stroke(e.fout() * 1.4f);
Lines.circle(e.x, e.y, (2f + e.fin() * 4f) * e.rotation); Lines.circle(e.x, e.y, (2f + e.fin() * 4f) * e.rotation);
}).ground(), }).ground(),

View File

@@ -9,7 +9,7 @@ import mindustry.type.StatusEffect;
import static mindustry.Vars.*; import static mindustry.Vars.*;
public class StatusEffects implements ContentList{ public class StatusEffects implements ContentList{
public static StatusEffect none, burning, freezing, wet, melting, sapped, tarred, overdrive, overclock, shielded, shocked, blasted, corroded, boss, sporeSlowed; public static StatusEffect none, burning, freezing, wet, muddy, melting, sapped, tarred, overdrive, overclock, shielded, shocked, blasted, corroded, boss, sporeSlowed;
@Override @Override
public void load(){ public void load(){
@@ -63,6 +63,13 @@ public class StatusEffects implements ContentList{
}); });
}}; }};
muddy = new StatusEffect("muddy"){{
color = Color.valueOf("46382a");
speedMultiplier = 0.94f;
effect = Fx.muddy;
effectChance = 0.09f;
}};
melting = new StatusEffect("melting"){{ melting = new StatusEffect("melting"){{
speedMultiplier = 0.8f; speedMultiplier = 0.8f;
armorMultiplier = 0.8f; armorMultiplier = 0.8f;

View File

@@ -41,8 +41,8 @@ public class UnitTypes implements ContentList{
//air + building + mining //air + building + mining
public static @EntityDef({Unitc.class, Builderc.class, Minerc.class}) UnitType alpha, beta, gamma; public static @EntityDef({Unitc.class, Builderc.class, Minerc.class}) UnitType alpha, beta, gamma;
//water //water + commander
public static @EntityDef({Unitc.class, WaterMovec.class, Commanderc.class}) UnitType risso, minke, bryde; public static @EntityDef({Unitc.class, WaterMovec.class, Commanderc.class}) UnitType risso, minke, bryde, sei, omura;
//special block unit type //special block unit type
public static @EntityDef({Unitc.class, BlockUnitc.class}) UnitType block; public static @EntityDef({Unitc.class, BlockUnitc.class}) UnitType block;
@@ -61,6 +61,7 @@ public class UnitTypes implements ContentList{
reload = 14f; reload = 14f;
x = 4f; x = 4f;
y = 2f; y = 2f;
top = false;
ejectEffect = Fx.shellEjectSmall; ejectEffect = Fx.shellEjectSmall;
bullet = Bullets.standardCopper; bullet = Bullets.standardCopper;
}}); }});
@@ -75,6 +76,7 @@ public class UnitTypes implements ContentList{
immunities.add(StatusEffects.burning); immunities.add(StatusEffects.burning);
weapons.add(new Weapon("flamethrower"){{ weapons.add(new Weapon("flamethrower"){{
top = false;
shootSound = Sounds.flame; shootSound = Sounds.flame;
shootY = 2f; shootY = 2f;
reload = 14f; reload = 14f;
@@ -106,6 +108,7 @@ public class UnitTypes implements ContentList{
mechFrontSway = 0.55f; mechFrontSway = 0.55f;
weapons.add(new Weapon("artillery"){{ weapons.add(new Weapon("artillery"){{
top = false;
y = 1f; y = 1f;
x = 9f; x = 9f;
reload = 60f; reload = 60f;
@@ -142,6 +145,7 @@ public class UnitTypes implements ContentList{
weapons.add( weapons.add(
new Weapon("scepter-weapon"){{ new Weapon("scepter-weapon"){{
top = false;
y = 1f; y = 1f;
x = 16f; x = 16f;
shootY = 8f; shootY = 8f;
@@ -201,6 +205,7 @@ public class UnitTypes implements ContentList{
weapons.add( weapons.add(
new Weapon("reign-weapon"){{ new Weapon("reign-weapon"){{
top = false;
y = 1f; y = 1f;
x = 21.5f; x = 21.5f;
shootY = 11f; shootY = 11f;
@@ -259,6 +264,7 @@ public class UnitTypes implements ContentList{
abilities.add(new HealFieldAbility(10f, 60f * 4, 60f)); abilities.add(new HealFieldAbility(10f, 60f * 4, 60f));
weapons.add(new Weapon("heal-weapon"){{ weapons.add(new Weapon("heal-weapon"){{
top = false;
shootY = 2f; shootY = 2f;
reload = 24f; reload = 24f;
x = 4.5f; x = 4.5f;
@@ -274,7 +280,7 @@ public class UnitTypes implements ContentList{
itemCapacity = 60; itemCapacity = 60;
canBoost = true; canBoost = true;
boostMultiplier = 1.5f; boostMultiplier = 1.5f;
speed = 0.48f; speed = 0.62f;
hitsize = 10f; hitsize = 10f;
health = 320f; health = 320f;
buildSpeed = 0.9f; buildSpeed = 0.9f;
@@ -287,6 +293,7 @@ public class UnitTypes implements ContentList{
abilities.add(new ShieldFieldAbility(20f, 40f, 60f * 5, 60f)); abilities.add(new ShieldFieldAbility(20f, 40f, 60f * 5, 60f));
weapons.add(new Weapon("heal-shotgun-weapon"){{ weapons.add(new Weapon("heal-shotgun-weapon"){{
top = false;
x = 5f; x = 5f;
shake = 2.2f; shake = 2.2f;
y = 0.5f; y = 0.5f;
@@ -336,6 +343,7 @@ public class UnitTypes implements ContentList{
abilities.add(new ForceFieldAbility(60f, 0.3f, 400f, 60f * 6)); abilities.add(new ForceFieldAbility(60f, 0.3f, 400f, 60f * 6));
weapons.add(new Weapon("beam-weapon"){{ weapons.add(new Weapon("beam-weapon"){{
top = false;
shake = 2f; shake = 2f;
shootY = 4f; shootY = 4f;
x = 6.5f; x = 6.5f;
@@ -406,6 +414,7 @@ public class UnitTypes implements ContentList{
groundLayer = Layer.legUnit - 1f; groundLayer = Layer.legUnit - 1f;
weapons.add(new Weapon("eruption"){{ weapons.add(new Weapon("eruption"){{
top = false;
shootY = 3f; shootY = 3f;
reload = 10f; reload = 10f;
ejectEffect = Fx.none; ejectEffect = Fx.none;
@@ -668,8 +677,8 @@ public class UnitTypes implements ContentList{
width = height = 25f; width = height = 25f;
collidesTiles = collides = true; collidesTiles = collides = true;
ammoMultiplier = 4f; ammoMultiplier = 4f;
splashDamageRadius = 95f; splashDamageRadius = 90f;
splashDamage = 90f; splashDamage = 75f;
backColor = Pal.sapBulletBack; backColor = Pal.sapBulletBack;
frontColor = lightningColor = Pal.sapBullet; frontColor = lightningColor = Pal.sapBullet;
lightning = 5; lightning = 5;
@@ -690,7 +699,7 @@ public class UnitTypes implements ContentList{
width = height = 20f; width = height = 20f;
collidesTiles = false; collidesTiles = false;
splashDamageRadius = 80f; splashDamageRadius = 80f;
splashDamage = 45f; splashDamage = 40f;
backColor = Pal.sapBulletBack; backColor = Pal.sapBulletBack;
frontColor = lightningColor = Pal.sapBullet; frontColor = lightningColor = Pal.sapBullet;
lightning = 2; lightning = 2;
@@ -1125,6 +1134,7 @@ public class UnitTypes implements ContentList{
accel = 0.3f; accel = 0.3f;
rotateSpeed = 2.6f; rotateSpeed = 2.6f;
immunities = ObjectSet.with(StatusEffects.wet); immunities = ObjectSet.with(StatusEffects.wet);
rotateShooting = false;
trailLength = 20; trailLength = 20;
trailX = 5.5f; trailX = 5.5f;
@@ -1164,7 +1174,7 @@ public class UnitTypes implements ContentList{
accel = 0.2f; accel = 0.2f;
rotateSpeed = 1.8f; rotateSpeed = 1.8f;
drag = 0.17f; drag = 0.17f;
hitsize = 14f; hitsize = 16f;
armor = 6f; armor = 6f;
immunities = ObjectSet.with(StatusEffects.wet); immunities = ObjectSet.with(StatusEffects.wet);
rotateShooting = false; rotateShooting = false;
@@ -1186,7 +1196,7 @@ public class UnitTypes implements ContentList{
shootY = 7f; shootY = 7f;
shake = 5f; shake = 5f;
recoil = 4f; recoil = 4f;
occlusion = 17f; occlusion = 12f;
shots = 1; shots = 1;
inaccuracy = 3f; inaccuracy = 3f;
@@ -1252,6 +1262,142 @@ public class UnitTypes implements ContentList{
}}); }});
}}; }};
sei = new UnitType("sei"){{
health = 10000;
armor = 12f;
speed = 0.73f;
drag = 0.17f;
hitsize = 39f;
accel = 0.2f;
rotateSpeed = 1.3f;
immunities = ObjectSet.with(StatusEffects.wet);
rotateShooting = false;
trailLength = 50;
trailX = 18f;
trailY = -21f;
trailScl = 3f;
weapons.add(new Weapon("sei-launcher"){{
x = 0f;
y = 0f;
rotate = true;
rotateSpeed = 4f;
mirror = false;
occlusion = 20f;
shootY = 2f;
recoil = 4f;
reload = 45f;
shots = 6;
spacing = 10f;
velocityRnd = 0.4f;
inaccuracy = 7f;
ejectEffect = Fx.none;
shake = 3f;
shootSound = Sounds.shootBig;
xRand = 8f;
shotDelay = 1f;
bullet = new MissileBulletType(4.2f, 25){{
homingPower = 0.12f;
width = 8f;
height = 8f;
shrinkX = shrinkY = 0f;
drag = -0.003f;
homingRange = 80f;
keepVelocity = false;
splashDamageRadius = 25f;
splashDamage = 25f;
lifetime = 56f;
trailColor = Pal.bulletYellowBack;
backColor = Pal.bulletYellowBack;
frontColor = Pal.bulletYellow;
hitEffect = Fx.blastExplosion;
despawnEffect = Fx.blastExplosion;
weaveScale = 8f;
weaveMag = 2f;
}};
}});
weapons.add(new Weapon("large-bullet-mount"){{
reload = 80f;
cooldownTime = 90f;
x = 70f/4f;
y = -66f/4f;
rotateSpeed = 4f;
rotate = true;
shootY = 7f;
shake = 2f;
recoil = 3f;
occlusion = 12f;
ejectEffect = Fx.shellEjectBig;
shots = 3;
shotDelay = 4f;
inaccuracy = 1f;
bullet = new BasicBulletType(7f, 50){{
width = 13f;
height = 19f;
shootEffect = Fx.shootBig;
lifetime = 30f;
}};
}});
}};
omura = new UnitType("omura"){{
health = 22000;
speed = 0.62f;
drag = 0.18f;
hitsize = 50f;
armor = 16f;
accel = 0.19f;
rotateSpeed = 0.9f;
immunities = ObjectSet.with(StatusEffects.wet);
rotateShooting = false;
float spawnTime = 60f * 25f;
abilities.add(new UnitSpawnAbility(flare, spawnTime, 19.25f, -31.75f), new UnitSpawnAbility(flare, spawnTime, -19.25f, -31.75f));
trailLength = 70;
trailX = 23f;
trailY = -32f;
trailScl = 3.5f;
weapons.add(new Weapon("omura-cannon"){{
reload = 110f;
cooldownTime = 90f;
mirror = false;
x = 0f;
y = -3.5f;
rotateSpeed = 1.4f;
rotate = true;
shootY = 23f;
shake = 6f;
recoil = 10.5f;
occlusion = 50f;
shots = 1;
ejectEffect = Fx.none;
bullet = new RailBulletType(){{
shootEffect = Fx.railShoot;
speed = 67f;
lifetime = 8f;
pierceEffect = Fx.railHit;
updateEffect = Fx.railTrail;
hitEffect = Fx.massiveExplosion;
smokeEffect = Fx.shootBig2;
damage = 1250;
pierceDamageFactor = 0.5f;
}};
}});
}};
//endregion //endregion
//region core //region core
@@ -1276,6 +1422,7 @@ public class UnitTypes implements ContentList{
reload = 17f; reload = 17f;
x = 2.75f; x = 2.75f;
y = 1f; y = 1f;
top = false;
bullet = new BasicBulletType(2.5f, 9){{ bullet = new BasicBulletType(2.5f, 9){{
width = 7f; width = 7f;
@@ -1308,6 +1455,7 @@ public class UnitTypes implements ContentList{
lowAltitude = true; lowAltitude = true;
weapons.add(new Weapon("small-mount-weapon"){{ weapons.add(new Weapon("small-mount-weapon"){{
top = false;
reload = 20f; reload = 20f;
x = 3f; x = 3f;
y = 0.5f; y = 0.5f;
@@ -1345,6 +1493,7 @@ public class UnitTypes implements ContentList{
hitsize = 10f; hitsize = 10f;
weapons.add(new Weapon("small-mount-weapon"){{ weapons.add(new Weapon("small-mount-weapon"){{
top = false;
reload = 15f; reload = 15f;
x = 1f; x = 1f;
y = 2f; y = 2f;

View File

@@ -191,6 +191,10 @@ public class Control implements ApplicationListener, Loadable{
} }
void resetCamera(){
}
@Override @Override
public void loadAsync(){ public void loadAsync(){
Draw.scl = 1f / Core.atlas.find("scale_marker").width; Draw.scl = 1f / Core.atlas.find("scale_marker").width;
@@ -280,6 +284,7 @@ public class Control implements ApplicationListener, Loadable{
try{ try{
net.reset(); net.reset();
slot.load(); slot.load();
slot.setAutosave(true);
state.rules.sector = sector; state.rules.sector = sector;
//if there is no base, simulate a new game and place the right loadout at the spawn position //if there is no base, simulate a new game and place the right loadout at the spawn position

View File

@@ -17,7 +17,7 @@ public class GameState{
/** Wave countdown in ticks. */ /** Wave countdown in ticks. */
public float wavetime; public float wavetime;
/** Whether the game is in game over state. */ /** Whether the game is in game over state. */
public boolean gameOver = false, launched = false, serverPaused = false; public boolean gameOver = false, launched = false, serverPaused = false, wasTimeout;
/** Map that is currently being played on. */ /** Map that is currently being played on. */
public @NonNull Map map = emptyMap; public @NonNull Map map = emptyMap;
/** The current game rules. */ /** The current game rules. */

View File

@@ -337,7 +337,14 @@ public class Logic implements ApplicationListener{
//force pausing when the player is out of sector time //force pausing when the player is out of sector time
if(state.isOutOfTime()){ if(state.isOutOfTime()){
state.set(State.paused); if(!state.wasTimeout){
universe.displayTimeEnd();
state.wasTimeout = true;
}
//if no turn was run.
if(state.isOutOfTime()){
state.set(State.paused);
}
} }
if(!state.isPaused()){ if(!state.isPaused()){

View File

@@ -549,6 +549,10 @@ public class NetClient implements ApplicationListener{
quiet = true; quiet = true;
} }
public void clearRemovedEntity(int id){
removed.remove(id);
}
public void addRemovedEntity(int id){ public void addRemovedEntity(int id){
removed.add(id); removed.add(id);
} }

View File

@@ -593,38 +593,38 @@ public class NetServer implements ApplicationListener{
if(player.isBuilder()){ if(player.isBuilder()){
player.builder().clearBuilding(); player.builder().clearBuilding();
player.builder().updateBuilding(building); player.builder().updateBuilding(building);
if(requests != null){
for(BuildPlan req : requests){
if(req == null) continue;
Tile tile = world.tile(req.x, req.y);
if(tile == null || (!req.breaking && req.block == null)) continue;
//auto-skip done requests
if(req.breaking && tile.block() == Blocks.air){
continue;
}else if(!req.breaking && tile.block() == req.block && (!req.block.rotate || (tile.build != null && tile.build.rotation == req.rotation))){
continue;
}else if(con.rejectedRequests.contains(r -> r.breaking == req.breaking && r.x == req.x && r.y == req.y)){ //check if request was recently rejected, and skip it if so
continue;
}else if(!netServer.admins.allowAction(player, req.breaking ? ActionType.breakBlock : ActionType.placeBlock, tile, action -> { //make sure request is allowed by the server
action.block = req.block;
action.rotation = req.rotation;
action.config = req.config;
})){
//force the player to remove this request if that's not the case
Call.removeQueueBlock(player.con, req.x, req.y, req.breaking);
con.rejectedRequests.add(req);
continue;
}
player.builder().plans().addLast(req);
}
}
} }
if(player.isMiner()){ if(player.isMiner()){
player.miner().mineTile(mining); player.miner().mineTile(mining);
} }
if(requests != null){
for(BuildPlan req : requests){
if(req == null) continue;
Tile tile = world.tile(req.x, req.y);
if(tile == null || (!req.breaking && req.block == null)) continue;
//auto-skip done requests
if(req.breaking && tile.block() == Blocks.air){
continue;
}else if(!req.breaking && tile.block() == req.block && (!req.block.rotate || (tile.build != null && tile.build.rotation == req.rotation))){
continue;
}else if(con.rejectedRequests.contains(r -> r.breaking == req.breaking && r.x == req.x && r.y == req.y)){ //check if request was recently rejected, and skip it if so
continue;
}else if(!netServer.admins.allowAction(player, req.breaking ? ActionType.breakBlock : ActionType.placeBlock, tile, action -> { //make sure request is allowed by the server
action.block = req.block;
action.rotation = req.rotation;
action.config = req.config;
})){
//force the player to remove this request if that's not the case
Call.removeQueueBlock(player.con, req.x, req.y, req.breaking);
con.rejectedRequests.add(req);
continue;
}
player.builder().plans().addLast(req);
}
}
con.rejectedRequests.clear(); con.rejectedRequests.clear();
if(!player.dead()){ if(!player.dead()){

View File

@@ -5,11 +5,13 @@ import arc.func.*;
import arc.math.*; import arc.math.*;
import arc.math.geom.*; import arc.math.geom.*;
import arc.struct.*; import arc.struct.*;
import arc.struct.ObjectIntMap.*;
import arc.util.ArcAnnotate.*; import arc.util.ArcAnnotate.*;
import arc.util.*; import arc.util.*;
import arc.util.noise.*; import arc.util.noise.*;
import mindustry.content.*; import mindustry.content.*;
import mindustry.core.GameState.*; import mindustry.core.GameState.*;
import mindustry.ctype.*;
import mindustry.game.EventType.*; import mindustry.game.EventType.*;
import mindustry.game.*; import mindustry.game.*;
import mindustry.game.Teams.*; import mindustry.game.Teams.*;
@@ -19,7 +21,6 @@ import mindustry.maps.*;
import mindustry.maps.filters.*; import mindustry.maps.filters.*;
import mindustry.maps.filters.GenerateFilter.*; import mindustry.maps.filters.GenerateFilter.*;
import mindustry.type.*; import mindustry.type.*;
import mindustry.type.Sector.*;
import mindustry.type.Weather.*; import mindustry.type.Weather.*;
import mindustry.world.*; import mindustry.world.*;
import mindustry.world.blocks.environment.*; import mindustry.world.blocks.environment.*;
@@ -33,11 +34,17 @@ public class World{
public @NonNull Tiles tiles = new Tiles(0, 0); public @NonNull Tiles tiles = new Tiles(0, 0);
private boolean generating, invalidMap; private boolean generating, invalidMap;
private ObjectMap<Map, Runnable> customMapLoaders = new ObjectMap<>();
public World(){ public World(){
} }
/** Adds a custom handler function for loading a custom map - usually a generated one. */
public void addMapLoader(Map map, Runnable loader){
customMapLoaders.put(map, loader);
}
public boolean isInvalidMap(){ public boolean isInvalidMap(){
return invalidMap; return invalidMap;
} }
@@ -255,9 +262,71 @@ public class World{
state.rules.weather.clear(); state.rules.weather.clear();
if(sector.is(SectorAttribute.rainy)) state.rules.weather.add(new WeatherEntry(Weathers.rain)); //apply weather based on terrain
if(sector.is(SectorAttribute.snowy)) state.rules.weather.add(new WeatherEntry(Weathers.snow)); ObjectIntMap<Block> floorc = new ObjectIntMap<>();
if(sector.is(SectorAttribute.desert)) state.rules.weather.add(new WeatherEntry(Weathers.sandstorm)); ObjectSet<UnlockableContent> content = new ObjectSet<>();
float waterFloors = 0, totalFloors = 0;
for(Tile tile : world.tiles){
if(world.getDarkness(tile.x, tile.y) >= 3){
continue;
}
Liquid liquid = tile.floor().liquidDrop;
if(tile.floor().itemDrop != null) content.add(tile.floor().itemDrop);
if(tile.overlay().itemDrop != null) content.add(tile.overlay().itemDrop);
if(liquid != null) content.add(liquid);
if(!tile.block().isStatic()){
totalFloors ++;
if(liquid == Liquids.water){
waterFloors += tile.floor().isDeep() ? 1f : 0.7f;
}
floorc.increment(tile.floor());
if(tile.overlay() != Blocks.air){
floorc.increment(tile.overlay());
}
}
}
//sort counts in descending order
Seq<Entry<Block>> entries = floorc.entries().toArray();
entries.sort(e -> -e.value);
//remove all blocks occuring < 30 times - unimportant
entries.removeAll(e -> e.value < 30);
Block[] floors = new Block[entries.size];
int[] floorCounts = new int[entries.size];
for(int i = 0; i < entries.size; i++){
floorCounts[i] = entries.get(i).value;
floors[i] = entries.get(i).key;
}
//TODO bad code
boolean hasSnow = floors[0].name.contains("ice") || floors[0].name.contains("snow");
boolean hasRain = !hasSnow && floors[0].name.contains("water");
boolean hasDesert = !hasSnow && !hasRain && floors[0].name.contains("sand");
boolean hasSpores = floors[0].name.contains("spore") || floors[0].name.contains("moss") || floors[0].name.contains("tainted");
if(hasSnow){
state.rules.weather.add(new WeatherEntry(Weathers.snow));
}
if(hasRain){
state.rules.weather.add(new WeatherEntry(Weathers.rain));
}
if(hasDesert){
state.rules.weather.add(new WeatherEntry(Weathers.sandstorm));
}
if(hasSpores){
state.rules.weather.add(new WeatherEntry(Weathers.sporestorm));
}
state.secinfo.resources = content.asArray();
state.secinfo.resources.sort(Structs.comps(Structs.comparing(Content::getContentType), Structs.comparingInt(c -> c.id)));
} }
@@ -270,6 +339,12 @@ public class World{
} }
public void loadMap(Map map, Rules checkRules){ public void loadMap(Map map, Rules checkRules){
//load using custom loader if possible
if(customMapLoaders.containsKey(map)){
customMapLoaders.get(map).run();
return;
}
try{ try{
SaveIO.load(map.file, new FilterContext(map)); SaveIO.load(map.file, new FilterContext(map));
}catch(Throwable e){ }catch(Throwable e){

View File

@@ -20,7 +20,7 @@ public class EditorTile extends Tile{
@Override @Override
public void setFloor(@NonNull Floor type){ public void setFloor(@NonNull Floor type){
if(state.isGame()){ if(skip()){
super.setFloor(type); super.setFloor(type);
return; return;
} }
@@ -41,20 +41,25 @@ public class EditorTile extends Tile{
@Override @Override
public void setBlock(Block type, Team team, int rotation){ public void setBlock(Block type, Team team, int rotation){
if(state.isGame()){ if(skip()){
super.setBlock(type, team, rotation); super.setBlock(type, team, rotation);
return; return;
} }
op(OpType.block, block.id); //if(this.block == type && (build == null || build.rotation == rotation)){
// ui.editor.editor.renderer().updatePoint(x, y);
// return;
//}
if(rotation != 0) op(OpType.rotation, (byte)rotation); if(rotation != 0) op(OpType.rotation, (byte)rotation);
if(team() != Team.derelict) op(OpType.team, (byte)team().id); if(team() != Team.derelict) op(OpType.team, (byte)team().id);
op(OpType.block, block.id);
super.setBlock(type, team, rotation); super.setBlock(type, team, rotation);
} }
@Override @Override
public void setTeam(Team team){ public void setTeam(Team team){
if(state.isGame()){ if(skip()){
super.setTeam(team); super.setTeam(team);
return; return;
} }
@@ -66,7 +71,7 @@ public class EditorTile extends Tile{
@Override @Override
public void setOverlay(Block overlay){ public void setOverlay(Block overlay){
if(state.isGame()){ if(skip()){
super.setOverlay(overlay); super.setOverlay(overlay);
return; return;
} }
@@ -79,7 +84,7 @@ public class EditorTile extends Tile{
@Override @Override
protected void fireChanged(){ protected void fireChanged(){
if(state.isGame()){ if(skip()){
super.fireChanged(); super.fireChanged();
}else{ }else{
ui.editor.editor.renderer().updatePoint(x, y); ui.editor.editor.renderer().updatePoint(x, y);
@@ -88,14 +93,14 @@ public class EditorTile extends Tile{
@Override @Override
public void recache(){ public void recache(){
if(state.isGame()){ if(skip()){
super.recache(); super.recache();
} }
} }
@Override @Override
protected void changeEntity(Team team, Prov<Building> entityprov, int rotation){ protected void changeEntity(Team team, Prov<Building> entityprov, int rotation){
if(state.isGame()){ if(skip()){
super.changeEntity(team, entityprov, rotation); super.changeEntity(team, entityprov, rotation);
return; return;
} }
@@ -116,6 +121,10 @@ public class EditorTile extends Tile{
} }
} }
private boolean skip(){
return state.isGame() || ui.editor.editor.isLoading();
}
private void op(OpType type, short value){ private void op(OpType type, short value){
ui.editor.editor.addTileOp(TileOp.get(x, y, (byte)type.ordinal(), value)); ui.editor.editor.addTileOp(TileOp.get(x, y, (byte)type.ordinal(), value));
} }

View File

@@ -17,7 +17,7 @@ public enum EditorTool{
if(!Structs.inBounds(x, y, editor.width(), editor.height())) return; if(!Structs.inBounds(x, y, editor.width(), editor.height())) return;
Tile tile = editor.tile(x, y); Tile tile = editor.tile(x, y);
editor.drawBlock = tile.block() == Blocks.air ? tile.overlay() == Blocks.air ? tile.floor() : tile.overlay() : tile.block(); editor.drawBlock = tile.block() == Blocks.air || !tile.block().inEditor ? tile.overlay() == Blocks.air ? tile.floor() : tile.overlay() : tile.block();
} }
}, },
line(KeyCode.l, "replace", "orthogonal"){ line(KeyCode.l, "replace", "orthogonal"){

View File

@@ -31,6 +31,10 @@ public class MapEditor{
public Block drawBlock = Blocks.stone; public Block drawBlock = Blocks.stone;
public Team drawTeam = Team.sharded; public Team drawTeam = Team.sharded;
public boolean isLoading(){
return loading;
}
public StringMap getTags(){ public StringMap getTags(){
return tags; return tags;
} }
@@ -52,7 +56,7 @@ public class MapEditor{
if(map.file.parent().parent().name().equals("1127400") && steam){ if(map.file.parent().parent().name().equals("1127400") && steam){
tags.put("steamid", map.file.parent().name()); tags.put("steamid", map.file.parent().name());
} }
MapIO.loadMap(map, context); load(() -> MapIO.loadMap(map, context));
renderer.resize(width(), height()); renderer.resize(width(), height());
loading = false; loading = false;
} }
@@ -227,8 +231,14 @@ public class MapEditor{
int px = offsetX + x, py = offsetY + y; int px = offsetX + x, py = offsetY + y;
if(previous.in(px, py)){ if(previous.in(px, py)){
tiles.set(x, y, previous.getn(px, py)); tiles.set(x, y, previous.getn(px, py));
tiles.getn(x, y).x = (short)x; Tile tile = tiles.getn(x, y);
tiles.getn(x, y).y = (short)y; tile.x = (short)x;
tile.y = (short)y;
if(tile.build != null && tile.isCenter()){
tile.build.x = x * tilesize + tile.block().offset;
tile.build.y = y * tilesize + tile.block().offset;
}
}else{ }else{
tiles.set(x, y, new EditorTile(x, y, Blocks.stone.id, (short)0, (short)0)); tiles.set(x, y, new EditorTile(x, y, Blocks.stone.id, (short)0, (short)0));
} }

View File

@@ -116,7 +116,7 @@ public class MapRenderer implements Disposable{
wx * tilesize + wall.offset + (tilesize - width) / 2f, wx * tilesize + wall.offset + (tilesize - width) / 2f,
wy * tilesize + wall.offset + (tilesize - height) / 2f, wy * tilesize + wall.offset + (tilesize - height) / 2f,
width, height, width, height,
tile.build == null || !wall.rotate ? 0 : tile.build.rotdeg() - 90); tile.build == null || !wall.rotate ? 0 : tile.build.rotdeg());
}else{ }else{
region = floor.editorVariantRegions()[Mathf.randomSeed(idxWall, 0, floor.editorVariantRegions().length - 1)]; region = floor.editorVariantRegions()[Mathf.randomSeed(idxWall, 0, floor.editorVariantRegions().length - 1)];

View File

@@ -86,12 +86,14 @@ public class Effect{
create(this, x, y, rotation, Color.white, data); create(this, x, y, rotation, Color.white, data);
} }
public void render(int id, Color color, float life, float rotation, float x, float y, Object data){ public float render(int id, Color color, float life, float lifetime, float rotation, float x, float y, Object data){
container.set(id, color, life, lifetime, rotation, x, y, data); container.set(id, color, life, lifetime, rotation, x, y, data);
Draw.z(ground ? Layer.debris : Layer.effect); Draw.z(ground ? Layer.debris : Layer.effect);
Draw.reset(); Draw.reset();
renderer.get(container); renderer.get(container);
Draw.reset(); Draw.reset();
return container.lifetime;
} }
public static @Nullable Effect get(int id){ public static @Nullable Effect get(int id){
@@ -125,13 +127,13 @@ public class Effect{
if(view.overlaps(pos)){ if(view.overlaps(pos)){
EffectState entity = EffectState.create(); EffectState entity = EffectState.create();
entity.effect(effect); entity.effect = effect;
entity.rotation(rotation); entity.rotation = rotation;
entity.data(data); entity.data = (data);
entity.lifetime(effect.lifetime); entity.lifetime = (effect.lifetime);
entity.set(x, y); entity.set(x, y);
entity.color().set(color); entity.color.set(color);
if(data instanceof Posc) entity.parent((Posc)data); if(data instanceof Posc) entity.parent = ((Posc)data);
entity.add(); entity.add();
} }
} }

View File

@@ -2,7 +2,16 @@ package mindustry.entities.abilities;
import mindustry.gen.*; import mindustry.gen.*;
public interface Ability{ public abstract class Ability implements Cloneable{
default void update(Unit unit){} public void update(Unit unit){}
default void draw(Unit unit){} public void draw(Unit unit){}
public Ability copy(){
try{
return (Ability)clone();
}catch(CloneNotSupportedException e){
//I am disgusted
throw new RuntimeException("java sucks", e);
}
}
} }

View File

@@ -11,7 +11,7 @@ import mindustry.content.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.graphics.*; import mindustry.graphics.*;
public class ForceFieldAbility implements Ability{ public class ForceFieldAbility extends Ability{
/** Shield radius. */ /** Shield radius. */
public float radius = 60f; public float radius = 60f;
/** Shield regen speed in damage/tick. */ /** Shield regen speed in damage/tick. */
@@ -21,18 +21,22 @@ public class ForceFieldAbility implements Ability{
/** Cooldown after the shield is broken, in ticks. */ /** Cooldown after the shield is broken, in ticks. */
public float cooldown = 60f * 5; public float cooldown = 60f * 5;
private float realRad; /** State: radius scaling. */
private Unit paramUnit; protected float radiusScale;
private final Cons<Shielderc> shieldConsumer = trait -> {
private static float realRad;
private static Unit paramUnit;
private static ForceFieldAbility paramField;
private static final Cons<Shielderc> shieldConsumer = trait -> {
if(trait.team() != paramUnit.team && Intersector.isInsideHexagon(paramUnit.x, paramUnit.y, realRad * 2f, trait.x(), trait.y()) && paramUnit.shield > 0){ if(trait.team() != paramUnit.team && Intersector.isInsideHexagon(paramUnit.x, paramUnit.y, realRad * 2f, trait.x(), trait.y()) && paramUnit.shield > 0){
trait.absorb(); trait.absorb();
Fx.absorb.at(trait); Fx.absorb.at(trait);
//break shield //break shield
if(paramUnit.shield <= trait.damage()){ if(paramUnit.shield <= trait.damage()){
paramUnit.shield -= cooldown * regen; paramUnit.shield -= paramField.cooldown * paramField.regen;
Fx.shieldBreak.at(paramUnit.x, paramUnit.y, radius, paramUnit.team.color); Fx.shieldBreak.at(paramUnit.x, paramUnit.y, paramField.radius, paramUnit.team.color);
} }
paramUnit.shield -= trait.damage(); paramUnit.shield -= trait.damage();
@@ -56,13 +60,14 @@ public class ForceFieldAbility implements Ability{
} }
if(unit.shield > 0){ if(unit.shield > 0){
unit.timer2 = Mathf.lerpDelta(unit.timer2, 1f, 0.06f); radiusScale = Mathf.lerpDelta(radiusScale, 1f, 0.06f);
paramUnit = unit; paramUnit = unit;
paramField = this;
checkRadius(unit); checkRadius(unit);
Groups.bullet.intersect(unit.x - realRad, unit.y - realRad, realRad * 2f, realRad * 2f, shieldConsumer); Groups.bullet.intersect(unit.x - realRad, unit.y - realRad, realRad * 2f, realRad * 2f, shieldConsumer);
}else{ }else{
unit.timer2 = 0f; radiusScale = 0f;
} }
} }
@@ -89,6 +94,6 @@ public class ForceFieldAbility implements Ability{
private void checkRadius(Unit unit){ private void checkRadius(Unit unit){
//timer2 is used to store radius scale as an effect //timer2 is used to store radius scale as an effect
realRad = unit.timer2 * radius; realRad = radiusScale * radius;
} }
} }

View File

@@ -5,12 +5,13 @@ import mindustry.content.*;
import mindustry.entities.*; import mindustry.entities.*;
import mindustry.gen.*; import mindustry.gen.*;
public class HealFieldAbility implements Ability{ public class HealFieldAbility extends Ability{
public float amount = 1, reload = 100, range = 60; public float amount = 1, reload = 100, range = 60;
public Effect healEffect = Fx.heal; public Effect healEffect = Fx.heal;
public Effect activeEffect = Fx.healWave; public Effect activeEffect = Fx.healWave;
private boolean wasHealed = false; protected float timer;
protected boolean wasHealed = false;
HealFieldAbility(){} HealFieldAbility(){}
@@ -22,9 +23,9 @@ public class HealFieldAbility implements Ability{
@Override @Override
public void update(Unit unit){ public void update(Unit unit){
unit.timer1 += Time.delta; timer += Time.delta;
if(unit.timer1 >= reload){ if(timer >= reload){
wasHealed = false; wasHealed = false;
Units.nearby(unit.team, unit.x, unit.y, range, other -> { Units.nearby(unit.team, unit.x, unit.y, range, other -> {
@@ -39,7 +40,7 @@ public class HealFieldAbility implements Ability{
activeEffect.at(unit); activeEffect.at(unit);
} }
unit.timer1 = 0f; timer = 0f;
} }
} }
} }

View File

@@ -5,12 +5,13 @@ import mindustry.content.*;
import mindustry.entities.*; import mindustry.entities.*;
import mindustry.gen.*; import mindustry.gen.*;
public class ShieldFieldAbility implements Ability{ public class ShieldFieldAbility extends Ability{
public float amount = 1, max = 100f, reload = 100, range = 60; public float amount = 1, max = 100f, reload = 100, range = 60;
public Effect applyEffect = Fx.shieldApply; public Effect applyEffect = Fx.shieldApply;
public Effect activeEffect = Fx.shieldWave; public Effect activeEffect = Fx.shieldWave;
private boolean applied = false; protected float timer;
protected boolean applied = false;
ShieldFieldAbility(){} ShieldFieldAbility(){}
@@ -23,9 +24,9 @@ public class ShieldFieldAbility implements Ability{
@Override @Override
public void update(Unit unit){ public void update(Unit unit){
unit.timer1 += Time.delta; timer += Time.delta;
if(unit.timer1 >= reload){ if(timer >= reload){
applied = false; applied = false;
Units.nearby(unit.team, unit.x, unit.y, range, other -> { Units.nearby(unit.team, unit.x, unit.y, range, other -> {
@@ -41,7 +42,7 @@ public class ShieldFieldAbility implements Ability{
activeEffect.at(unit); activeEffect.at(unit);
} }
unit.timer1 = 0f; timer = 0f;
} }
} }
} }

View File

@@ -7,12 +7,14 @@ import mindustry.entities.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.type.*; import mindustry.type.*;
public class StatusFieldAbility implements Ability{ public class StatusFieldAbility extends Ability{
public @NonNull StatusEffect effect; public @NonNull StatusEffect effect;
public float duration = 60, reload = 100, range = 20; public float duration = 60, reload = 100, range = 20;
public Effect applyEffect = Fx.heal; public Effect applyEffect = Fx.heal;
public Effect activeEffect = Fx.overdriveWave; public Effect activeEffect = Fx.overdriveWave;
protected float timer;
StatusFieldAbility(){} StatusFieldAbility(){}
public StatusFieldAbility(@NonNull StatusEffect effect, float duration, float reload, float range){ public StatusFieldAbility(@NonNull StatusEffect effect, float duration, float reload, float range){
@@ -24,9 +26,9 @@ public class StatusFieldAbility implements Ability{
@Override @Override
public void update(Unit unit){ public void update(Unit unit){
unit.timer2 += Time.delta; timer += Time.delta;
if(unit.timer2 >= reload){ if(timer >= reload){
Units.nearby(unit.team, unit.x, unit.y, range, other -> { Units.nearby(unit.team, unit.x, unit.y, range, other -> {
other.apply(effect, duration); other.apply(effect, duration);
@@ -34,7 +36,7 @@ public class StatusFieldAbility implements Ability{
activeEffect.at(unit); activeEffect.at(unit);
unit.timer2 = 0f; timer = 0f;
} }
} }
} }

View File

@@ -0,0 +1,60 @@
package mindustry.entities.abilities;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.util.ArcAnnotate.*;
import arc.util.*;
import mindustry.*;
import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.ui.*;
public class UnitSpawnAbility extends Ability{
public @NonNull UnitType type;
public float spawnTime = 60f, spawnX, spawnY;
public Effect spawnEffect = Fx.spawn;
protected float timer;
public UnitSpawnAbility(@NonNull UnitType type, float spawnTime, float spawnX, float spawnY){
this.type = type;
this.spawnTime = spawnTime;
this.spawnX = spawnX;
this.spawnY = spawnY;
}
public UnitSpawnAbility(){
}
@Override
public void update(Unit unit){
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);
u.set(x, y);
u.rotation = unit.rotation;
if(!Vars.net.client()){
u.add();
}
timer = 0f;
}
}
@Override
public void draw(Unit unit){
if(Units.canCreate(unit.team, type)){
Draw.draw(Draw.z(), () -> {
float x = unit.x + Angles.trnsx(unit.rotation, spawnY, spawnX), y = unit.y + Angles.trnsy(unit.rotation, spawnY, spawnX);
Drawf.construct(x, y, type.icon(Cicon.full), unit.rotation - 90, timer / spawnTime, 1f, timer);
});
}
}
}

View File

@@ -24,7 +24,7 @@ public abstract class BulletType extends Content{
public float hitSize = 4; public float hitSize = 4;
public float drawSize = 40f; public float drawSize = 40f;
public float drag = 0f; public float drag = 0f;
public boolean pierce; public boolean pierce, pierceBuilding;
public Effect hitEffect, despawnEffect; public Effect hitEffect, despawnEffect;
/** Effect created when shooting. */ /** Effect created when shooting. */
@@ -69,6 +69,8 @@ public abstract class BulletType extends Content{
public boolean scaleVelocity; public boolean scaleVelocity;
/** Whether this bullet can be hit by point defense. */ /** Whether this bullet can be hit by point defense. */
public boolean hittable = true; public boolean hittable = true;
/** Whether this bullet can be reflected. */
public boolean reflectable = true;
//additional effects //additional effects
@@ -131,10 +133,14 @@ public abstract class BulletType extends Content{
return true; return true;
} }
public void hitTile(Bullet b, Building tile){ public void hitTile(Bullet b, Building tile, float initialHealth){
hit(b); hit(b);
} }
public void hitEntity(Bullet b, Hitboxc other, float initialHealth){
}
public void hit(Bullet b){ public void hit(Bullet b){
hit(b, b.x, b.y); hit(b, b.x, b.y);
} }

View File

@@ -43,7 +43,7 @@ public class HealBulletType extends BulletType{
} }
@Override @Override
public void hitTile(Bullet b, Building tile){ public void hitTile(Bullet b, Building tile, float initialHealth){
super.hit(b); super.hit(b);
if(tile.team == b.team && !(tile.block instanceof ConstructBlock)){ if(tile.team == b.team && !(tile.block instanceof ConstructBlock)){

View File

@@ -0,0 +1,52 @@
package mindustry.entities.bullet;
import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
public class RailBulletType extends BulletType{
public Effect pierceEffect = Fx.hitBulletSmall, updateEffect = Fx.none;
/** Multiplier of damage decreased per health pierced. */
public float pierceDamageFactor = 1f;
public RailBulletType(){
pierceBuilding = true;
pierce = true;
reflectable = false;
hitEffect = Fx.none;
despawnEffect = Fx.none;
}
void handle(Bullet b, Posc pos, float initialHealth){
float sub = initialHealth*pierceDamageFactor;
if(sub >= b.damage){
//cause a despawn
b.remove();
}
//subtract health from each consecutive pierce
b.damage -= Math.min(b.damage, sub);
if(b.damage > 0){
pierceEffect.at(pos.getX(), pos.getY(), b.rotation());
}
hitEffect.at(pos.getX(), pos.getY());
}
@Override
public void update(Bullet b){
updateEffect.at(b.x, b.y, b.rotation());
}
@Override
public void hitEntity(Bullet b, Hitboxc entity, float initialHealth){
handle(b, entity, initialHealth);
}
@Override
public void hitTile(Bullet b, Building tile, float initialHealth){
handle(b, tile, initialHealth);
}
}

View File

@@ -39,10 +39,15 @@ public class SapBulletType extends BulletType{
Draw.reset(); Draw.reset();
Drawf.light(b.team, b.x, b.y, b.x + Tmp.v1.x, b.y + Tmp.v1.y, 15f * b.fout(), lightColor, 0.6f); Drawf.light(b.team, b.x, b.y, Tmp.v1.x, Tmp.v1.y, 15f * b.fout(), lightColor, 0.6f);
} }
} }
@Override
public void drawLight(Bullet b){
}
@Override @Override
public float range(){ public float range(){
return length; return length;

View File

@@ -108,9 +108,9 @@ abstract class BuilderComp implements Unitc{
ConstructBuild entity = tile.bc(); ConstructBuild entity = tile.bc();
if(current.breaking){ if(current.breaking){
entity.deconstruct(base(), core, 1f / entity.buildCost * Time.delta * type().buildSpeed * state.rules.buildSpeedMultiplier); entity.deconstruct(self(), core, 1f / entity.buildCost * Time.delta * type().buildSpeed * state.rules.buildSpeedMultiplier);
}else{ }else{
entity.construct(base(), core, 1f / entity.buildCost * Time.delta * type().buildSpeed * state.rules.buildSpeedMultiplier, current.config); entity.construct(self(), core, 1f / entity.buildCost * Time.delta * type().buildSpeed * state.rules.buildSpeedMultiplier, current.config);
} }
current.stuck = Mathf.equal(current.progress, entity.progress); current.stuck = Mathf.equal(current.progress, entity.progress);

View File

@@ -80,7 +80,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
if(block.hasPower){ if(block.hasPower){
//reinit power graph //reinit power graph
power.graph = new PowerGraph(); power.graph = new PowerGraph();
power.graph.add(base()); power.graph.add(self());
} }
} }
this.rotation = rotation; this.rotation = rotation;
@@ -94,7 +94,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
created(); created();
return base(); return self();
} }
/** Sets up all the necessary variables, but does not add this entity anywhere. */ /** Sets up all the necessary variables, but does not add this entity anywhere. */
@@ -111,17 +111,17 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
maxHealth(block.health); maxHealth(block.health);
timer(new Interval(block.timers)); timer(new Interval(block.timers));
cons = new ConsumeModule(base()); cons = new ConsumeModule(self());
if(block.hasItems) items = new ItemModule(); if(block.hasItems) items = new ItemModule();
if(block.hasLiquids) liquids = new LiquidModule(); if(block.hasLiquids) liquids = new LiquidModule();
if(block.hasPower){ if(block.hasPower){
power = new PowerModule(); power = new PowerModule();
power.graph.add(base()); power.graph.add(self());
} }
initialized = true; initialized = true;
return base(); return self();
} }
@Override @Override
@@ -195,17 +195,17 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
public void configure(Object value){ public void configure(Object value){
//save last used config //save last used config
block.lastConfig = value; block.lastConfig = value;
Call.tileConfig(player, base(), value); Call.tileConfig(player, self(), value);
} }
/** Configure from a server. */ /** Configure from a server. */
public void configureAny(Object value){ public void configureAny(Object value){
Call.tileConfig(null, base(), value); Call.tileConfig(null, self(), value);
} }
/** Deselect this tile from configuration. */ /** Deselect this tile from configuration. */
public void deselect(){ public void deselect(){
if(!headless && control.input.frag.config.getSelectedTile() == base()){ if(!headless && control.input.frag.config.getSelectedTile() == self()){
control.input.frag.config.hideConfig(); control.input.frag.config.hideConfig();
} }
} }
@@ -372,7 +372,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
/** Returns the amount of items this block can accept. */ /** Returns the amount of items this block can accept. */
public int acceptStack(Item item, int amount, Teamc source){ public int acceptStack(Item item, int amount, Teamc source){
if(acceptItem(base(), item) && block.hasItems && (source == null || source.team() == team)){ if(acceptItem(self(), item) && block.hasItems && (source == null || source.team() == team)){
return Math.min(getMaximumAccepted(item) - items.get(item), amount); return Math.min(getMaximumAccepted(item) - items.get(item), amount);
}else{ }else{
return 0; return 0;
@@ -425,8 +425,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
int trns = block.size/2 + 1; int trns = block.size/2 + 1;
Tile next = tile.getNearby(Geometry.d4(rotation).x * trns, Geometry.d4(rotation).y * trns); Tile next = tile.getNearby(Geometry.d4(rotation).x * trns, Geometry.d4(rotation).y * trns);
if(next != null && next.build != null && next.build.team == team && next.build.acceptPayload(base(), todump)){ if(next != null && next.build != null && next.build.team == team && next.build.acceptPayload(self(), todump)){
next.build.handlePayload(base(), todump); next.build.handlePayload(self(), todump);
return true; return true;
} }
@@ -446,8 +446,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
for(int i = 0; i < proximity.size; i++){ for(int i = 0; i < proximity.size; i++){
Building other = proximity.get((i + dump) % proximity.size); Building other = proximity.get((i + dump) % proximity.size);
if(other.team == team && other.acceptPayload(base(), todump)){ if(other.team == team && other.acceptPayload(self(), todump)){
other.handlePayload(base(), todump); other.handlePayload(self(), todump);
incrementDump(proximity.size); incrementDump(proximity.size);
return true; return true;
} }
@@ -480,7 +480,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
for(int i = 0; i < proximity.size; i++){ for(int i = 0; i < proximity.size; i++){
incrementDump(proximity.size); incrementDump(proximity.size);
Building other = proximity.get((i + dump) % proximity.size); Building other = proximity.get((i + dump) % proximity.size);
other = other.getLiquidDestination(base(), liquid); other = other.getLiquidDestination(self(), liquid);
if(other != null && other.team == team && other.block.hasLiquids && canDumpLiquid(other, liquid) && other.liquids != null){ if(other != null && other.team == team && other.block.hasLiquids && canDumpLiquid(other, liquid) && other.liquids != null){
float ofract = other.liquids.get(liquid) / other.block.liquidCapacity; float ofract = other.liquids.get(liquid) / other.block.liquidCapacity;
@@ -499,8 +499,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
public void transferLiquid(Building next, float amount, Liquid liquid){ public void transferLiquid(Building next, float amount, Liquid liquid){
float flow = Math.min(next.block.liquidCapacity - next.liquids.get(liquid) - 0.001f, amount); float flow = Math.min(next.block.liquidCapacity - next.liquids.get(liquid) - 0.001f, amount);
if(next.acceptLiquid(base(), liquid, flow)){ if(next.acceptLiquid(self(), liquid, flow)){
next.handleLiquid(base(), liquid, flow); next.handleLiquid(self(), liquid, flow);
liquids.remove(liquid, flow); liquids.remove(liquid, flow);
} }
} }
@@ -523,7 +523,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
public float moveLiquid(Building next, Liquid liquid){ public float moveLiquid(Building next, Liquid liquid){
if(next == null) return 0; if(next == null) return 0;
next = next.getLiquidDestination(base(), liquid); next = next.getLiquidDestination(self(), liquid);
if(next.team == team && next.block.hasLiquids && liquids.get(liquid) > 0f){ if(next.team == team && next.block.hasLiquids && liquids.get(liquid) > 0f){
float ofract = next.liquids.get(liquid) / next.block.liquidCapacity; float ofract = next.liquids.get(liquid) / next.block.liquidCapacity;
@@ -531,8 +531,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
float flow = Math.min(Mathf.clamp((fract - ofract) * (1f)) * (block.liquidCapacity), liquids.get(liquid)); float flow = Math.min(Mathf.clamp((fract - ofract) * (1f)) * (block.liquidCapacity), liquids.get(liquid));
flow = Math.min(flow, next.block.liquidCapacity - next.liquids.get(liquid) - 0.001f); flow = Math.min(flow, next.block.liquidCapacity - next.liquids.get(liquid) - 0.001f);
if(flow > 0f && ofract <= fract && next.acceptLiquid(base(), liquid, flow)){ if(flow > 0f && ofract <= fract && next.acceptLiquid(self(), liquid, flow)){
next.handleLiquid(base(), liquid, flow); next.handleLiquid(self(), liquid, flow);
liquids.remove(liquid, flow); liquids.remove(liquid, flow);
return flow; return flow;
}else if(next.liquids.currentAmount() / next.block.liquidCapacity > 0.1f && fract > 0.1f){ }else if(next.liquids.currentAmount() / next.block.liquidCapacity > 0.1f && fract > 0.1f){
@@ -558,7 +558,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
} }
public Building getLiquidDestination(Building from, Liquid liquid){ public Building getLiquidDestination(Building from, Liquid liquid){
return base(); return self();
} }
public @Nullable Payload getPayload(){ public @Nullable Payload getPayload(){
@@ -580,13 +580,13 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
for(int i = 0; i < proximity.size; i++){ for(int i = 0; i < proximity.size; i++){
incrementDump(proximity.size); incrementDump(proximity.size);
Building other = proximity.get((i + dump) % proximity.size); Building other = proximity.get((i + dump) % proximity.size);
if(other.team == team && other.acceptItem(base(), item) && canDump(other, item)){ if(other.team == team && other.acceptItem(self(), item) && canDump(other, item)){
other.handleItem(base(), item); other.handleItem(self(), item);
return; return;
} }
} }
handleItem(base(), item); handleItem(self(), item);
} }
/** /**
@@ -598,8 +598,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
for(int i = 0; i < proximity.size; i++){ for(int i = 0; i < proximity.size; i++){
incrementDump(proximity.size); incrementDump(proximity.size);
Building other = proximity.get((i + dump) % proximity.size); Building other = proximity.get((i + dump) % proximity.size);
if(other.team == team && other.acceptItem(base(), item) && canDump(other, item)){ if(other.team == team && other.acceptItem(self(), item) && canDump(other, item)){
other.handleItem(base(), item); other.handleItem(self(), item);
return true; return true;
} }
} }
@@ -631,16 +631,16 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
for(int ii = 0; ii < content.items().size; ii++){ for(int ii = 0; ii < content.items().size; ii++){
Item item = content.item(ii); Item item = content.item(ii);
if(other.team == team && items.has(item) && other.acceptItem(base(), item) && canDump(other, item)){ if(other.team == team && items.has(item) && other.acceptItem(self(), item) && canDump(other, item)){
other.handleItem(base(), item); other.handleItem(self(), item);
items.remove(item, 1); items.remove(item, 1);
incrementDump(proximity.size); incrementDump(proximity.size);
return true; return true;
} }
} }
}else{ }else{
if(other.team == team && other.acceptItem(base(), todump) && canDump(other, todump)){ if(other.team == team && other.acceptItem(self(), todump) && canDump(other, todump)){
other.handleItem(base(), todump); other.handleItem(self(), todump);
items.remove(todump, 1); items.remove(todump, 1);
incrementDump(proximity.size); incrementDump(proximity.size);
return true; return true;
@@ -665,8 +665,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
/** Try offloading an item to a nearby container in its facing direction. Returns true if success. */ /** Try offloading an item to a nearby container in its facing direction. Returns true if success. */
public boolean moveForward(Item item){ public boolean moveForward(Item item){
Building other = front(); Building other = front();
if(other != null && other.team == team && other.acceptItem(base(), item)){ if(other != null && other.team == team && other.acceptItem(self(), item)){
other.handleItem(base(), item); other.handleItem(self(), item);
return true; return true;
} }
return false; return false;
@@ -696,7 +696,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
return; return;
} }
power.graph.remove(base()); power.graph.remove(self());
for(int i = 0; i < power.links.size; i++){ for(int i = 0; i < power.links.size; i++){
Tile other = world.tile(power.links.get(i)); Tile other = world.tile(power.links.get(i));
if(other != null && other.build != null && other.build.power != null){ if(other != null && other.build != null && other.build.power != null){
@@ -833,8 +833,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
tempTiles.clear(); tempTiles.clear();
Geometry.circle(tileX(), tileY(), range, (x, y) -> { Geometry.circle(tileX(), tileY(), range, (x, y) -> {
Building other = world.build(x, y); Building other = world.build(x, y);
if(other != null && other.block instanceof PowerNode && ((PowerNode)other.block).linkValid(other, base()) && !PowerNode.insulated(other, base()) if(other != null && other.block instanceof PowerNode && ((PowerNode)other.block).linkValid(other, self()) && !PowerNode.insulated(other, self())
&& !other.proximity().contains(this.<Building>base()) && && !other.proximity().contains(this.<Building>self()) &&
!(block.outputsPower && proximity.contains(p -> p.power != null && p.power.graph == other.power.graph))){ !(block.outputsPower && proximity.contains(p -> p.power != null && p.power.graph == other.power.graph))){
tempTiles.add(other.tile); tempTiles.add(other.tile);
} }
@@ -1037,13 +1037,13 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
table.left(); table.left();
for(Consume cons : block.consumes.all()){ for(Consume cons : block.consumes.all()){
if(cons.isOptional() && cons.isBoost()) continue; if(cons.isOptional() && cons.isBoost()) continue;
cons.build(base(), table); cons.build(self(), table);
} }
} }
public void displayBars(Table table){ public void displayBars(Table table){
for(Func<Building, Bar> bar : block.bars.list()){ for(Func<Building, Bar> bar : block.bars.list()){
table.add(bar.get(base())).growX(); table.add(bar.get(self())).growX();
table.row(); table.row();
} }
} }
@@ -1069,7 +1069,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
* @return whether or not this block should be deselected. * @return whether or not this block should be deselected.
*/ */
public boolean onConfigureTileTapped(Building other){ public boolean onConfigureTileTapped(Building other){
return base() != other; return self() != other;
} }
/** Returns whether this config menu should show when the specified player taps it. */ /** Returns whether this config menu should show when the specified player taps it. */
@@ -1128,7 +1128,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
} }
for(Building other : tmpTiles){ for(Building other : tmpTiles){
other.proximity.remove(base(), true); other.proximity.remove(self(), true);
other.onProximityUpdate(); other.onProximityUpdate();
} }
} }
@@ -1144,8 +1144,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
if(other == null || !(other.tile.interactable(team))) continue; if(other == null || !(other.tile.interactable(team))) continue;
//add this tile to proximity of nearby tiles //add this tile to proximity of nearby tiles
if(!other.proximity.contains(base(), true)){ if(!other.proximity.contains(self(), true)){
other.proximity.add(base()); other.proximity.add(self());
} }
tmpTiles.add(other); tmpTiles.add(other);
@@ -1184,13 +1184,13 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
@Replace @Replace
@Override @Override
public boolean isValid(){ public boolean isValid(){
return tile.build == base() && !dead(); return tile.build == self() && !dead();
} }
@Replace @Replace
@Override @Override
public void kill(){ public void kill(){
Call.tileDestroyed(base()); Call.tileDestroyed(self());
} }
@Replace @Replace
@@ -1204,10 +1204,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
damage /= state.rules.blockHealthMultiplier; damage /= state.rules.blockHealthMultiplier;
} }
Call.tileDamage(base(), health - handleDamage(damage)); Call.tileDamage(self(), health - handleDamage(damage));
if(health <= 0){ if(health <= 0){
Call.tileDestroyed(base()); Call.tileDestroyed(self());
} }
} }
@@ -1292,7 +1292,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
} }
if(block.idleSound != Sounds.none && shouldIdleSound()){ if(block.idleSound != Sounds.none && shouldIdleSound()){
loops.play(block.idleSound, base(), block.idleSoundVolume); loops.play(block.idleSound, self(), block.idleSoundVolume);
} }
if(enabled || !block.noUpdateDisabled){ if(enabled || !block.noUpdateDisabled){

View File

@@ -44,17 +44,17 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
@Override @Override
public void drawBullets(){ public void drawBullets(){
type.draw(base()); type.draw(self());
} }
@Override @Override
public void add(){ public void add(){
type.init(base()); type.init(self());
} }
@Override @Override
public void remove(){ public void remove(){
type.despawned(base()); type.despawned(self());
collided.clear(); collided.clear();
} }
@@ -92,10 +92,12 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
@MethodPriority(100) @MethodPriority(100)
@Override @Override
public void collision(Hitboxc other, float x, float y){ public void collision(Hitboxc other, float x, float y){
type.hit(base(), x, y); type.hit(self(), x, y);
float health = 0f;
if(other instanceof Healthc){ if(other instanceof Healthc){
Healthc h = (Healthc)other; Healthc h = (Healthc)other;
health = h.health();
h.damage(damage); h.damage(damage);
} }
@@ -111,30 +113,40 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
}else{ }else{
collided.add(other.id()); collided.add(other.id());
} }
type.hitEntity(self(), other, health);
} }
@Override @Override
public void update(){ public void update(){
type.update(base()); type.update(self());
if(type.collidesTiles && type.collides && type.collidesGround){ if(type.collidesTiles && type.collides && type.collidesGround){
world.raycastEach(world.toTile(lastX()), world.toTile(lastY()), tileX(), tileY(), (x, y) -> { world.raycastEach(world.toTile(lastX()), world.toTile(lastY()), tileX(), tileY(), (x, y) -> {
Building tile = world.build(x, y); Building tile = world.build(x, y);
if(tile == null) return false; if(tile == null || !isAdded()) return false;
if(tile.collide(base()) && type.collides(base(), tile) && !tile.dead() && (type.collidesTeam || tile.team != team)){ if(tile.collide(self()) && type.collides(self(), tile) && !tile.dead() && (type.collidesTeam || tile.team != team) && !(type.pierceBuilding && collided.contains(tile.id))){
boolean remove = false; boolean remove = false;
float health = tile.health;
if(tile.team != team){ if(tile.team != team){
remove = tile.collision(base()); remove = tile.collision(self());
} }
if(remove || type.collidesTeam){ if(remove || type.collidesTeam){
type.hitTile(base(), tile); if(!type.pierceBuilding){
remove(); remove();
}else{
collided.add(tile.id);
}
} }
return true;
type.hitTile(self(), tile, health);
return !type.pierceBuilding;
} }
return false; return false;
@@ -146,8 +158,8 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
public void draw(){ public void draw(){
Draw.z(Layer.bullet); Draw.z(Layer.bullet);
type.draw(base()); type.draw(self());
type.drawLight(base()); type.drawLight(self());
} }
/** Sets the bullet's rotation in degrees. */ /** Sets the bullet's rotation in degrees. */

View File

@@ -59,7 +59,7 @@ abstract class CommanderComp implements Unitc{
units.clear(); units.clear();
Units.nearby(team(), x, y, 200f, u -> { Units.nearby(team(), x, y, 200f, u -> {
if(u.isAI() && include.get(u) && u != base()){ if(u.isAI() && include.get(u) && u != self()){
units.add(u); units.add(u);
} }
}); });
@@ -79,7 +79,7 @@ abstract class CommanderComp implements Unitc{
controlling.addAll(units); controlling.addAll(units);
for(Unit unit : units){ for(Unit unit : units){
FormationAI ai; FormationAI ai;
unit.controller(ai = new FormationAI(base(), formation)); unit.controller(ai = new FormationAI(self(), formation));
spacing = Math.max(spacing, ai.formationSize()); spacing = Math.max(spacing, ai.formationSize());
minFormationSpeed = Math.min(minFormationSpeed, unit.type().speed); minFormationSpeed = Math.min(minFormationSpeed, unit.type().speed);
} }
@@ -104,7 +104,7 @@ abstract class CommanderComp implements Unitc{
void clearCommand(){ void clearCommand(){
//reset controlled units //reset controlled units
for(Unit unit : controlling){ for(Unit unit : controlling){
if(unit.controller().isBeingControlled(base())){ if(unit.controller().isBeingControlled(self())){
unit.controller(unit.type().createController()); unit.controller(unit.type().createController());
} }
} }

View File

@@ -8,13 +8,16 @@ import mindustry.gen.*;
@EntityDef(value = {EffectStatec.class, Childc.class}, pooled = true, serialize = false) @EntityDef(value = {EffectStatec.class, Childc.class}, pooled = true, serialize = false)
@Component(base = true) @Component(base = true)
abstract class EffectStateComp implements Posc, Drawc, Timedc, Rotc, Childc{ abstract class EffectStateComp implements Posc, Drawc, Timedc, Rotc, Childc{
@Import float time, lifetime, rotation, x, y;
@Import int id;
Color color = new Color(Color.white); Color color = new Color(Color.white);
Effect effect; Effect effect;
Object data; Object data;
@Override @Override
public void draw(){ public void draw(){
effect.render(id(), color, time(), rotation(), x(), y(), data); lifetime = effect.render(id, color, time, lifetime, rotation, x, y, data);
} }
@Replace @Replace

View File

@@ -40,7 +40,7 @@ abstract class EntityComp{
return false; return false;
} }
<T extends Entityc> T base(){ <T extends Entityc> T self(){
return (T)this; return (T)this;
} }

View File

@@ -97,11 +97,11 @@ abstract class FireComp implements Timedc, Posc, Firec, Syncc{
@Override @Override
public void afterRead(){ public void afterRead(){
Fires.register(base()); Fires.register(self());
} }
@Override @Override
public void afterSync(){ public void afterSync(){
Fires.register(base()); Fires.register(self());
} }
} }

View File

@@ -74,7 +74,7 @@ abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{
} }
if(!hovering && isGrounded() && floor.isLiquid){ if(!hovering && isGrounded() && floor.isLiquid){
if((splashTimer += Mathf.dst(deltaX(), deltaY())) >= 7f){ if((splashTimer += Mathf.dst(deltaX(), deltaY())) >= (7f + hitSize()/8f)){
floor.walkEffect.at(x, y, hitSize() / 8f, floor.mapColor); floor.walkEffect.at(x, y, hitSize() / 8f, floor.mapColor);
splashTimer = 0f; splashTimer = 0f;
} }

View File

@@ -33,7 +33,7 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
} }
boolean mining(){ boolean mining(){
return mineTile != null; return mineTile != null && !(((Object)this) instanceof Builderc && ((Builderc)(Object)this).activelyBuilding());
} }
@Override @Override
@@ -51,13 +51,12 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
} }
if(mineTile == null || core == null || mineTile.block() != Blocks.air || dst(mineTile.worldx(), mineTile.worldy()) > miningRange if(mineTile == null || core == null || mineTile.block() != Blocks.air || dst(mineTile.worldx(), mineTile.worldy()) > miningRange
|| (((Object)this) instanceof Builderc && ((Builderc)(Object)this).activelyBuilding())
|| mineTile.drop() == null || !canMine(mineTile.drop())){ || mineTile.drop() == null || !canMine(mineTile.drop())){
mineTile = null; mineTile = null;
mineTimer = 0f; mineTimer = 0f;
}else{ }else if(mining()){
Item item = mineTile.drop(); Item item = mineTile.drop();
rotation(Mathf.slerpDelta(rotation(), angleTo(mineTile.worldx(), mineTile.worldy()), 0.4f)); rotation = Mathf.slerpDelta(rotation, angleTo(mineTile.worldx(), mineTile.worldy()), 0.4f);
mineTimer += Time.delta *type.mineSpeed; mineTimer += Time.delta *type.mineSpeed;
if(Mathf.chance(0.06 * Time.delta)){ if(Mathf.chance(0.06 * Time.delta)){

View File

@@ -48,6 +48,9 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
unit.remove(); unit.remove();
payloads.add(new UnitPayload(unit)); payloads.add(new UnitPayload(unit));
Fx.unitPickup.at(unit); Fx.unitPickup.at(unit);
if(Vars.net.client()){
Vars.netClient.clearRemovedEntity(unit.id);
}
} }
void pickup(Building tile){ void pickup(Building tile){
@@ -71,6 +74,11 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
boolean tryDropPayload(Payload payload){ boolean tryDropPayload(Payload payload){
Tile on = tileOn(); Tile on = tileOn();
//clear removed state of unit so it can be synced
if(Vars.net.client() && payload instanceof UnitPayload){
Vars.netClient.clearRemovedEntity(((UnitPayload)payload).unit.id);
}
//drop off payload on an acceptor if possible //drop off payload on an acceptor if possible
if(on != null && on.build != null && on.build.acceptPayload(on.build, payload)){ if(on != null && on.build != null && on.build.acceptPayload(on.build, payload)){
Fx.unitDrop.at(on.build); Fx.unitDrop.at(on.build);

View File

@@ -134,7 +134,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
deathTimer += Time.delta; deathTimer += Time.delta;
if(deathTimer >= deathDelay){ if(deathTimer >= deathDelay){
//request spawn - this happens serverside only //request spawn - this happens serverside only
core.requestSpawn(base()); core.requestSpawn(self());
deathTimer = 0; deathTimer = 0;
} }
} }
@@ -191,7 +191,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
} }
} }
Events.fire(new UnitChangeEvent(base(), unit)); Events.fire(new UnitChangeEvent(self(), unit));
} }
boolean dead(){ boolean dead(){

View File

@@ -128,6 +128,6 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{
@Override @Override
public void afterRead(){ public void afterRead(){
Puddles.register(base()); Puddles.register(self());
} }
} }

View File

@@ -42,7 +42,7 @@ abstract class StatusComp implements Posc, Flyingc{
return; return;
}else if(entry.effect.reactsWith(effect)){ //find opposite }else if(entry.effect.reactsWith(effect)){ //find opposite
StatusEntry.tmp.effect = entry.effect; StatusEntry.tmp.effect = entry.effect;
entry.effect.getTransition(base(), effect, entry.time, duration, StatusEntry.tmp); entry.effect.getTransition(self(), effect, entry.time, duration, StatusEntry.tmp);
entry.time = StatusEntry.tmp.time; entry.time = StatusEntry.tmp.time;
if(StatusEntry.tmp.effect != entry.effect){ if(StatusEntry.tmp.effect != entry.effect){
@@ -125,14 +125,14 @@ abstract class StatusComp implements Posc, Flyingc{
armorMultiplier *= entry.effect.armorMultiplier; armorMultiplier *= entry.effect.armorMultiplier;
damageMultiplier *= entry.effect.damageMultiplier; damageMultiplier *= entry.effect.damageMultiplier;
reloadMultiplier *= entry.effect.reloadMultiplier; reloadMultiplier *= entry.effect.reloadMultiplier;
entry.effect.update(base(), entry.time); entry.effect.update(self(), entry.time);
} }
} }
} }
public void draw(){ public void draw(){
for(StatusEntry e : statuses){ for(StatusEntry e : statuses){
e.effect.draw(base()); e.effect.draw(self());
} }
} }

View File

@@ -5,12 +5,14 @@ import arc.graphics.g2d.*;
import arc.math.*; import arc.math.*;
import arc.math.geom.*; import arc.math.geom.*;
import arc.scene.ui.layout.*; import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.ArcAnnotate.*; import arc.util.ArcAnnotate.*;
import arc.util.*; import arc.util.*;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;
import mindustry.content.*; import mindustry.content.*;
import mindustry.ctype.*; import mindustry.ctype.*;
import mindustry.entities.*; import mindustry.entities.*;
import mindustry.entities.abilities.*;
import mindustry.entities.units.*; import mindustry.entities.units.*;
import mindustry.game.EventType.*; import mindustry.game.EventType.*;
import mindustry.game.*; import mindustry.game.*;
@@ -37,7 +39,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
private UnitType type; private UnitType type;
boolean spawnedByCore, deactivated; boolean spawnedByCore, deactivated;
transient float timer1, timer2; transient Seq<Ability> abilities = new Seq<>(0);
public void moveAt(Vec2 vector){ public void moveAt(Vec2 vector){
moveAt(vector, type.accel); moveAt(vector, type.accel);
@@ -117,7 +119,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Override @Override
public void controller(UnitController next){ public void controller(UnitController next){
this.controller = next; this.controller = next;
if(controller.unit() != base()) controller.unit(base()); if(controller.unit() != self()) controller.unit(self());
} }
@Override @Override
@@ -171,7 +173,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
return Units.getCap(team); return Units.getCap(team);
} }
private void setStats(UnitType type){ public void setStats(UnitType type){
this.type = type; this.type = type;
this.maxHealth = type.health; this.maxHealth = type.health;
this.drag = type.drag; this.drag = type.drag;
@@ -181,13 +183,16 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
if(controller == null) controller(type.createController()); if(controller == null) controller(type.createController());
if(mounts().length != type.weapons.size) setupWeapons(type); if(mounts().length != type.weapons.size) setupWeapons(type);
if(abilities.size != type.abilities.size){
abilities = type.abilities.map(Ability::copy);
}
} }
@Override @Override
public void afterSync(){ public void afterSync(){
//set up type info after reading //set up type info after reading
setStats(this.type); setStats(this.type);
controller.unit(base()); controller.unit(self());
} }
@Override @Override
@@ -212,7 +217,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Override @Override
public void remove(){ public void remove(){
teamIndex.updateCount(team, type, -1); teamIndex.updateCount(team, type, -1);
controller.removed(base()); controller.removed(self());
} }
@Override @Override
@@ -221,7 +226,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
Effect.shake(type.landShake, type.landShake, this); Effect.shake(type.landShake, type.landShake, this);
} }
type.landed(base()); type.landed(self());
} }
@Override @Override
@@ -232,7 +237,15 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
deactivated = false; deactivated = false;
} }
if(!deactivated) type.update(base()); if(!deactivated){
type.update(self());
if(abilities.size > 0){
for(Ability a : abilities){
a.update(self());
}
}
}
drag = type.drag * (isGrounded() ? (floorOn().dragMultiplier) : 1f); drag = type.drag * (isGrounded() ? (floorOn().dragMultiplier) : 1f);
@@ -282,7 +295,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
if(tile != null && isGrounded() && !type.hovering){ if(tile != null && isGrounded() && !type.hovering){
//unit block update //unit block update
if(tile.build != null){ if(tile.build != null){
tile.build.unitOn(base()); tile.build.unitOn(self());
} }
//apply damage //apply damage
@@ -316,7 +329,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
//remove units spawned by the core //remove units spawned by the core
if(spawnedByCore && !isPlayer()){ if(spawnedByCore && !isPlayer()){
Call.unitDespawn(base()); Call.unitDespawn(self());
} }
} }
@@ -338,7 +351,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
Effect.shake(shake, shake, this); Effect.shake(shake, shake, this);
type.deathSound.at(this); type.deathSound.at(this);
Events.fire(new UnitDestroyEvent(base())); Events.fire(new UnitDestroyEvent(self()));
if(explosiveness > 7f && isLocal()){ if(explosiveness > 7f && isLocal()){
Events.fire(Trigger.suicideBomb); Events.fire(Trigger.suicideBomb);
@@ -364,7 +377,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Override @Override
public void display(Table table){ public void display(Table table){
type.display(base(), table); type.display(self(), table);
} }
@Override @Override
@@ -374,7 +387,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Override @Override
public void draw(){ public void draw(){
type.draw(base()); type.draw(self());
} }
@Override @Override

View File

@@ -93,6 +93,7 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
for(WeaponMount mount : mounts){ for(WeaponMount mount : mounts){
Weapon weapon = mount.weapon; Weapon weapon = mount.weapon;
mount.reload = Math.max(mount.reload - Time.delta * reloadMultiplier, 0); mount.reload = Math.max(mount.reload - Time.delta * reloadMultiplier, 0);
mount.heat = Math.max(mount.heat - Time.delta * reloadMultiplier / mount.weapon.cooldownTime, 0);
//flip weapon shoot side for alternating weapons at half reload //flip weapon shoot side for alternating weapons at half reload
if(weapon.otherSide != -1 && weapon.alternate && mount.side == weapon.flipSprite && if(weapon.otherSide != -1 && weapon.alternate && mount.side == weapon.flipSprite &&
@@ -127,7 +128,6 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
float rotation = this.rotation - 90; float rotation = this.rotation - 90;
float weaponRotation = rotation + (weapon.rotate ? mount.rotation : 0); float weaponRotation = rotation + (weapon.rotate ? mount.rotation : 0);
//m a t h
float mountX = this.x + Angles.trnsx(rotation, weapon.x, weapon.y), float mountX = this.x + Angles.trnsx(rotation, weapon.x, weapon.y),
mountY = this.y + Angles.trnsy(rotation, weapon.x, weapon.y); mountY = this.y + Angles.trnsy(rotation, weapon.x, weapon.y);
@@ -138,6 +138,7 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
shoot(weapon, shootX, shootY, mount.aimX, mount.aimY, shootAngle, Mathf.sign(weapon.x)); shoot(weapon, shootX, shootY, mount.aimX, mount.aimY, shootAngle, Mathf.sign(weapon.x));
mount.reload = weapon.reload; mount.reload = weapon.reload;
mount.heat = 1f;
ammo--; ammo--;
if(ammo < 0) ammo = 0; if(ammo < 0) ammo = 0;
@@ -164,9 +165,8 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> bullet(weapon, x, y, f + Mathf.range(weapon.inaccuracy), lifeScl)); Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> bullet(weapon, x, y, f + Mathf.range(weapon.inaccuracy), lifeScl));
} }
if(this instanceof Velc){ vel().add(Tmp.v1.trns(rotation + 180f, ammo.recoil));
((Velc)this).vel().add(Tmp.v1.trns(rotation + 180f, ammo.recoil));
}
boolean parentize = ammo.keepVelocity; boolean parentize = ammo.keepVelocity;
Effect.shake(weapon.shake, weapon.shake, x, y); Effect.shake(weapon.shake, weapon.shake, x, y);
@@ -176,6 +176,11 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
} }
private void bullet(Weapon weapon, float x, float y, float angle, float lifescl){ private void bullet(Weapon weapon, float x, float y, float angle, float lifescl){
weapon.bullet.create(this, team(), x, y, angle, (1f - weapon.velocityRnd) + Mathf.random(weapon.velocityRnd), lifescl); float xr = Mathf.range(weapon.xRand);
weapon.bullet.create(this, team(),
x + Angles.trnsx(angle, 0, xr),
y + Angles.trnsy(angle, 0, xr),
angle, (1f - weapon.velocityRnd) + Mathf.random(weapon.velocityRnd), lifescl);
} }
} }

View File

@@ -152,7 +152,7 @@ public class AIController implements UnitController{
vec.rotate((circleLength - vec.len()) / circleLength * 180f); vec.rotate((circleLength - vec.len()) / circleLength * 180f);
} }
vec.setLength(speed * Time.delta); vec.setLength(speed);
unit.moveAt(vec); unit.moveAt(vec);
} }
@@ -164,7 +164,7 @@ public class AIController implements UnitController{
float length = circleLength <= 0.001f ? 1f : Mathf.clamp((unit.dst(target) - circleLength) / 100f, -1f, 1f); float length = circleLength <= 0.001f ? 1f : Mathf.clamp((unit.dst(target) - circleLength) / 100f, -1f, 1f);
vec.setLength(unit.type().speed * Time.delta * length); vec.setLength(unit.type().speed * length);
if(length < -0.5f){ if(length < -0.5f){
vec.rotate(180f); vec.rotate(180f);
}else if(length < 0){ }else if(length < 0){

View File

@@ -11,6 +11,8 @@ public class WeaponMount{
public float rotation; public float rotation;
/** destination rotation; do not modify! */ /** destination rotation; do not modify! */
public float targetRotation; public float targetRotation;
/** current heat, 0 to 1*/
public float heat;
/** aiming position in world coordinates */ /** aiming position in world coordinates */
public float aimX, aimY; public float aimX, aimY;
/** whether to shoot right now */ /** whether to shoot right now */

View File

@@ -128,6 +128,7 @@ public class Saves{
sector.save.setName(sector.save.file.nameWithoutExtension()); sector.save.setName(sector.save.file.nameWithoutExtension());
saves.add(sector.save); saves.add(sector.save);
} }
sector.save.setAutosave(true);
sector.save.save(); sector.save.save();
lastSectorSave = sector.save; lastSectorSave = sector.save;
Core.settings.put("last-sector-save", sector.save.getName()); Core.settings.put("last-sector-save", sector.save.getName());

View File

@@ -2,9 +2,10 @@ package mindustry.game;
import arc.math.*; import arc.math.*;
import arc.struct.*; import arc.struct.*;
import arc.util.*;
import arc.util.ArcAnnotate.*; import arc.util.ArcAnnotate.*;
import arc.util.*;
import mindustry.content.*; import mindustry.content.*;
import mindustry.ctype.*;
import mindustry.type.*; import mindustry.type.*;
import mindustry.world.*; import mindustry.world.*;
import mindustry.world.blocks.storage.CoreBlock.*; import mindustry.world.blocks.storage.CoreBlock.*;
@@ -32,6 +33,8 @@ public class SectorInfo{
public boolean hasCore = true; public boolean hasCore = true;
/** Sector that was launched from. */ /** Sector that was launched from. */
public @Nullable Sector origin; public @Nullable Sector origin;
/** Resources known to occur at this sector. */
public Seq<UnlockableContent> resources = new Seq<>();
/** Time spent at this sector. Do not use unless you know what you're doing. */ /** Time spent at this sector. Do not use unless you know what you're doing. */
public transient float internalTimeSpent; public transient float internalTimeSpent;
@@ -86,11 +89,6 @@ public class SectorInfo{
public void update(){ public void update(){
internalTimeSpent += Time.delta; internalTimeSpent += Time.delta;
//time spent exceeds turn duration!
if(internalTimeSpent >= turnDuration && internalTimeSpent - Time.delta < turnDuration){
universe.displayTimeEnd();
}
//create last stored core items //create last stored core items
if(lastCoreItems == null){ if(lastCoreItems == null){
lastCoreItems = new int[content.items().size]; lastCoreItems = new int[content.items().size];

View File

@@ -39,7 +39,7 @@ public class Stats{
//weigh used fractions //weigh used fractions
float frac = 0f; float frac = 0f;
Seq<Item> obtainable = Seq.select(zone.data.resources, i -> i instanceof Item).as(); Seq<Item> obtainable = zone.save == null ? new Seq<>() : zone.save.meta.secinfo.resources.select(i -> i instanceof Item).as();
for(Item item : obtainable){ for(Item item : obtainable){
frac += Mathf.clamp((float)itemsDelivered.get(item, 0) / capacity) / (float)obtainable.size; frac += Mathf.clamp((float)itemsDelivered.get(item, 0) / capacity) / (float)obtainable.size;
} }

View File

@@ -56,7 +56,7 @@ public class Universe{
public void displayTimeEnd(){ public void displayTimeEnd(){
if(!headless){ if(!headless){
//check if any sectors are under attack to display this //check if any sectors are under attack to display this
Seq<Sector> attacked = state.getSector().planet.sectors.select(s -> s.hasWaves() && s.hasBase() && !s.isBeingPlayed()); Seq<Sector> attacked = state.getSector().planet.sectors.select(s -> s.hasWaves() && s.hasBase() && !s.isBeingPlayed() && s.getSecondsPassed() > 1);
if(attacked.any()){ if(attacked.any()){
state.set(State.paused); state.set(State.paused);

View File

@@ -18,6 +18,17 @@ public enum CacheLayer{
endShader(Shaders.water); endShader(Shaders.water);
} }
}, },
mud{
@Override
public void begin(){
beginShader();
}
@Override
public void end(){
endShader(Shaders.mud);
}
},
tar{ tar{
@Override @Override
public void begin(){ public void begin(){

View File

@@ -172,6 +172,20 @@ public class Drawf{
construct(t, content.icon(Cicon.full), rotation, progress, speed, time); construct(t, content.icon(Cicon.full), rotation, progress, speed, time);
} }
public static void construct(float x, float y, TextureRegion region, float rotation, float progress, float speed, float time){
Shaders.build.region = region;
Shaders.build.progress = progress;
Shaders.build.color.set(Pal.accent);
Shaders.build.color.a = speed;
Shaders.build.time = -time / 20f;
Draw.shader(Shaders.build);
Draw.rect(region, x, y, rotation);
Draw.shader();
Draw.reset();
}
public static void construct(Building t, TextureRegion region, float rotation, float progress, float speed, float time){ public static void construct(Building t, TextureRegion region, float rotation, float progress, float speed, float time){
Shaders.build.region = region; Shaders.build.region = region;
Shaders.build.progress = progress; Shaders.build.progress = progress;

View File

@@ -228,7 +228,7 @@ public class FloorRenderer implements Disposable{
int chunksx = Mathf.ceil((float)(world.width()) / chunksize), int chunksx = Mathf.ceil((float)(world.width()) / chunksize),
chunksy = Mathf.ceil((float)(world.height()) / chunksize); chunksy = Mathf.ceil((float)(world.height()) / chunksize);
cache = new Chunk[chunksx][chunksy]; cache = new Chunk[chunksx][chunksy];
cbatch = new MultiCacheBatch(chunksize * chunksize * 6); cbatch = new MultiCacheBatch(chunksize * chunksize * 7);
Time.mark(); Time.mark();

View File

@@ -96,24 +96,24 @@ public class IndexedRenderer implements Disposable{
vertices[idx++] = v2; vertices[idx++] = v2;
//tri2 //tri2
vertices[idx++] = x;
vertices[idx++] = y;
vertices[idx++] = color;
vertices[idx++] = u;
vertices[idx++] = v;
vertices[idx++] = fx2;
vertices[idx++] = y;
vertices[idx++] = color;
vertices[idx++] = u2;
vertices[idx++] = v;
vertices[idx++] = fx2; vertices[idx++] = fx2;
vertices[idx++] = fy2; vertices[idx++] = fy2;
vertices[idx++] = color; vertices[idx++] = color;
vertices[idx++] = u2; vertices[idx++] = u2;
vertices[idx++] = v2; vertices[idx++] = v2;
vertices[idx++] = fx2;
vertices[idx++] = y;
vertices[idx++] = color;
vertices[idx++] = u2;
vertices[idx++] = v;
vertices[idx++] = x;
vertices[idx++] = y;
vertices[idx++] = color;
vertices[idx++] = u;
vertices[idx++] = v;
mesh.updateVertices(index * vsize * 6, vertices); mesh.updateVertices(index * vsize * 6, vertices);
} }
@@ -155,6 +155,19 @@ public class IndexedRenderer implements Disposable{
vertices[idx++] = u; vertices[idx++] = u;
vertices[idx++] = v; vertices[idx++] = v;
vertices[idx++] = x2;
vertices[idx++] = y2;
vertices[idx++] = color;
vertices[idx++] = u;
vertices[idx++] = v2;
vertices[idx++] = x3;
vertices[idx++] = y3;
vertices[idx++] = color;
vertices[idx++] = u2;
vertices[idx++] = v2;
//tri2
vertices[idx++] = x3; vertices[idx++] = x3;
vertices[idx++] = y3; vertices[idx++] = y3;
vertices[idx++] = color; vertices[idx++] = color;
@@ -164,28 +177,15 @@ public class IndexedRenderer implements Disposable{
vertices[idx++] = x4; vertices[idx++] = x4;
vertices[idx++] = y4; vertices[idx++] = y4;
vertices[idx++] = color; vertices[idx++] = color;
vertices[idx++] = u; vertices[idx++] = u2;
vertices[idx++] = v2; vertices[idx++] = v;
//tri2
vertices[idx++] = x1; vertices[idx++] = x1;
vertices[idx++] = y1; vertices[idx++] = y1;
vertices[idx++] = color; vertices[idx++] = color;
vertices[idx++] = u; vertices[idx++] = u;
vertices[idx++] = v; vertices[idx++] = v;
vertices[idx++] = x2;
vertices[idx++] = y2;
vertices[idx++] = color;
vertices[idx++] = u2;
vertices[idx++] = v;
vertices[idx++] = x3;
vertices[idx++] = y3;
vertices[idx++] = color;
vertices[idx++] = u2;
vertices[idx++] = v2;
mesh.updateVertices(index * vsize * 6, vertices); mesh.updateVertices(index * vsize * 6, vertices);
} }

View File

@@ -20,7 +20,7 @@ public class Shaders{
public static UnitBuild build; public static UnitBuild build;
public static DarknessShader darkness; public static DarknessShader darkness;
public static LightShader light; public static LightShader light;
public static SurfaceShader water, tar, slag; public static SurfaceShader water, mud, tar, slag;
public static PlanetShader planet; public static PlanetShader planet;
public static PlanetGridShader planetGrid; public static PlanetGridShader planetGrid;
public static AtmosphereShader atmosphere; public static AtmosphereShader atmosphere;
@@ -42,6 +42,7 @@ public class Shaders{
darkness = new DarknessShader(); darkness = new DarknessShader();
light = new LightShader(); light = new LightShader();
water = new SurfaceShader("water"); water = new SurfaceShader("water");
mud = new SurfaceShader("mud");
tar = new SurfaceShader("tar"); tar = new SurfaceShader("tar");
slag = new SurfaceShader("slag"); slag = new SurfaceShader("slag");
planet = new PlanetShader(); planet = new PlanetShader();

View File

@@ -47,6 +47,7 @@ public class DesktopInput extends InputHandler{
@Override @Override
public void buildUI(Group group){ public void buildUI(Group group){
group.fill(t -> { 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.visible(() -> Core.settings.getBool("hints") && ui.hudfrag.shown() && !player.dead() && !player.unit().spawnedByCore() && !(Core.settings.getBool("hints") && lastSchematic != null && !selectRequests.isEmpty()));
t.bottom(); t.bottom();
@@ -224,7 +225,7 @@ public class DesktopInput extends InputHandler{
if(!player.dead() && !state.isPaused() && !(Core.scene.getKeyboardFocus() instanceof TextField)){ if(!player.dead() && !state.isPaused() && !(Core.scene.getKeyboardFocus() instanceof TextField)){
updateMovement(player.unit()); updateMovement(player.unit());
if(Core.input.keyDown(Binding.respawn) && !player.unit().spawnedByCore()){ if(Core.input.keyDown(Binding.respawn) && !player.unit().spawnedByCore() && !scene.hasField()){
Call.unitClear(player); Call.unitClear(player);
controlledType = null; controlledType = null;
} }

View File

@@ -236,7 +236,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
@Remote(targets = Loc.both, forward = true, called = Loc.server) @Remote(targets = Loc.both, forward = true, called = Loc.server)
public static void transferInventory(Player player, Building tile){ public static void transferInventory(Player player, Building tile){
if(player == null || tile == null || !player.within(tile, buildingRange)) return; if(player == null || tile == null || !player.within(tile, buildingRange) || tile.items == null) return;
if(net.server() && (player.unit().stack.amount <= 0 || !Units.canInteract(player, tile) || if(net.server() && (player.unit().stack.amount <= 0 || !Units.canInteract(player, tile) ||
!netServer.admins.allowAction(player, ActionType.depositItem, tile.tile, action -> { !netServer.admins.allowAction(player, ActionType.depositItem, tile.tile, action -> {
@@ -980,6 +980,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
uiGroup.touchable = Touchable.childrenOnly; uiGroup.touchable = Touchable.childrenOnly;
uiGroup.setFillParent(true); uiGroup.setFillParent(true);
ui.hudGroup.addChild(uiGroup); ui.hudGroup.addChild(uiGroup);
uiGroup.toBack();
buildUI(uiGroup); buildUI(uiGroup);
frag.add(); frag.add();

View File

@@ -100,6 +100,20 @@ public class JsonIO{
} }
}); });
json.setSerializer(Liquid.class, new Serializer<Liquid>(){
@Override
public void write(Json json, Liquid object, Class knownType){
json.writeValue(object.name);
}
@Override
public Liquid read(Json json, JsonValue jsonData, Class type){
if(jsonData.asString() == null) return Liquids.water;
Liquid i = Vars.content.getByName(ContentType.liquid, jsonData.asString());
return i == null ? Liquids.water : i;
}
});
json.setSerializer(Item.class, new Serializer<Item>(){ json.setSerializer(Item.class, new Serializer<Item>(){
@Override @Override
public void write(Json json, Item object, Class knownType){ public void write(Json json, Item object, Class knownType){
@@ -165,6 +179,21 @@ public class JsonIO{
return new ItemStack(json.getSerializer(Item.class).read(json, jsonData.get("item"), Item.class), jsonData.getInt("amount")); return new ItemStack(json.getSerializer(Item.class).read(json, jsonData.get("item"), Item.class), jsonData.getInt("amount"));
} }
}); });
json.setSerializer(UnlockableContent.class, new Serializer<UnlockableContent>(){
@Override
public void write(Json json, UnlockableContent object, Class knownType){
json.writeValue(object.name);
}
@Override
public UnlockableContent read(Json json, JsonValue jsonData, Class type){
String str = jsonData.asString();
Item item = Vars.content.getByName(ContentType.item, str);
Liquid liquid = Vars.content.getByName(ContentType.liquid, str);
return item != null ? item : liquid;
}
});
} }
static class CustomJson extends Json{ static class CustomJson extends Json{

View File

@@ -3,6 +3,7 @@ package mindustry.io;
import arc.*; import arc.*;
import arc.files.*; import arc.files.*;
import arc.struct.*; import arc.struct.*;
import arc.util.*;
import arc.util.io.*; import arc.util.io.*;
import mindustry.*; import mindustry.*;
import mindustry.game.EventType.*; import mindustry.game.EventType.*;
@@ -41,7 +42,7 @@ public class SaveIO{
if(exists) file.moveTo(backupFileFor(file)); if(exists) file.moveTo(backupFileFor(file));
try{ try{
write(file); write(file);
}catch(Exception e){ }catch(Throwable e){
if(exists) backupFileFor(file).moveTo(file); if(exists) backupFileFor(file).moveTo(file);
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@@ -56,9 +57,9 @@ public class SaveIO{
} }
public static boolean isSaveValid(Fi file){ public static boolean isSaveValid(Fi file){
try{ try(DataInputStream stream = new DataInputStream(new InflaterInputStream(file.read(bufferSize)))){
return isSaveValid(new DataInputStream(new InflaterInputStream(file.read(bufferSize)))); return isSaveValid(stream);
}catch(Exception e){ }catch(Throwable e){
return false; return false;
} }
} }
@@ -67,8 +68,8 @@ public class SaveIO{
try{ try{
getMeta(stream); getMeta(stream);
return true; return true;
}catch(Exception e){ }catch(Throwable e){
e.printStackTrace(); Log.err(e);
return false; return false;
} }
} }
@@ -76,7 +77,8 @@ public class SaveIO{
public static SaveMeta getMeta(Fi file){ public static SaveMeta getMeta(Fi file){
try{ try{
return getMeta(getStream(file)); return getMeta(getStream(file));
}catch(Exception e){ }catch(Throwable e){
Log.err(e);
return getMeta(getBackupStream(file)); return getMeta(getBackupStream(file));
} }
} }
@@ -119,7 +121,7 @@ public class SaveIO{
}else{ }else{
getVersion().write(stream, tags); getVersion().write(stream, tags);
} }
}catch(Exception e){ }catch(Throwable e){
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
@@ -133,7 +135,7 @@ public class SaveIO{
//try and load; if any exception at all occurs //try and load; if any exception at all occurs
load(new InflaterInputStream(file.read(bufferSize)), context); load(new InflaterInputStream(file.read(bufferSize)), context);
}catch(SaveException e){ }catch(SaveException e){
e.printStackTrace(); Log.err(e);
Fi backup = file.sibling(file.name() + "-backup." + file.extension()); Fi backup = file.sibling(file.name() + "-backup." + file.extension());
if(backup.exists()){ if(backup.exists()){
load(new InflaterInputStream(backup.read(bufferSize)), context); load(new InflaterInputStream(backup.read(bufferSize)), context);
@@ -153,7 +155,7 @@ public class SaveIO{
ver.read(stream, counter, context); ver.read(stream, counter, context);
Events.fire(new SaveLoadEvent()); Events.fire(new SaveLoadEvent());
}catch(Exception e){ }catch(Throwable e){
throw new SaveException(e); throw new SaveException(e);
}finally{ }finally{
world.setGenerating(false); world.setGenerating(false);

Some files were not shown because too many files have changed in this diff Show More