Merge branch 'master' of https://github.com/Anuken/Mindustry into 7.0-features
Conflicts: core/src/mindustry/ui/dialogs/PlanetDialog.java
This commit is contained in:
@@ -19,7 +19,8 @@ import static mindustry.Vars.*;
|
||||
public class Effect{
|
||||
private static final float shakeFalloff = 10000f;
|
||||
private static final EffectContainer container = new EffectContainer();
|
||||
private static final Seq<Effect> all = new Seq<>();
|
||||
|
||||
public static final Seq<Effect> all = new Seq<>();
|
||||
|
||||
private boolean initialized;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package mindustry.entities;
|
||||
|
||||
import arc.func.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
@@ -23,7 +24,9 @@ public class EntityCollisions{
|
||||
private Rect r2 = new Rect();
|
||||
|
||||
//entity collisions
|
||||
private Seq<Hitboxc> arrOut = new Seq<>();
|
||||
private Seq<Hitboxc> arrOut = new Seq<>(Hitboxc.class);
|
||||
private Cons<Hitboxc> hitCons = this::updateCollision;
|
||||
private Cons<QuadTree> treeCons = tree -> tree.intersect(r2, arrOut);
|
||||
|
||||
public void moveCheck(Hitboxc entity, float deltax, float deltay, SolidPred solidCheck){
|
||||
if(!solidCheck.solid(entity.tileX(), entity.tileY())){
|
||||
@@ -36,7 +39,7 @@ public class EntityCollisions{
|
||||
}
|
||||
|
||||
public void move(Hitboxc entity, float deltax, float deltay, SolidPred solidCheck){
|
||||
if(Math.abs(deltax) < 0.0001f & Math.abs(deltay) < 0.0001f) return;
|
||||
if(Math.abs(deltax) < 0.0001f & Math.abs(deltay) < 0.0001f) return;
|
||||
|
||||
boolean movedx = false;
|
||||
|
||||
@@ -213,28 +216,34 @@ public class EntityCollisions{
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Hitboxc> void collide(EntityGroup<T> groupa){
|
||||
groupa.each(solid -> {
|
||||
solid.hitbox(r1);
|
||||
r1.x += (solid.lastX() - solid.getX());
|
||||
r1.y += (solid.lastY() - solid.getY());
|
||||
groupa.each((Cons<T>)hitCons);
|
||||
}
|
||||
|
||||
solid.hitbox(r2);
|
||||
r2.merge(r1);
|
||||
private void updateCollision(Hitboxc solid){
|
||||
solid.hitbox(r1);
|
||||
r1.x += (solid.lastX() - solid.getX());
|
||||
r1.y += (solid.lastY() - solid.getY());
|
||||
|
||||
arrOut.clear();
|
||||
solid.hitbox(r2);
|
||||
r2.merge(r1);
|
||||
|
||||
//get all targets based on what entity wants to collide with
|
||||
solid.getCollisions(tree -> tree.intersect(r2, arrOut));
|
||||
arrOut.clear();
|
||||
|
||||
for(Hitboxc sc : arrOut){
|
||||
sc.hitbox(r1);
|
||||
if(r2.overlaps(r1)){
|
||||
checkCollide(solid, sc);
|
||||
//break out of loop when this object hits something
|
||||
if(!solid.isAdded()) return;
|
||||
}
|
||||
//get all targets based on what entity wants to collide with
|
||||
solid.getCollisions(treeCons);
|
||||
|
||||
var items = arrOut.items;
|
||||
int size = arrOut.size;
|
||||
|
||||
for(int i = 0; i < size; i++){
|
||||
Hitboxc sc = items[i];
|
||||
sc.hitbox(r1);
|
||||
if(r2.overlaps(r1)){
|
||||
checkCollide(solid, sc);
|
||||
//break out of loop when this object hits something
|
||||
if(!solid.isAdded()) return;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public interface SolidPred{
|
||||
|
||||
@@ -10,6 +10,7 @@ import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
@@ -105,7 +106,11 @@ public class EnergyFieldAbility extends Ability{
|
||||
});
|
||||
|
||||
if(hitBuildings){
|
||||
Units.nearbyBuildings(rx, ry, range, all::add);
|
||||
Units.nearbyBuildings(rx, ry, range, b -> {
|
||||
if(b.team != Team.derelict || state.rules.coreCapture){
|
||||
all.add(b);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
all.sort(h -> h.dst2(rx, ry));
|
||||
|
||||
@@ -118,36 +118,7 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
|
||||
type.update(self());
|
||||
|
||||
if(type.collidesTiles && type.collides && type.collidesGround){
|
||||
world.raycastEach(World.toTile(lastX()), World.toTile(lastY()), tileX(), tileY(), (x, y) -> {
|
||||
|
||||
Building build = world.build(x, y);
|
||||
if(build == null || !isAdded()) return false;
|
||||
|
||||
if(build.collide(self()) && type.testCollision(self(), build) && !build.dead() && (type.collidesTeam || build.team != team) && !(type.pierceBuilding && hasCollided(build.id))){
|
||||
boolean remove = false;
|
||||
|
||||
float health = build.health;
|
||||
|
||||
if(build.team != team){
|
||||
remove = build.collision(self());
|
||||
}
|
||||
|
||||
if(remove || type.collidesTeam){
|
||||
if(!type.pierceBuilding){
|
||||
hit = true;
|
||||
remove();
|
||||
}else{
|
||||
collided.add(build.id);
|
||||
}
|
||||
}
|
||||
|
||||
type.hitTile(self(), build, health, true);
|
||||
|
||||
return !type.pierceBuilding;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
tileRaycast(World.toTile(lastX()), World.toTile(lastY()), tileX(), tileY());
|
||||
}
|
||||
|
||||
if(type.pierceCap != -1 && collided.size >= type.pierceCap){
|
||||
@@ -156,6 +127,55 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
|
||||
}
|
||||
}
|
||||
|
||||
//copy-paste of World#raycastEach, inlined for lambda capture performance.
|
||||
@Override
|
||||
public void tileRaycast(int x0f, int y0f, int x1, int y1){
|
||||
int x = x0f, dx = Math.abs(x1 - x), sx = x < x1 ? 1 : -1;
|
||||
int y = y0f, dy = Math.abs(y1 - y), sy = y < y1 ? 1 : -1;
|
||||
int e2, err = dx - dy;
|
||||
|
||||
while(true){
|
||||
Building build = world.build(x, y);
|
||||
if(build != null && isAdded() && build.collide(self()) && type.testCollision(self(), build)
|
||||
&& !build.dead() && (type.collidesTeam || build.team != team) && !(type.pierceBuilding && hasCollided(build.id))){
|
||||
|
||||
boolean remove = false;
|
||||
float health = build.health;
|
||||
|
||||
if(build.team != team){
|
||||
remove = build.collision(self());
|
||||
}
|
||||
|
||||
if(remove || type.collidesTeam){
|
||||
if(!type.pierceBuilding){
|
||||
hit = true;
|
||||
remove();
|
||||
}else{
|
||||
collided.add(build.id);
|
||||
}
|
||||
}
|
||||
|
||||
type.hitTile(self(), build, health, true);
|
||||
|
||||
//stop raycasting when building is hit
|
||||
if(type.pierceBuilding) return;
|
||||
}
|
||||
|
||||
if(x == x1 && y == y1) break;
|
||||
|
||||
e2 = 2 * err;
|
||||
if(e2 > -dy){
|
||||
err -= dy;
|
||||
x += sx;
|
||||
}
|
||||
|
||||
if(e2 < dx){
|
||||
err += dx;
|
||||
y += sy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
Draw.z(type.layer);
|
||||
|
||||
@@ -45,6 +45,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
|
||||
transient String lastText = "";
|
||||
transient float textFadeTime;
|
||||
transient private Unit lastReadUnit = Nulls.unit;
|
||||
transient private int wrongReadUnits;
|
||||
transient @Nullable Unit justSwitchFrom, justSwitchTo;
|
||||
|
||||
public boolean isBuilder(){
|
||||
@@ -104,9 +105,15 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
|
||||
//reason: we know the server is lying here, essentially skip the unit snapshot because we know the client's information is more recent
|
||||
if(isLocal() && unit == justSwitchFrom && justSwitchFrom != null && justSwitchTo != null){
|
||||
unit = justSwitchTo;
|
||||
//if several snapshots have passed and this unit is still incorrect, something's wrong
|
||||
if(++wrongReadUnits >= 2){
|
||||
justSwitchFrom = null;
|
||||
wrongReadUnits = 0;
|
||||
}
|
||||
}else{
|
||||
justSwitchFrom = null;
|
||||
justSwitchTo = null;
|
||||
wrongReadUnits = 0;
|
||||
}
|
||||
|
||||
//simulate a unit change after sync
|
||||
|
||||
@@ -40,8 +40,8 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{
|
||||
|
||||
@Import int id;
|
||||
@Import float x, y;
|
||||
@Import boolean added;
|
||||
|
||||
transient private boolean mismatch = false;
|
||||
transient float accepting, updateTime, lastRipple = Time.time + Mathf.random(40f);
|
||||
float amount;
|
||||
Tile tile;
|
||||
@@ -79,9 +79,12 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{
|
||||
return;
|
||||
}
|
||||
|
||||
if(Puddles.get(tile) != self()){
|
||||
mismatch = true;
|
||||
remove();
|
||||
if(Puddles.get(tile) != self() && added){
|
||||
//force removal without pool free
|
||||
Groups.all.remove(self());
|
||||
Groups.draw.remove(self());
|
||||
Groups.puddle.remove(self());
|
||||
added = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -134,9 +137,7 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{
|
||||
|
||||
@Override
|
||||
public void remove(){
|
||||
if(!mismatch){
|
||||
Puddles.remove(tile);
|
||||
}
|
||||
Puddles.remove(tile);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -46,19 +46,19 @@ public class AIController implements UnitController{
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected AIController fallback(){
|
||||
public AIController fallback(){
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean useFallback(){
|
||||
public boolean useFallback(){
|
||||
return false;
|
||||
}
|
||||
|
||||
protected UnitCommand command(){
|
||||
public UnitCommand command(){
|
||||
return unit.team.data().command;
|
||||
}
|
||||
|
||||
protected void updateVisuals(){
|
||||
public void updateVisuals(){
|
||||
if(unit.isFlying()){
|
||||
unit.wobble();
|
||||
|
||||
@@ -66,21 +66,21 @@ public class AIController implements UnitController{
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateMovement(){
|
||||
public void updateMovement(){
|
||||
|
||||
}
|
||||
|
||||
protected void updateTargeting(){
|
||||
public void updateTargeting(){
|
||||
if(unit.hasWeapons()){
|
||||
updateWeapons();
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean invalid(Teamc target){
|
||||
public boolean invalid(Teamc target){
|
||||
return Units.invalidateTarget(target, unit.team, unit.x, unit.y);
|
||||
}
|
||||
|
||||
protected void pathfind(int pathTarget){
|
||||
public void pathfind(int pathTarget){
|
||||
int costType = unit.pathType();
|
||||
|
||||
Tile tile = unit.tileOn();
|
||||
@@ -92,7 +92,7 @@ public class AIController implements UnitController{
|
||||
unit.moveAt(vec.trns(unit.angleTo(targetTile.worldx(), targetTile.worldy()), unit.speed()));
|
||||
}
|
||||
|
||||
protected void updateWeapons(){
|
||||
public void updateWeapons(){
|
||||
float rotation = unit.rotation - 90;
|
||||
boolean ret = retarget();
|
||||
|
||||
@@ -146,45 +146,45 @@ public class AIController implements UnitController{
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean checkTarget(Teamc target, float x, float y, float range){
|
||||
public boolean checkTarget(Teamc target, float x, float y, float range){
|
||||
return Units.invalidateTarget(target, unit.team, x, y, range);
|
||||
}
|
||||
|
||||
protected boolean shouldShoot(){
|
||||
public boolean shouldShoot(){
|
||||
return true;
|
||||
}
|
||||
|
||||
protected Teamc targetFlag(float x, float y, BlockFlag flag, boolean enemy){
|
||||
public Teamc targetFlag(float x, float y, BlockFlag flag, boolean enemy){
|
||||
if(unit.team == Team.derelict) return null;
|
||||
Tile target = Geometry.findClosest(x, y, enemy ? indexer.getEnemy(unit.team, flag) : indexer.getAllied(unit.team, flag));
|
||||
return target == null ? null : target.build;
|
||||
}
|
||||
|
||||
protected Teamc target(float x, float y, float range, boolean air, boolean ground){
|
||||
public Teamc target(float x, float y, float range, boolean air, boolean ground){
|
||||
return Units.closestTarget(unit.team, x, y, range, u -> u.checkTarget(air, ground), t -> ground);
|
||||
}
|
||||
|
||||
protected boolean retarget(){
|
||||
public boolean retarget(){
|
||||
return timer.get(timerTarget, target == null ? 40 : 90);
|
||||
}
|
||||
|
||||
protected Teamc findMainTarget(float x, float y, float range, boolean air, boolean ground){
|
||||
public Teamc findMainTarget(float x, float y, float range, boolean air, boolean ground){
|
||||
return findTarget(x, y, range, air, ground);
|
||||
}
|
||||
|
||||
protected Teamc findTarget(float x, float y, float range, boolean air, boolean ground){
|
||||
public Teamc findTarget(float x, float y, float range, boolean air, boolean ground){
|
||||
return target(x, y, range, air, ground);
|
||||
}
|
||||
|
||||
protected void init(){
|
||||
public void init(){
|
||||
|
||||
}
|
||||
|
||||
protected @Nullable Tile getClosestSpawner(){
|
||||
public @Nullable Tile getClosestSpawner(){
|
||||
return Geometry.findClosest(unit.x, unit.y, Vars.spawner.getSpawns());
|
||||
}
|
||||
|
||||
protected void unloadPayloads(){
|
||||
public void unloadPayloads(){
|
||||
if(unit instanceof Payloadc pay && pay.hasPayload() && target instanceof Building && pay.payloads().peek() instanceof UnitPayload){
|
||||
if(target.within(unit, Math.max(unit.type().range + 1f, 75f))){
|
||||
pay.dropLastPayload();
|
||||
@@ -192,11 +192,11 @@ public class AIController implements UnitController{
|
||||
}
|
||||
}
|
||||
|
||||
protected void circle(Position target, float circleLength){
|
||||
public void circle(Position target, float circleLength){
|
||||
circle(target, circleLength, unit.speed());
|
||||
}
|
||||
|
||||
protected void circle(Position target, float circleLength, float speed){
|
||||
public void circle(Position target, float circleLength, float speed){
|
||||
if(target == null) return;
|
||||
|
||||
vec.set(target).sub(unit);
|
||||
@@ -210,11 +210,11 @@ public class AIController implements UnitController{
|
||||
unit.moveAt(vec);
|
||||
}
|
||||
|
||||
protected void moveTo(Position target, float circleLength){
|
||||
public void moveTo(Position target, float circleLength){
|
||||
moveTo(target, circleLength, 100f);
|
||||
}
|
||||
|
||||
protected void moveTo(Position target, float circleLength, float smooth){
|
||||
public void moveTo(Position target, float circleLength, float smooth){
|
||||
if(target == null) return;
|
||||
|
||||
vec.set(target).sub(unit);
|
||||
|
||||
Reference in New Issue
Block a user