diff --git a/core/assets/baseparts/752942460573057196.msch b/core/assets/baseparts/752942460573057196.msch index 57b5e83b0a..6f81df2b4e 100644 Binary files a/core/assets/baseparts/752942460573057196.msch and b/core/assets/baseparts/752942460573057196.msch differ diff --git a/core/src/mindustry/async/PhysicsProcess.java b/core/src/mindustry/async/PhysicsProcess.java index 5e8b1be923..0f49176c57 100644 --- a/core/src/mindustry/async/PhysicsProcess.java +++ b/core/src/mindustry/async/PhysicsProcess.java @@ -43,6 +43,7 @@ public class PhysicsProcess implements AsyncProcess{ //find entities without bodies and assign them for(Physicsc entity : group){ boolean grounded = entity.isGrounded(); + int bits = grounded ? flying.maskBits : ground.maskBits; if(entity.physref() == null){ //add bodies to entities that have none @@ -66,12 +67,9 @@ public class PhysicsProcess implements AsyncProcess{ //save last position PhysicRef ref = entity.physref(); - if(ref.wasGround != grounded){ - if(ref.body.getFixtureList().isEmpty()) continue; - + if(ref.body.getFixtureList().any() && ref.body.getFixtureList().first().getFilterData().categoryBits != bits){ //set correct filter ref.body.getFixtureList().first().setFilterData(grounded ? ground : flying); - ref.wasGround = grounded; } ref.velocity.set(entity.deltaX(), entity.deltaY()); @@ -143,10 +141,9 @@ public class PhysicsProcess implements AsyncProcess{ } public static class PhysicRef{ - Physicsc entity; - Body body; - boolean wasGround = true; - Vec2 lastPosition = new Vec2(), delta = new Vec2(), velocity = new Vec2(), lastVelocity = new Vec2(), position = new Vec2(); + public Physicsc entity; + public Body body; + public Vec2 lastPosition = new Vec2(), delta = new Vec2(), velocity = new Vec2(), lastVelocity = new Vec2(), position = new Vec2(); public PhysicRef(Physicsc entity, Body body){ this.entity = entity; diff --git a/core/src/mindustry/core/NetServer.java b/core/src/mindustry/core/NetServer.java index f15c225f48..6174798e96 100644 --- a/core/src/mindustry/core/NetServer.java +++ b/core/src/mindustry/core/NetServer.java @@ -485,7 +485,7 @@ public class NetServer implements ApplicationListener{ data.stream = new ByteArrayInputStream(stream.toByteArray()); player.con.sendStream(data); - Log.debug("Packed @ invalid world data.", stream.size()); + Log.debug("Packed @ bytes of world data.", stream.size()); } public void addPacketHandler(String type, Cons2 handler){ diff --git a/core/src/mindustry/entities/Units.java b/core/src/mindustry/entities/Units.java index c93ecaffce..6460e9ce8d 100644 --- a/core/src/mindustry/entities/Units.java +++ b/core/src/mindustry/entities/Units.java @@ -99,7 +99,7 @@ public class Units{ nearby(x, y, width, height, unit -> { if(boolResult) return; - if(unit.isGrounded() == ground){ + if((unit.isGrounded() && !unit.type().hovering) == ground){ unit.hitbox(hitrect); if(hitrect.overlaps(x, y, width, height)){ diff --git a/core/src/mindustry/entities/comp/LegsComp.java b/core/src/mindustry/entities/comp/LegsComp.java index 9cc5d876e2..68c0de5f00 100644 --- a/core/src/mindustry/entities/comp/LegsComp.java +++ b/core/src/mindustry/entities/comp/LegsComp.java @@ -30,6 +30,30 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{ collisions.moveCheck(this, cx, cy, !type.allowLegStep ? EntityCollisions::solid : EntityCollisions::legsSolid); } + @Override + public void add(){ + resetLegs(); + } + + public void resetLegs(){ + float rot = baseRotation; + int count = type.legCount; + float legLength = type.legLength; + + this.legs = new Leg[count]; + + float spacing = 360f / count; + + for(int i = 0; i < legs.length; i++){ + Leg l = new Leg(); + + l.joint.trns(i * spacing + rot, legLength/2f + type.legBaseOffset).add(x, y); + l.base.trns(i * spacing + rot, legLength + type.legBaseOffset).add(x, y); + + legs[i] = l; + } + } + @Override public void update(){ if(Mathf.dst(deltaX(), deltaY()) > 0.001f){ @@ -37,23 +61,11 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{ } float rot = baseRotation; - int count = type.legCount; float legLength = type.legLength; //set up initial leg positions if(legs.length != type.legCount){ - this.legs = new Leg[count]; - - float spacing = 360f / count; - - for(int i = 0; i < legs.length; i++){ - Leg l = new Leg(); - - l.joint.trns(i * spacing + rot, legLength/2f + type.legBaseOffset).add(x, y); - l.base.trns(i * spacing + rot, legLength + type.legBaseOffset).add(x, y); - - legs[i] = l; - } + resetLegs(); } float moveSpeed = type.legSpeed; diff --git a/core/src/mindustry/mod/Scripts.java b/core/src/mindustry/mod/Scripts.java index d2009187f7..14a9e4326f 100644 --- a/core/src/mindustry/mod/Scripts.java +++ b/core/src/mindustry/mod/Scripts.java @@ -22,7 +22,7 @@ public class Scripts implements Disposable{ private final Seq blacklist = Seq.with(".net.", "java.net", "files", "reflect", "javax", "rhino", "file", "channels", "jdk", "runtime", "util.os", "rmi", "security", "org.", "sun.", "beans", "sql", "http", "exec", "compiler", "process", "system", ".awt", "socket", "classloader", "oracle", "invoke", "java.util.function", "java.util.stream", "org."); - private final Seq whitelist = Seq.with("mindustry.net", "netserver", "netclient", "com.sun.proxy.$proxy", "mindustry.gen.", "mindustry.logic."); + private final Seq whitelist = Seq.with("mindustry.net", "netserver", "netclient", "com.sun.proxy.$proxy", "mindustry.gen.", "mindustry.logic.", "mindustry.async."); private final Context context; private final Scriptable scope; private boolean errored; diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index 3a83bb9cb7..973fd13c6f 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -112,6 +112,17 @@ public class UnitType extends UnlockableContent{ return unit; } + public Unit spawn(Team team, float x, float y){ + Unit out = create(team); + out.set(x, y); + out.add(); + return out; + } + + public Unit spawn(float x, float y){ + return spawn(state.rules.defaultTeam, x, y); + } + public boolean hasWeapons(){ return weapons.size > 0; } diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index 255e269ecb..3e3006383f 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -196,7 +196,7 @@ public class Block extends UnlockableContent{ /** Whether this block has instant transfer.*/ public boolean instantTransfer = false; - protected Prov entityType = null; //initialized later + public Prov buildType = null; //initialized later public ObjectMap, Cons2> configurations = new ObjectMap<>(); protected TextureRegion[] generatedIcons; @@ -217,7 +217,7 @@ public class Block extends UnlockableContent{ public Block(String name){ super(name); - initEntity(); + initBuilding(); } public void drawBase(Tile tile){ @@ -499,8 +499,8 @@ public class Block extends UnlockableContent{ return destructible || update; } - public final Building newEntity(){ - return entityType.get(); + public final Building newBuilding(){ + return buildType.get(); } public Rect bounds(int x, int y, Rect rect){ @@ -576,7 +576,7 @@ public class Block extends UnlockableContent{ Arrays.sort(requirements, Structs.comparingInt(i -> i.item.id)); } - protected void initEntity(){ + protected void initBuilding(){ //attempt to find the first declared class and use it as the entity type try{ Class current = getClass(); @@ -585,13 +585,13 @@ public class Block extends UnlockableContent{ current = current.getSuperclass(); } - while(entityType == null && Block.class.isAssignableFrom(current)){ + while(buildType == null && Block.class.isAssignableFrom(current)){ //first class that is subclass of Building Class type = Structs.find(current.getDeclaredClasses(), t -> Building.class.isAssignableFrom(t) && !t.isInterface()); if(type != null){ //these are inner classes, so they have an implicit parameter generated Constructor cons = (Constructor)type.getDeclaredConstructor(type.getDeclaringClass()); - entityType = () -> { + buildType = () -> { try{ return cons.newInstance(this); }catch(Exception e){ @@ -607,9 +607,9 @@ public class Block extends UnlockableContent{ }catch(Throwable ignored){ } - if(entityType == null){ + if(buildType == null){ //assign default value - entityType = Building::create; + buildType = Building::create; } } diff --git a/core/src/mindustry/world/Tile.java b/core/src/mindustry/world/Tile.java index 8d6b0841ae..ba303750e1 100644 --- a/core/src/mindustry/world/Tile.java +++ b/core/src/mindustry/world/Tile.java @@ -45,7 +45,7 @@ public class Tile implements Position, QuadTreeObject, Displayable{ this.block = wall; //update entity and create it if needed - changeEntity(Team.derelict, wall::newEntity, 0); + changeEntity(Team.derelict, wall::newBuilding, 0); changed(); } @@ -174,7 +174,7 @@ public class Tile implements Position, QuadTreeObject, Displayable{ } public void setBlock(@NonNull Block type, Team team, int rotation){ - setBlock(type, team, rotation, type::newEntity); + setBlock(type, team, rotation, type::newBuilding); } public void setBlock(@NonNull Block type, Team team, int rotation, Prov entityprov){ diff --git a/core/src/mindustry/world/blocks/environment/Floor.java b/core/src/mindustry/world/blocks/environment/Floor.java index 410980bcff..6640613779 100644 --- a/core/src/mindustry/world/blocks/environment/Floor.java +++ b/core/src/mindustry/world/blocks/environment/Floor.java @@ -103,9 +103,8 @@ public class Floor extends Block{ super.init(); if(wall == Blocks.air){ - wall = content.block(name + "Rocks"); - if(wall == null) wall = content.block(name + "rocks"); - if(wall == null) wall = content.block(name.replace("darksand", "dune") + "rocks"); + wall = content.block(name + "-wall"); + if(wall == null) wall = content.block(name.replace("darksand", "dune") + "-wall"); } //keep default value if not found... diff --git a/core/src/mindustry/world/blocks/payloads/BlockPayload.java b/core/src/mindustry/world/blocks/payloads/BlockPayload.java index fe91be7035..3fc87dbe6b 100644 --- a/core/src/mindustry/world/blocks/payloads/BlockPayload.java +++ b/core/src/mindustry/world/blocks/payloads/BlockPayload.java @@ -14,7 +14,7 @@ public class BlockPayload implements Payload{ public Building entity; public BlockPayload(Block block, Team team){ - this.entity = block.newEntity().create(block, team); + this.entity = block.newBuilding().create(block, team); } public BlockPayload(Building entity){ diff --git a/tests/src/test/java/ApplicationTests.java b/tests/src/test/java/ApplicationTests.java index f13f430a4d..d689dbd5df 100644 --- a/tests/src/test/java/ApplicationTests.java +++ b/tests/src/test/java/ApplicationTests.java @@ -377,7 +377,7 @@ public class ApplicationTests{ world.tile(length + 1, 0).setBlock(new Block("___"){{ hasItems = true; destructible = true; - entityType = () -> new Building(){ + buildType = () -> new Building(){ @Override public void handleItem(Building source, Item item){ itemsa[0] ++; diff --git a/tests/src/test/java/power/ItemLiquidGeneratorTests.java b/tests/src/test/java/power/ItemLiquidGeneratorTests.java index 64959780d1..08f636c566 100644 --- a/tests/src/test/java/power/ItemLiquidGeneratorTests.java +++ b/tests/src/test/java/power/ItemLiquidGeneratorTests.java @@ -39,7 +39,7 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ powerProduction = 0.1f; itemDuration = fakeItemDuration; maxLiquidGenerate = maximumLiquidUsage; - entityType = ItemLiquidGeneratorBuild::new; + buildType = ItemLiquidGeneratorBuild::new; } @Override diff --git a/tests/src/test/java/power/PowerTestFixture.java b/tests/src/test/java/power/PowerTestFixture.java index 1c888070bf..994130a596 100644 --- a/tests/src/test/java/power/PowerTestFixture.java +++ b/tests/src/test/java/power/PowerTestFixture.java @@ -43,21 +43,21 @@ public class PowerTestFixture{ protected static PowerGenerator createFakeProducerBlock(float producedPower){ return new PowerGenerator("fakegen"){{ - entityType = () -> new GeneratorBuild(); + buildType = () -> new GeneratorBuild(); powerProduction = producedPower; }}; } protected static Battery createFakeBattery(float capacity){ return new Battery("fakebattery"){{ - entityType = () -> new BatteryBuild(); + buildType = () -> new BatteryBuild(); consumes.powerBuffered(capacity); }}; } protected static Block createFakeDirectConsumer(float powerPerTick){ return new PowerBlock("fakedirectconsumer"){{ - entityType = Building::create; + buildType = Building::create; consumes.power(powerPerTick); }}; } @@ -86,7 +86,7 @@ public class PowerTestFixture{ Reflect.set(Tile.class, tile, "floor", Blocks.sand); // Simulate the "changed" method. Calling it through reflections would require half the game to be initialized. - tile.build = block.newEntity().init(tile, Team.sharded, false, 0); + tile.build = block.newBuilding().init(tile, Team.sharded, false, 0); if(block.hasPower){ tile.build.power.graph = new PowerGraph(){ //assume there's always something consuming power