Merged Unit & Builder components / Cleanup
This commit is contained in:
@@ -1,10 +1,13 @@
|
|||||||
#Maps entity names to IDs. Autogenerated.
|
#Maps entity names to IDs. Autogenerated.
|
||||||
|
|
||||||
alpha=0
|
alpha=0
|
||||||
|
arkyid=29
|
||||||
atrax=1
|
atrax=1
|
||||||
|
beta=30
|
||||||
block=2
|
block=2
|
||||||
corvus=24
|
corvus=24
|
||||||
flare=3
|
flare=3
|
||||||
|
gamma=31
|
||||||
mace=4
|
mace=4
|
||||||
mega=5
|
mega=5
|
||||||
mindustry.entities.comp.BuildingComp=6
|
mindustry.entities.comp.BuildingComp=6
|
||||||
@@ -26,6 +29,8 @@ oct=26
|
|||||||
poly=18
|
poly=18
|
||||||
pulsar=19
|
pulsar=19
|
||||||
quad=23
|
quad=23
|
||||||
|
quasar=32
|
||||||
risso=20
|
risso=20
|
||||||
spiroct=21
|
spiroct=21
|
||||||
|
toxopid=33
|
||||||
vela=25
|
vela=25
|
||||||
1
annotations/src/main/resources/revisions/alpha/0.json
Normal file
1
annotations/src/main/resources/revisions/alpha/0.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/arkyid/0.json
Normal file
1
annotations/src/main/resources/revisions/arkyid/0.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/beta/0.json
Normal file
1
annotations/src/main/resources/revisions/beta/0.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/block/4.json
Normal file
1
annotations/src/main/resources/revisions/block/4.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:4,fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/corvus/4.json
Normal file
1
annotations/src/main/resources/revisions/corvus/4.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:4,fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/flare/4.json
Normal file
1
annotations/src/main/resources/revisions/flare/4.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:4,fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/gamma/0.json
Normal file
1
annotations/src/main/resources/revisions/gamma/0.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/mace/4.json
Normal file
1
annotations/src/main/resources/revisions/mace/4.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:4,fields:[{name:ammo,type:float},{name:armor,type:float},{name:baseRotation,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/mono/3.json
Normal file
1
annotations/src/main/resources/revisions/mono/3.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:3,fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/pulsar/0.json
Normal file
1
annotations/src/main/resources/revisions/pulsar/0.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:ammo,type:float},{name:armor,type:float},{name:baseRotation,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/quasar/0.json
Normal file
1
annotations/src/main/resources/revisions/quasar/0.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:ammo,type:float},{name:armor,type:float},{name:baseRotation,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/risso/4.json
Normal file
1
annotations/src/main/resources/revisions/risso/4.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{version:4,fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:x,type:float},{name:y,type:float}]}
|
||||||
1
annotations/src/main/resources/revisions/toxopid/0.json
Normal file
1
annotations/src/main/resources/revisions/toxopid/0.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{fields:[{name:ammo,type:float},{name:armor,type:float},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:x,type:float},{name:y,type:float}]}
|
||||||
@@ -1279,6 +1279,7 @@ liquid.slag.description = Refined in separators into constituent metals, or spra
|
|||||||
liquid.oil.description = Used in advanced material production and as incendiary ammunition.
|
liquid.oil.description = Used in advanced material production and as incendiary ammunition.
|
||||||
liquid.cryofluid.description = Used as coolant in reactors, turrets and factories.
|
liquid.cryofluid.description = Used as coolant in reactors, turrets and factories.
|
||||||
|
|
||||||
|
block.resupply-point.description = Resupplies nearby units with copper ammunition. Not compatible with units that require battery power.
|
||||||
block.armored-conveyor.description = Moves items forward. Does not accept inputs from the sides.
|
block.armored-conveyor.description = Moves items forward. Does not accept inputs from the sides.
|
||||||
block.illuminator.description = Emits light.
|
block.illuminator.description = Emits light.
|
||||||
block.message.description = Stores a message for communication between allies.
|
block.message.description = Stores a message for communication between allies.
|
||||||
|
|||||||
@@ -14,21 +14,20 @@ import static mindustry.Vars.*;
|
|||||||
public class BuilderAI extends AIController{
|
public class BuilderAI extends AIController{
|
||||||
float buildRadius = 1500;
|
float buildRadius = 1500;
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
@Nullable Builderc following;
|
@Nullable Unit following;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateMovement(){
|
public void updateMovement(){
|
||||||
Builderc builder = (Builderc)unit;
|
|
||||||
|
|
||||||
if(builder.moving()){
|
if(unit.moving()){
|
||||||
builder.lookAt(builder.vel().angle());
|
unit.lookAt(unit.vel.angle());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(target != null && shouldShoot()){
|
if(target != null && shouldShoot()){
|
||||||
unit.lookAt(target);
|
unit.lookAt(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.updateBuilding(true);
|
unit.updateBuilding = true;
|
||||||
|
|
||||||
if(following != null){
|
if(following != null){
|
||||||
//try to follow and mimic someone
|
//try to follow and mimic someone
|
||||||
@@ -36,18 +35,18 @@ public class BuilderAI extends AIController{
|
|||||||
//validate follower
|
//validate follower
|
||||||
if(!following.isValid() || !following.activelyBuilding()){
|
if(!following.isValid() || !following.activelyBuilding()){
|
||||||
following = null;
|
following = null;
|
||||||
builder.plans().clear();
|
unit.plans.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//set to follower's first build plan, whatever that is
|
//set to follower's first build plan, whatever that is
|
||||||
builder.plans().clear();
|
unit.plans.clear();
|
||||||
builder.plans().addFirst(following.buildPlan());
|
unit.plans.addFirst(following.buildPlan());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(builder.buildPlan() != null){
|
if(unit.buildPlan() != null){
|
||||||
//approach request if building
|
//approach request if building
|
||||||
BuildPlan req = builder.buildPlan();
|
BuildPlan req = unit.buildPlan();
|
||||||
|
|
||||||
boolean valid =
|
boolean valid =
|
||||||
(req.tile().build instanceof ConstructBuild && req.tile().<ConstructBuild>bc().cblock == req.block) ||
|
(req.tile().build instanceof ConstructBuild && req.tile().<ConstructBuild>bc().cblock == req.block) ||
|
||||||
@@ -60,7 +59,7 @@ public class BuilderAI extends AIController{
|
|||||||
moveTo(req.tile(), buildingRange - 20f);
|
moveTo(req.tile(), buildingRange - 20f);
|
||||||
}else{
|
}else{
|
||||||
//discard invalid request
|
//discard invalid request
|
||||||
builder.plans().removeFirst();
|
unit.plans.removeFirst();
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
|
|
||||||
@@ -71,8 +70,8 @@ public class BuilderAI extends AIController{
|
|||||||
Units.nearby(unit.team, unit.x, unit.y, buildRadius, u -> {
|
Units.nearby(unit.team, unit.x, unit.y, buildRadius, u -> {
|
||||||
if(found) return;
|
if(found) return;
|
||||||
|
|
||||||
if(u instanceof Builderc b && u != unit && b.activelyBuilding()){
|
if(u.canBuild() && u != unit && u.activelyBuilding()){
|
||||||
BuildPlan plan = b.buildPlan();
|
BuildPlan plan = u.buildPlan();
|
||||||
|
|
||||||
Building build = world.build(plan.x, plan.y);
|
Building build = world.build(plan.x, plan.y);
|
||||||
if(build instanceof ConstructBuild cons){
|
if(build instanceof ConstructBuild cons){
|
||||||
@@ -80,7 +79,7 @@ public class BuilderAI extends AIController{
|
|||||||
|
|
||||||
//make sure you can reach the request in time
|
//make sure you can reach the request in time
|
||||||
if(dist / unit.speed() < cons.buildCost * 0.9f){
|
if(dist / unit.speed() < cons.buildCost * 0.9f){
|
||||||
following = b;
|
following = u;
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,7 +97,7 @@ public class BuilderAI extends AIController{
|
|||||||
blocks.removeFirst();
|
blocks.removeFirst();
|
||||||
}else if(Build.validPlace(content.block(block.block), unit.team(), block.x, block.y, block.rotation)){ //it's valid.
|
}else if(Build.validPlace(content.block(block.block), unit.team(), block.x, block.y, block.rotation)){ //it's valid.
|
||||||
//add build request.
|
//add build request.
|
||||||
builder.addBuild(new BuildPlan(block.x, block.y, block.rotation, content.block(block.block), block.config));
|
unit.addBuild(new BuildPlan(block.x, block.y, block.rotation, content.block(block.block), block.config));
|
||||||
//shift build plan to tail so next unit builds something else.
|
//shift build plan to tail so next unit builds something else.
|
||||||
blocks.addLast(blocks.removeFirst());
|
blocks.addLast(blocks.removeFirst());
|
||||||
}else{
|
}else{
|
||||||
|
|||||||
@@ -59,13 +59,13 @@ public class FormationAI extends AIController implements FormationMember{
|
|||||||
unit.moveAt(realtarget.sub(unit).limit(speed));
|
unit.moveAt(realtarget.sub(unit).limit(speed));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(unit instanceof Minerc mine && leader instanceof Minerc com){
|
if(unit.canMine() && leader.canMine()){
|
||||||
if(com.mineTile() != null && mine.validMine(com.mineTile())){
|
if(leader.mineTile != null && unit.validMine(leader.mineTile)){
|
||||||
mine.mineTile(com.mineTile());
|
unit.mineTile(leader.mineTile);
|
||||||
|
|
||||||
CoreBuild core = unit.team.core();
|
CoreBuild core = unit.team.core();
|
||||||
|
|
||||||
if(core != null && com.mineTile().drop() != null && unit.within(core, unit.type.range) && !unit.acceptsItem(com.mineTile().drop())){
|
if(core != null && leader.mineTile.drop() != null && unit.within(core, unit.type.range) && !unit.acceptsItem(leader.mineTile.drop())){
|
||||||
if(core.acceptStack(unit.stack.item, unit.stack.amount, unit) > 0){
|
if(core.acceptStack(unit.stack.item, unit.stack.amount, unit) > 0){
|
||||||
Call.transferItemTo(unit.stack.item, unit.stack.amount, unit.x, unit.y, core);
|
Call.transferItemTo(unit.stack.item, unit.stack.amount, unit.x, unit.y, core);
|
||||||
|
|
||||||
@@ -73,13 +73,13 @@ public class FormationAI extends AIController implements FormationMember{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
mine.mineTile(null);
|
unit.mineTile(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(unit instanceof Builderc build && leader instanceof Builderc com && com.activelyBuilding()){
|
if(unit.canBuild() && leader.canBuild() && leader.activelyBuilding()){
|
||||||
build.clearBuilding();
|
unit.clearBuilding();
|
||||||
build.addBuild(com.buildPlan());
|
leader.addBuild(unit.buildPlan());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -92,9 +92,7 @@ public class LogicAI extends AIController{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case stop -> {
|
case stop -> {
|
||||||
if(unit instanceof Builderc build){
|
unit.clearBuilding();
|
||||||
build.clearBuilding();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,21 +17,21 @@ public class MinerAI extends AIController{
|
|||||||
protected void updateMovement(){
|
protected void updateMovement(){
|
||||||
Building core = unit.closestCore();
|
Building core = unit.closestCore();
|
||||||
|
|
||||||
if(!(unit instanceof Minerc miner) || core == null) return;
|
if(!(unit.canMine()) || core == null) return;
|
||||||
|
|
||||||
if(miner.mineTile() != null && !miner.mineTile().within(unit, unit.type.range)){
|
if(unit.mineTile != null && !unit.mineTile.within(unit, unit.type.range)){
|
||||||
miner.mineTile(null);
|
unit.mineTile(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mining){
|
if(mining){
|
||||||
if(timer.get(timerTarget2, 60 * 4) || targetItem == null){
|
if(timer.get(timerTarget2, 60 * 4) || targetItem == null){
|
||||||
targetItem = unit.team.data().mineItems.min(i -> indexer.hasOre(i) && miner.canMine(i), i -> core.items.get(i));
|
targetItem = unit.team.data().mineItems.min(i -> indexer.hasOre(i) && unit.canMine(i), i -> core.items.get(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
//core full of the target item, do nothing
|
//core full of the target item, do nothing
|
||||||
if(targetItem != null && core.acceptStack(targetItem, 1, unit) == 0){
|
if(targetItem != null && core.acceptStack(targetItem, 1, unit) == 0){
|
||||||
unit.clearItem();
|
unit.clearItem();
|
||||||
miner.mineTile(null);
|
unit.mineTile(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ public class MinerAI extends AIController{
|
|||||||
moveTo(ore, unit.type.range / 2f, 20f);
|
moveTo(ore, unit.type.range / 2f, 20f);
|
||||||
|
|
||||||
if(unit.within(ore, unit.type.range)){
|
if(unit.within(ore, unit.type.range)){
|
||||||
miner.mineTile(ore);
|
unit.mineTile = ore;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ore.block() != Blocks.air){
|
if(ore.block() != Blocks.air){
|
||||||
@@ -56,7 +56,7 @@ public class MinerAI extends AIController{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
miner.mineTile(null);
|
unit.mineTile = null;
|
||||||
|
|
||||||
if(unit.stack.amount == 0){
|
if(unit.stack.amount == 0){
|
||||||
mining = true;
|
mining = true;
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ import static mindustry.Vars.*;
|
|||||||
public class UnitTypes implements ContentList{
|
public class UnitTypes implements ContentList{
|
||||||
//region definitions
|
//region definitions
|
||||||
|
|
||||||
|
//(the wall of shame - should fix the legacy stuff eventually...)
|
||||||
|
|
||||||
//mech
|
//mech
|
||||||
public static @EntityDef({Unitc.class, Mechc.class}) UnitType mace, dagger, crawler, fortress, scepter, reign;
|
public static @EntityDef({Unitc.class, Mechc.class}) UnitType mace, dagger, crawler, fortress, scepter, reign;
|
||||||
|
|
||||||
//mech + builder + miner
|
//mech
|
||||||
public static @EntityDef({Unitc.class, Mechc.class, Builderc.class}) UnitType nova, pulsar, quasar;
|
public static @EntityDef(value = {Unitc.class, Mechc.class}, legacy = true) UnitType nova, pulsar, quasar;
|
||||||
|
|
||||||
//mech
|
//mech
|
||||||
public static @EntityDef({Unitc.class, Mechc.class}) UnitType vela;
|
public static @EntityDef({Unitc.class, Mechc.class}) UnitType vela;
|
||||||
@@ -29,29 +31,29 @@ public class UnitTypes implements ContentList{
|
|||||||
//legs
|
//legs
|
||||||
public static @EntityDef({Unitc.class, Legsc.class}) UnitType corvus, atrax;
|
public static @EntityDef({Unitc.class, Legsc.class}) UnitType corvus, atrax;
|
||||||
|
|
||||||
//legs + building
|
//legs
|
||||||
public static @EntityDef({Unitc.class, Legsc.class, Builderc.class}) UnitType spiroct, arkyid, toxopid;
|
public static @EntityDef(value = {Unitc.class, Legsc.class}, legacy = true) UnitType spiroct, arkyid, toxopid;
|
||||||
|
|
||||||
//air (no special traits)
|
//air
|
||||||
public static @EntityDef({Unitc.class}) UnitType flare, eclipse, horizon, zenith, antumbra;
|
public static @EntityDef({Unitc.class}) UnitType flare, eclipse, horizon, zenith, antumbra;
|
||||||
|
|
||||||
//air, legacy mining
|
//air
|
||||||
public static @EntityDef(value = {Unitc.class}, legacy = true) UnitType mono;
|
public static @EntityDef(value = {Unitc.class}, legacy = true) UnitType mono;
|
||||||
|
|
||||||
//air + building + mining
|
//air
|
||||||
public static @EntityDef({Unitc.class, Builderc.class}) UnitType poly;
|
public static @EntityDef(value = {Unitc.class}, legacy = true) UnitType poly;
|
||||||
|
|
||||||
//air + building + mining + payload
|
//air + payload
|
||||||
public static @EntityDef({Unitc.class, Builderc.class, Payloadc.class}) UnitType mega;
|
public static @EntityDef({Unitc.class, Payloadc.class}) UnitType mega;
|
||||||
|
|
||||||
//air + building + payload
|
//air + payload
|
||||||
public static @EntityDef(value = {Unitc.class, Builderc.class, Payloadc.class}, legacy = true) UnitType quad;
|
public static @EntityDef(value = {Unitc.class, Payloadc.class}, legacy = true) UnitType quad;
|
||||||
|
|
||||||
//air + building + payload
|
//air + payload + ammo distribution
|
||||||
public static @EntityDef({Unitc.class, Builderc.class, Payloadc.class, AmmoDistributec.class}) UnitType oct;
|
public static @EntityDef({Unitc.class, Payloadc.class, AmmoDistributec.class}) UnitType oct;
|
||||||
|
|
||||||
//air + building + mining
|
//air
|
||||||
public static @EntityDef({Unitc.class, Builderc.class}) UnitType alpha, beta, gamma;
|
public static @EntityDef(value = {Unitc.class}, legacy = true) UnitType alpha, beta, gamma;
|
||||||
|
|
||||||
//water
|
//water
|
||||||
public static @EntityDef({Unitc.class, WaterMovec.class}) UnitType risso, minke, bryde, sei, omura;
|
public static @EntityDef({Unitc.class, WaterMovec.class}) UnitType risso, minke, bryde, sei, omura;
|
||||||
@@ -470,7 +472,6 @@ public class UnitTypes implements ContentList{
|
|||||||
mineTier = 1;
|
mineTier = 1;
|
||||||
hitSize = 29f;
|
hitSize = 29f;
|
||||||
health = 18000f;
|
health = 18000f;
|
||||||
buildSpeed = 1.7f;
|
|
||||||
armor = 9f;
|
armor = 9f;
|
||||||
landShake = 1.5f;
|
landShake = 1.5f;
|
||||||
rotateSpeed = 1.5f;
|
rotateSpeed = 1.5f;
|
||||||
@@ -700,6 +701,7 @@ public class UnitTypes implements ContentList{
|
|||||||
rippleScale = 2f;
|
rippleScale = 2f;
|
||||||
legSpeed = 0.2f;
|
legSpeed = 0.2f;
|
||||||
ammoType = AmmoTypes.power;
|
ammoType = AmmoTypes.power;
|
||||||
|
buildSpeed = 1f;
|
||||||
|
|
||||||
legSplashDamage = 32;
|
legSplashDamage = 32;
|
||||||
legSplashRange = 30;
|
legSplashRange = 30;
|
||||||
@@ -802,6 +804,7 @@ public class UnitTypes implements ContentList{
|
|||||||
rippleScale = 3f;
|
rippleScale = 3f;
|
||||||
legSpeed = 0.19f;
|
legSpeed = 0.19f;
|
||||||
ammoType = AmmoTypes.powerHigh;
|
ammoType = AmmoTypes.powerHigh;
|
||||||
|
buildSpeed = 1f;
|
||||||
|
|
||||||
legSplashDamage = 80;
|
legSplashDamage = 80;
|
||||||
legSplashRange = 60;
|
legSplashRange = 60;
|
||||||
|
|||||||
@@ -571,13 +571,13 @@ public class NetClient implements ApplicationListener{
|
|||||||
BuildPlan[] requests = null;
|
BuildPlan[] requests = null;
|
||||||
if(player.isBuilder()){
|
if(player.isBuilder()){
|
||||||
//limit to 10 to prevent buffer overflows
|
//limit to 10 to prevent buffer overflows
|
||||||
int usedRequests = Math.min(player.builder().plans().size, 10);
|
int usedRequests = Math.min(player.unit().plans().size, 10);
|
||||||
|
|
||||||
int totalLength = 0;
|
int totalLength = 0;
|
||||||
|
|
||||||
//prevent buffer overflow by checking config length
|
//prevent buffer overflow by checking config length
|
||||||
for(int i = 0; i < usedRequests; i++){
|
for(int i = 0; i < usedRequests; i++){
|
||||||
BuildPlan plan = player.builder().plans().get(i);
|
BuildPlan plan = player.unit().plans().get(i);
|
||||||
if(plan.config instanceof byte[] b){
|
if(plan.config instanceof byte[] b){
|
||||||
int length = b.length;
|
int length = b.length;
|
||||||
totalLength += length;
|
totalLength += length;
|
||||||
@@ -591,7 +591,7 @@ public class NetClient implements ApplicationListener{
|
|||||||
|
|
||||||
requests = new BuildPlan[usedRequests];
|
requests = new BuildPlan[usedRequests];
|
||||||
for(int i = 0; i < usedRequests; i++){
|
for(int i = 0; i < usedRequests; i++){
|
||||||
requests[i] = player.builder().plans().get(i);
|
requests[i] = player.unit().plans().get(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -607,7 +607,7 @@ public class NetClient implements ApplicationListener{
|
|||||||
unit.rotation,
|
unit.rotation,
|
||||||
unit instanceof Mechc m ? m.baseRotation() : 0,
|
unit instanceof Mechc m ? m.baseRotation() : 0,
|
||||||
unit.vel.x, unit.vel.y,
|
unit.vel.x, unit.vel.y,
|
||||||
player.unit().mineTile(),
|
player.unit().mineTile,
|
||||||
player.boosting, player.shooting, ui.chatfrag.shown(), control.input.isBuilding,
|
player.boosting, player.shooting, ui.chatfrag.shown(), control.input.isBuilding,
|
||||||
requests,
|
requests,
|
||||||
Core.camera.position.x, Core.camera.position.y,
|
Core.camera.position.x, Core.camera.position.y,
|
||||||
|
|||||||
@@ -600,8 +600,8 @@ public class NetServer implements ApplicationListener{
|
|||||||
player.unit().aim(pointerX, pointerY);
|
player.unit().aim(pointerX, pointerY);
|
||||||
|
|
||||||
if(player.isBuilder()){
|
if(player.isBuilder()){
|
||||||
player.builder().clearBuilding();
|
player.unit().clearBuilding();
|
||||||
player.builder().updateBuilding(building);
|
player.unit().updateBuilding(building);
|
||||||
|
|
||||||
if(requests != null){
|
if(requests != null){
|
||||||
for(BuildPlan req : requests){
|
for(BuildPlan req : requests){
|
||||||
@@ -625,7 +625,7 @@ public class NetServer implements ApplicationListener{
|
|||||||
con.rejectedRequests.add(req);
|
con.rejectedRequests.add(req);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
player.builder().plans().addLast(req);
|
player.unit().plans().addLast(req);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import mindustry.entities.units.*;
|
|||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
|
import mindustry.type.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
import mindustry.world.blocks.*;
|
import mindustry.world.blocks.*;
|
||||||
import mindustry.world.blocks.ConstructBlock.*;
|
import mindustry.world.blocks.ConstructBlock.*;
|
||||||
@@ -22,17 +23,22 @@ import java.util.*;
|
|||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
abstract class BuilderComp implements Unitc{
|
abstract class BuilderComp implements Posc, Teamc, Rotc{
|
||||||
static final Vec2[] vecs = new Vec2[]{new Vec2(), new Vec2(), new Vec2(), new Vec2()};
|
static final Vec2[] vecs = new Vec2[]{new Vec2(), new Vec2(), new Vec2(), new Vec2()};
|
||||||
|
|
||||||
@Import float x, y, rotation;
|
@Import float x, y, rotation;
|
||||||
|
@Import UnitType type;
|
||||||
|
|
||||||
@SyncLocal Queue<BuildPlan> plans = new Queue<>(1);
|
@SyncLocal Queue<BuildPlan> plans = new Queue<>(1);
|
||||||
@SyncLocal transient boolean updateBuilding = true;
|
@SyncLocal transient boolean updateBuilding = true;
|
||||||
|
|
||||||
|
public boolean canBuild(){
|
||||||
|
return type.buildSpeed > 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(){
|
public void update(){
|
||||||
if(!updateBuilding) return;
|
if(!updateBuilding || !canBuild()) return;
|
||||||
|
|
||||||
float finalPlaceDst = state.rules.infiniteResources ? Float.MAX_VALUE : buildingRange;
|
float finalPlaceDst = state.rules.infiniteResources ? Float.MAX_VALUE : buildingRange;
|
||||||
boolean infinite = state.rules.infiniteResources || team().rules().infiniteResources;
|
boolean infinite = state.rules.infiniteResources || team().rules().infiniteResources;
|
||||||
@@ -102,9 +108,9 @@ abstract class BuilderComp implements Unitc{
|
|||||||
ConstructBuild entity = tile.bc();
|
ConstructBuild entity = tile.bc();
|
||||||
|
|
||||||
if(current.breaking){
|
if(current.breaking){
|
||||||
entity.deconstruct(self(), 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(self(), 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);
|
||||||
@@ -161,6 +167,8 @@ abstract class BuilderComp implements Unitc{
|
|||||||
|
|
||||||
/** Add another build requests to the queue, if it doesn't exist there yet. */
|
/** Add another build requests to the queue, if it doesn't exist there yet. */
|
||||||
void addBuild(BuildPlan place, boolean tail){
|
void addBuild(BuildPlan place, boolean tail){
|
||||||
|
if(!canBuild()) return;
|
||||||
|
|
||||||
BuildPlan replace = null;
|
BuildPlan replace = null;
|
||||||
for(BuildPlan request : plans){
|
for(BuildPlan request : plans){
|
||||||
if(request.x == place.x && request.y == place.y){
|
if(request.x == place.x && request.y == place.y){
|
||||||
@@ -196,9 +204,8 @@ abstract class BuilderComp implements Unitc{
|
|||||||
return plans.size == 0 ? null : plans.first();
|
return plans.size == 0 ? null : plans.first();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void draw(){
|
public void draw(){
|
||||||
if(!isBuilding() || !updateBuilding) return;
|
if(!isBuilding() || !updateBuilding || !canBuild()) return;
|
||||||
|
|
||||||
//TODO check correctness
|
//TODO check correctness
|
||||||
Draw.z(Layer.flyingUnit);
|
Draw.z(Layer.flyingUnit);
|
||||||
|
|||||||
@@ -1122,7 +1122,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
|
|
||||||
/** Returns whether or not a hand cursor should be shown over this block. */
|
/** Returns whether or not a hand cursor should be shown over this block. */
|
||||||
public Cursor getCursor(){
|
public Cursor getCursor(){
|
||||||
return block.configurable ? SystemCursor.hand : SystemCursor.arrow;
|
return block.configurable && team == player.team() ? SystemCursor.hand : SystemCursor.arrow;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc{
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean mining(){
|
boolean mining(){
|
||||||
return mineTile != null && !(((Object)this) instanceof Builderc b && b.activelyBuilding());
|
return mineTile != null && !this.<Unit>self().activelyBuilding();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean validMine(Tile tile, boolean checkDst){
|
public boolean validMine(Tile tile, boolean checkDst){
|
||||||
@@ -44,6 +44,10 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc{
|
|||||||
return validMine(tile, true);
|
return validMine(tile, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean canMine(){
|
||||||
|
return type.mineSpeed > 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(){
|
public void update(){
|
||||||
Building core = closestCore();
|
Building core = closestCore();
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
|
|||||||
transient float textFadeTime;
|
transient float textFadeTime;
|
||||||
|
|
||||||
public boolean isBuilder(){
|
public boolean isBuilder(){
|
||||||
return unit instanceof Builderc;
|
return unit.canBuild();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable CoreBuild closestCore(){
|
public @Nullable CoreBuild closestCore(){
|
||||||
@@ -160,10 +160,6 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
|
|||||||
return unit;
|
return unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builderc builder(){
|
|
||||||
return !(unit instanceof Builderc) ? Nulls.builder : (Builderc)unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unit(Unit unit){
|
public void unit(Unit unit){
|
||||||
if(unit == null) throw new IllegalArgumentException("Unit cannot be null. Use clearUnit() instead.");
|
if(unit == null) throw new IllegalArgumentException("Unit cannot be null. Use clearUnit() instead.");
|
||||||
if(this.unit == unit) return;
|
if(this.unit == unit) return;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import mindustry.world.blocks.payloads.*;
|
|||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
@Component(base = true)
|
@Component(base = true)
|
||||||
abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, Itemsc, Rotc, Unitc, Weaponsc, Drawc, Boundedc, Syncc, Shieldc, Commanderc, Displayable, Senseable, Ranged, Minerc{
|
abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, Itemsc, Rotc, Unitc, Weaponsc, Drawc, Boundedc, Syncc, Shieldc, Commanderc, Displayable, Senseable, Ranged, Minerc, Builderc{
|
||||||
|
|
||||||
@Import boolean hovering, dead;
|
@Import boolean hovering, dead;
|
||||||
@Import float x, y, rotation, elevation, maxHealth, drag, armor, hitSize, health, ammo, minFormationSpeed;
|
@Import float x, y, rotation, elevation, maxHealth, drag, armor, hitSize, health, ammo, minFormationSpeed;
|
||||||
@@ -88,8 +88,8 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
|||||||
|
|
||||||
/** @return where the unit wants to look at. */
|
/** @return where the unit wants to look at. */
|
||||||
public float prefRotation(){
|
public float prefRotation(){
|
||||||
if(this instanceof Builderc builder && builder.activelyBuilding()){
|
if(activelyBuilding()){
|
||||||
return angleTo(builder.buildPlan());
|
return angleTo(buildPlan());
|
||||||
}else if(mineTile() != null){
|
}else if(mineTile() != null){
|
||||||
return angleTo(mineTile());
|
return angleTo(mineTile());
|
||||||
}else if(moving()){
|
}else if(moving()){
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class OverlayRenderer{
|
|||||||
if(player.dead()) return;
|
if(player.dead()) return;
|
||||||
|
|
||||||
if(player.isBuilder()){
|
if(player.isBuilder()){
|
||||||
player.builder().drawBuildRequests();
|
player.unit().drawBuildRequests();
|
||||||
}
|
}
|
||||||
|
|
||||||
input.drawBottom();
|
input.drawBottom();
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public class DesktopInput extends InputHandler{
|
|||||||
group.fill(t -> {
|
group.fill(t -> {
|
||||||
t.bottom();
|
t.bottom();
|
||||||
t.visible(() -> {
|
t.visible(() -> {
|
||||||
t.color.a = Mathf.lerpDelta(t.color.a, player.builder().isBuilding() ? 1f : 0f, 0.15f);
|
t.color.a = Mathf.lerpDelta(t.color.a, player.unit().isBuilding() ? 1f : 0f, 0.15f);
|
||||||
|
|
||||||
return ui.hudfrag.shown && Core.settings.getBool("hints") && selectRequests.isEmpty() && t.color.a > 0.01f;
|
return ui.hudfrag.shown && Core.settings.getBool("hints") && selectRequests.isEmpty() && t.color.a > 0.01f;
|
||||||
});
|
});
|
||||||
@@ -290,7 +290,7 @@ public class DesktopInput extends InputHandler{
|
|||||||
cursorType = cursor.build.getCursor();
|
cursorType = cursor.build.getCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isPlacing() || !selectRequests.isEmpty()){
|
if((isPlacing() && player.isBuilder()) || !selectRequests.isEmpty()){
|
||||||
cursorType = SystemCursor.hand;
|
cursorType = SystemCursor.hand;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,7 +366,7 @@ public class DesktopInput extends InputHandler{
|
|||||||
int rawCursorX = World.toTile(Core.input.mouseWorld().x), rawCursorY = World.toTile(Core.input.mouseWorld().y);
|
int rawCursorX = World.toTile(Core.input.mouseWorld().x), rawCursorY = World.toTile(Core.input.mouseWorld().y);
|
||||||
|
|
||||||
// automatically pause building if the current build queue is empty
|
// automatically pause building if the current build queue is empty
|
||||||
if(Core.settings.getBool("buildautopause") && isBuilding && !player.builder().isBuilding()){
|
if(Core.settings.getBool("buildautopause") && isBuilding && !player.unit().isBuilding()){
|
||||||
isBuilding = false;
|
isBuilding = false;
|
||||||
buildWasAutoPaused = true;
|
buildWasAutoPaused = true;
|
||||||
}
|
}
|
||||||
@@ -388,7 +388,7 @@ public class DesktopInput extends InputHandler{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(Core.input.keyTap(Binding.clear_building)){
|
if(Core.input.keyTap(Binding.clear_building)){
|
||||||
player.builder().clearBuilding();
|
player.unit().clearBuilding();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Core.input.keyTap(Binding.schematic_select) && !Core.scene.hasKeyboard() && mode != breaking){
|
if(Core.input.keyTap(Binding.schematic_select) && !Core.scene.hasKeyboard() && mode != breaking){
|
||||||
@@ -480,8 +480,8 @@ public class DesktopInput extends InputHandler{
|
|||||||
deleting = true;
|
deleting = true;
|
||||||
}else if(selected != null){
|
}else if(selected != null){
|
||||||
//only begin shooting if there's no cursor event
|
//only begin shooting if there's no cursor event
|
||||||
if(!tileTapped(selected.build) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && !player.builder().activelyBuilding() && !droppingItem &&
|
if(!tileTapped(selected.build) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && !player.unit().activelyBuilding() && !droppingItem &&
|
||||||
!tryBeginMine(selected) && player.unit().mineTile() == null && !Core.scene.hasKeyboard()){
|
!tryBeginMine(selected) && player.unit().mineTile == null && !Core.scene.hasKeyboard()){
|
||||||
player.shooting = shouldShoot;
|
player.shooting = shouldShoot;
|
||||||
}
|
}
|
||||||
}else if(!Core.scene.hasKeyboard()){ //if it's out of bounds, shooting is just fine
|
}else if(!Core.scene.hasKeyboard()){ //if it's out of bounds, shooting is just fine
|
||||||
@@ -506,7 +506,7 @@ public class DesktopInput extends InputHandler{
|
|||||||
if(Core.input.keyDown(Binding.select) && mode == none && !isPlacing() && deleting){
|
if(Core.input.keyDown(Binding.select) && mode == none && !isPlacing() && deleting){
|
||||||
BuildPlan req = getRequest(cursorX, cursorY);
|
BuildPlan req = getRequest(cursorX, cursorY);
|
||||||
if(req != null && req.breaking){
|
if(req != null && req.breaking){
|
||||||
player.builder().plans().remove(req);
|
player.unit().plans().remove(req);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
deleting = false;
|
deleting = false;
|
||||||
@@ -547,7 +547,7 @@ public class DesktopInput extends InputHandler{
|
|||||||
|
|
||||||
if(sreq != null){
|
if(sreq != null){
|
||||||
if(getRequest(sreq.x, sreq.y, sreq.block.size, sreq) != null){
|
if(getRequest(sreq.x, sreq.y, sreq.block.size, sreq) != null){
|
||||||
player.builder().plans().remove(sreq, true);
|
player.unit().plans().remove(sreq, true);
|
||||||
}
|
}
|
||||||
sreq = null;
|
sreq = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
|
|
||||||
@Remote(variants = Variant.one)
|
@Remote(variants = Variant.one)
|
||||||
public static void removeQueueBlock(int x, int y, boolean breaking){
|
public static void removeQueueBlock(int x, int y, boolean breaking){
|
||||||
player.builder().removeBuild(x, y, breaking);
|
player.unit().removeBuild(x, y, breaking);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(targets = Loc.both, called = Loc.server)
|
@Remote(targets = Loc.both, called = Loc.server)
|
||||||
@@ -383,7 +383,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
|
|
||||||
public Eachable<BuildPlan> allRequests(){
|
public Eachable<BuildPlan> allRequests(){
|
||||||
return cons -> {
|
return cons -> {
|
||||||
for(BuildPlan request : player.builder().plans()) cons.get(request);
|
for(BuildPlan request : player.unit().plans()) cons.get(request);
|
||||||
for(BuildPlan request : selectRequests) cons.get(request);
|
for(BuildPlan request : selectRequests) cons.get(request);
|
||||||
for(BuildPlan request : lineRequests) cons.get(request);
|
for(BuildPlan request : lineRequests) cons.get(request);
|
||||||
};
|
};
|
||||||
@@ -401,7 +401,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
player.typing = ui.chatfrag.shown();
|
player.typing = ui.chatfrag.shown();
|
||||||
|
|
||||||
if(player.isBuilder()){
|
if(player.isBuilder()){
|
||||||
player.builder().updateBuilding(isBuilding);
|
player.unit().updateBuilding(isBuilding);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(player.shooting && !wasShooting && player.unit().hasWeapons() && state.rules.unitAmmo && player.unit().ammo <= 0){
|
if(player.shooting && !wasShooting && player.unit().hasWeapons() && state.rules.unitAmmo && player.unit().ammo <= 0){
|
||||||
@@ -653,7 +653,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
return r2.overlaps(r1);
|
return r2.overlaps(r1);
|
||||||
};
|
};
|
||||||
|
|
||||||
for(BuildPlan req : player.builder().plans()){
|
for(BuildPlan req : player.unit().plans()){
|
||||||
if(test.get(req)) return req;
|
if(test.get(req)) return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -678,7 +678,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
Draw.color(Pal.remove);
|
Draw.color(Pal.remove);
|
||||||
Lines.stroke(1f);
|
Lines.stroke(1f);
|
||||||
|
|
||||||
for(BuildPlan req : player.builder().plans()){
|
for(BuildPlan req : player.unit().plans()){
|
||||||
if(req.breaking) continue;
|
if(req.breaking) continue;
|
||||||
if(req.bounds(Tmp.r2).overlaps(Tmp.r1)){
|
if(req.bounds(Tmp.r2).overlaps(Tmp.r1)){
|
||||||
drawBreaking(req);
|
drawBreaking(req);
|
||||||
@@ -740,7 +740,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
for(BuildPlan req : requests){
|
for(BuildPlan req : requests){
|
||||||
if(req.block != null && validPlace(req.x, req.y, req.block, req.rotation)){
|
if(req.block != null && validPlace(req.x, req.y, req.block, req.rotation)){
|
||||||
BuildPlan copy = req.copy();
|
BuildPlan copy = req.copy();
|
||||||
player.builder().addBuild(copy);
|
player.unit().addBuild(copy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -804,7 +804,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
//remove build requests
|
//remove build requests
|
||||||
Tmp.r1.set(result.x * tilesize, result.y * tilesize, (result.x2 - result.x) * tilesize, (result.y2 - result.y) * tilesize);
|
Tmp.r1.set(result.x * tilesize, result.y * tilesize, (result.x2 - result.x) * tilesize, (result.y2 - result.y) * tilesize);
|
||||||
|
|
||||||
Iterator<BuildPlan> it = player.builder().plans().iterator();
|
Iterator<BuildPlan> it = player.unit().plans().iterator();
|
||||||
while(it.hasNext()){
|
while(it.hasNext()){
|
||||||
BuildPlan req = it.next();
|
BuildPlan req = it.next();
|
||||||
if(!req.breaking && req.bounds(Tmp.r2).overlaps(Tmp.r1)){
|
if(!req.breaking && req.bounds(Tmp.r2).overlaps(Tmp.r1)){
|
||||||
@@ -1044,7 +1044,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean canShoot(){
|
public boolean canShoot(){
|
||||||
return block == null && !onConfigurable() && !isDroppingItem() && !player.builder().activelyBuilding() &&
|
return block == null && !onConfigurable() && !isDroppingItem() && !player.unit().activelyBuilding() &&
|
||||||
!(player.unit() instanceof Mechc && player.unit().isFlying());
|
!(player.unit() instanceof Mechc && player.unit().isFlying());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1090,7 +1090,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean validPlace(int x, int y, Block type, int rotation, BuildPlan ignore){
|
public boolean validPlace(int x, int y, Block type, int rotation, BuildPlan ignore){
|
||||||
for(BuildPlan req : player.builder().plans()){
|
for(BuildPlan req : player.unit().plans()){
|
||||||
if(req != ignore
|
if(req != ignore
|
||||||
&& !req.breaking
|
&& !req.breaking
|
||||||
&& req.block.bounds(req.x, req.y, Tmp.r1).overlaps(type.bounds(x, y, Tmp.r2))
|
&& req.block.bounds(req.x, req.y, Tmp.r1).overlaps(type.bounds(x, y, Tmp.r2))
|
||||||
@@ -1108,15 +1108,15 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
public void placeBlock(int x, int y, Block block, int rotation){
|
public void placeBlock(int x, int y, Block block, int rotation){
|
||||||
BuildPlan req = getRequest(x, y);
|
BuildPlan req = getRequest(x, y);
|
||||||
if(req != null){
|
if(req != null){
|
||||||
player.builder().plans().remove(req);
|
player.unit().plans().remove(req);
|
||||||
}
|
}
|
||||||
player.builder().addBuild(new BuildPlan(x, y, rotation, block, block.nextConfig()));
|
player.unit().addBuild(new BuildPlan(x, y, rotation, block, block.nextConfig()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void breakBlock(int x, int y){
|
public void breakBlock(int x, int y){
|
||||||
Tile tile = world.tile(x, y);
|
Tile tile = world.tile(x, y);
|
||||||
if(tile != null && tile.build != null) tile = tile.build.tile;
|
if(tile != null && tile.build != null) tile = tile.build.tile;
|
||||||
player.builder().addBuild(new BuildPlan(tile.x, tile.y));
|
player.unit().addBuild(new BuildPlan(tile.x, tile.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drawArrow(Block block, int x, int y, int rotation){
|
public void drawArrow(Block block, int x, int y, int rotation){
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(BuildPlan req : player.builder().plans()){
|
for(BuildPlan req : player.unit().plans()){
|
||||||
Tile other = world.tile(req.x, req.y);
|
Tile other = world.tile(req.x, req.y);
|
||||||
|
|
||||||
if(other == null || req.breaking) continue;
|
if(other == null || req.breaking) continue;
|
||||||
@@ -219,10 +219,10 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
BuildPlan copy = request.copy();
|
BuildPlan copy = request.copy();
|
||||||
|
|
||||||
if(other == null){
|
if(other == null){
|
||||||
player.builder().addBuild(copy);
|
player.unit().addBuild(copy);
|
||||||
}else if(!other.breaking && other.x == request.x && other.y == request.y && other.block.size == request.block.size){
|
}else if(!other.breaking && other.x == request.x && other.y == request.y && other.block.size == request.block.size){
|
||||||
player.builder().plans().remove(other);
|
player.unit().plans().remove(other);
|
||||||
player.builder().addBuild(copy);
|
player.unit().addBuild(copy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,10 +245,10 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
Boolp schem = () -> lastSchematic != null && !selectRequests.isEmpty();
|
Boolp schem = () -> lastSchematic != null && !selectRequests.isEmpty();
|
||||||
|
|
||||||
group.fill(t -> {
|
group.fill(t -> {
|
||||||
t.visible(() -> (player.builder().isBuilding() || block != null || mode == breaking || !selectRequests.isEmpty()) && !schem.get());
|
t.visible(() -> (player.unit().isBuilding() || block != null || mode == breaking || !selectRequests.isEmpty()) && !schem.get());
|
||||||
t.bottom().left();
|
t.bottom().left();
|
||||||
t.button("@cancel", Icon.cancel, () -> {
|
t.button("@cancel", Icon.cancel, () -> {
|
||||||
player.builder().clearBuilding();
|
player.unit().clearBuilding();
|
||||||
selectRequests.clear();
|
selectRequests.clear();
|
||||||
mode = none;
|
mode = none;
|
||||||
block = null;
|
block = null;
|
||||||
@@ -914,7 +914,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//update shooting if not building + not mining
|
//update shooting if not building + not mining
|
||||||
if(!player.builder().isBuilding() && player.unit().mineTile() == null){
|
if(!player.unit().isBuilding() && player.unit().mineTile == null){
|
||||||
|
|
||||||
//autofire targeting
|
//autofire targeting
|
||||||
if(manualShooting){
|
if(manualShooting){
|
||||||
|
|||||||
@@ -321,13 +321,8 @@ public class LExecutor{
|
|||||||
((LogicAI)unit.controller()).controller = exec.building(varThis);
|
((LogicAI)unit.controller()).controller = exec.building(varThis);
|
||||||
|
|
||||||
//clear old state
|
//clear old state
|
||||||
if(unit instanceof Minerc miner){
|
unit.mineTile = null;
|
||||||
miner.mineTile(null);
|
unit.clearBuilding();
|
||||||
}
|
|
||||||
|
|
||||||
if(unit instanceof Builderc builder){
|
|
||||||
builder.clearBuilding();
|
|
||||||
}
|
|
||||||
|
|
||||||
return (LogicAI)unit.controller();
|
return (LogicAI)unit.controller();
|
||||||
}
|
}
|
||||||
@@ -357,12 +352,8 @@ public class LExecutor{
|
|||||||
|
|
||||||
//stop mining/building
|
//stop mining/building
|
||||||
if(type == LUnitControl.stop){
|
if(type == LUnitControl.stop){
|
||||||
if(unit instanceof Minerc miner){
|
unit.mineTile = null;
|
||||||
miner.mineTile(null);
|
unit.clearBuilding();
|
||||||
}
|
|
||||||
if(unit instanceof Builderc build){
|
|
||||||
build.clearBuilding();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case within -> {
|
case within -> {
|
||||||
@@ -390,8 +381,8 @@ public class LExecutor{
|
|||||||
}
|
}
|
||||||
case mine -> {
|
case mine -> {
|
||||||
Tile tile = world.tileWorld(x1, y1);
|
Tile tile = world.tileWorld(x1, y1);
|
||||||
if(unit instanceof Minerc miner){
|
if(unit.canMine()){
|
||||||
miner.mineTile(miner.validMine(tile) ? tile : null);
|
unit.mineTile = unit.validMine(tile) ? tile : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case payDrop -> {
|
case payDrop -> {
|
||||||
@@ -432,12 +423,12 @@ public class LExecutor{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case build -> {
|
case build -> {
|
||||||
if(unit instanceof Builderc builder && exec.obj(p3) instanceof Block block){
|
if(unit.canBuild() && exec.obj(p3) instanceof Block block){
|
||||||
int x = World.toTile(x1), y = World.toTile(y1);
|
int x = World.toTile(x1), y = World.toTile(y1);
|
||||||
int rot = exec.numi(p4);
|
int rot = exec.numi(p4);
|
||||||
|
|
||||||
//reset state of last request when necessary
|
//reset state of last request when necessary
|
||||||
if(ai.plan.x != x || ai.plan.y != y || ai.plan.block != block || builder.plans().isEmpty()){
|
if(ai.plan.x != x || ai.plan.y != y || ai.plan.block != block || unit.plans.isEmpty()){
|
||||||
ai.plan.progress = 0;
|
ai.plan.progress = 0;
|
||||||
ai.plan.initialized = false;
|
ai.plan.initialized = false;
|
||||||
ai.plan.stuck = false;
|
ai.plan.stuck = false;
|
||||||
@@ -446,11 +437,11 @@ public class LExecutor{
|
|||||||
ai.plan.set(x, y, rot, block);
|
ai.plan.set(x, y, rot, block);
|
||||||
ai.plan.config = exec.obj(p5) instanceof Content c ? c : null;
|
ai.plan.config = exec.obj(p5) instanceof Content c ? c : null;
|
||||||
|
|
||||||
builder.clearBuilding();
|
unit.clearBuilding();
|
||||||
|
|
||||||
if(ai.plan.tile() != null){
|
if(ai.plan.tile() != null){
|
||||||
builder.updateBuilding(true);
|
unit.updateBuilding = true;
|
||||||
builder.addBuild(ai.plan);
|
unit.addBuild(ai.plan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ public class UnitType extends UnlockableContent{
|
|||||||
public int ammoCapacity = -1;
|
public int ammoCapacity = -1;
|
||||||
public AmmoType ammoType = AmmoTypes.copper;
|
public AmmoType ammoType = AmmoTypes.copper;
|
||||||
public int mineTier = -1;
|
public int mineTier = -1;
|
||||||
public float buildSpeed = 1f, mineSpeed = 1f;
|
public float buildSpeed = -1f, mineSpeed = 1f;
|
||||||
public Sound mineSound = Sounds.minebeam;
|
public Sound mineSound = Sounds.minebeam;
|
||||||
public float mineSoundVolume = 0.6f;
|
public float mineSoundVolume = 0.6f;
|
||||||
|
|
||||||
@@ -225,7 +225,7 @@ public class UnitType extends UnlockableContent{
|
|||||||
stats.addPercent(Stat.mineSpeed, mineSpeed);
|
stats.addPercent(Stat.mineSpeed, mineSpeed);
|
||||||
stats.add(Stat.mineTier, new BlockFilterValue(b -> b instanceof Floor f && f.itemDrop != null && f.itemDrop.hardness <= mineTier && !f.playerUnmineable));
|
stats.add(Stat.mineTier, new BlockFilterValue(b -> b instanceof Floor f && f.itemDrop != null && f.itemDrop.hardness <= mineTier && !f.playerUnmineable));
|
||||||
}
|
}
|
||||||
if(inst instanceof Builderc){
|
if(buildSpeed > 0){
|
||||||
stats.addPercent(Stat.buildSpeed, buildSpeed);
|
stats.addPercent(Stat.buildSpeed, buildSpeed);
|
||||||
}
|
}
|
||||||
if(inst instanceof Payloadc){
|
if(inst instanceof Payloadc){
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ public class PlacementFragment extends Fragment{
|
|||||||
Block tryRecipe = tile == null ? null : tile.block instanceof ConstructBlock ? ((ConstructBuild)tile).cblock : tile.block;
|
Block tryRecipe = tile == null ? null : tile.block instanceof ConstructBlock ? ((ConstructBuild)tile).cblock : tile.block;
|
||||||
Object tryConfig = tile == null ? null : tile.config();
|
Object tryConfig = tile == null ? null : tile.config();
|
||||||
|
|
||||||
for(BuildPlan req : player.builder().plans()){
|
for(BuildPlan req : player.unit().plans()){
|
||||||
if(!req.breaking && req.block.bounds(req.x, req.y, Tmp.r1).contains(Core.input.mouseWorld())){
|
if(!req.breaking && req.block.bounds(req.x, req.y, Tmp.r1).contains(Core.input.mouseWorld())){
|
||||||
tryRecipe = req.block;
|
tryRecipe = req.block;
|
||||||
tryConfig = req.config;
|
tryConfig = req.config;
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ public class ConstructBlock extends Block{
|
|||||||
if(control.input.buildWasAutoPaused && !control.input.isBuilding && player.isBuilder()){
|
if(control.input.buildWasAutoPaused && !control.input.isBuilding && player.isBuilder()){
|
||||||
control.input.isBuilding = true;
|
control.input.isBuilding = true;
|
||||||
}
|
}
|
||||||
player.builder().addBuild(new BuildPlan(tile.x, tile.y, rotation, cblock, lastConfig), false);
|
player.unit().addBuild(new BuildPlan(tile.x, tile.y, rotation, cblock, lastConfig), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ public interface Payload{
|
|||||||
return (T)payload;
|
return (T)payload;
|
||||||
}else if(type == payloadUnit){
|
}else if(type == payloadUnit){
|
||||||
byte id = read.b();
|
byte id = read.b();
|
||||||
|
if(EntityMapping.map(id) == null) throw new RuntimeException("No type with ID " + id + " found.");
|
||||||
Unit unit = (Unit)EntityMapping.map(id).get();
|
Unit unit = (Unit)EntityMapping.map(id).get();
|
||||||
unit.read(read);
|
unit.read(read);
|
||||||
return (T)new UnitPayload(unit);
|
return (T)new UnitPayload(unit);
|
||||||
|
|||||||
@@ -433,6 +433,15 @@ public class ApplicationTests{
|
|||||||
assertEquals(256, world.height());
|
assertEquals(256, world.height());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void load114Save(){
|
||||||
|
resetWorld();
|
||||||
|
SaveIO.load(Core.files.internal("114.msav"));
|
||||||
|
|
||||||
|
assertEquals(500, world.width());
|
||||||
|
assertEquals(500, world.height());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void arrayIterators(){
|
void arrayIterators(){
|
||||||
Seq<String> arr = Seq.with("a", "b" , "c", "d", "e", "f");
|
Seq<String> arr = Seq.with("a", "b" , "c", "d", "e", "f");
|
||||||
|
|||||||
BIN
tests/src/test/resources/114.msav
Normal file
BIN
tests/src/test/resources/114.msav
Normal file
Binary file not shown.
Reference in New Issue
Block a user