diff --git a/annotations/src/main/java/mindustry/annotations/impl/EntityProcess.java b/annotations/src/main/java/mindustry/annotations/impl/EntityProcess.java index c8b1739013..8af36efafc 100644 --- a/annotations/src/main/java/mindustry/annotations/impl/EntityProcess.java +++ b/annotations/src/main/java/mindustry/annotations/impl/EntityProcess.java @@ -335,6 +335,24 @@ public class EntityProcess extends BaseProcessor{ idBuilder.addStaticBlock(idStore.build()); + //create mock types of all components + for(Stype component : allComponents){ + + + Array dependencies = getDependencies(component); + Array out = new Array<>(); + out.add(component); + out.addAll(component.superclasses()); + dependencies.each(dep -> { + out.add(dep); + out.addAll(dep.superclasses()); + }); + + out.distinct(); + + Log.info("Dependencies of {0}:\n{1}\n\n", component, out.toString("\n", s -> "&lb> " + s)); + } + write(idBuilder); }else{ //round 2: generate actual classes and implement interfaces diff --git a/annotations/src/main/java/mindustry/annotations/util/Selement.java b/annotations/src/main/java/mindustry/annotations/util/Selement.java index f4ec31a39b..12bf900c21 100644 --- a/annotations/src/main/java/mindustry/annotations/util/Selement.java +++ b/annotations/src/main/java/mindustry/annotations/util/Selement.java @@ -54,11 +54,11 @@ public class Selement{ @Override public int hashCode(){ - return e.hashCode(); + return toString().hashCode(); } @Override public boolean equals(Object o){ - return o != null && o.getClass() == getClass() && ((Selement)o).e.equals(e); + return o != null && toString().equals(o.toString()); } } diff --git a/annotations/src/main/java/mindustry/annotations/util/Stype.java b/annotations/src/main/java/mindustry/annotations/util/Stype.java index 21d49c5c6a..0fc9672661 100644 --- a/annotations/src/main/java/mindustry/annotations/util/Stype.java +++ b/annotations/src/main/java/mindustry/annotations/util/Stype.java @@ -25,13 +25,7 @@ public class Stype extends Selement{ } public Array superclasses(){ - Array out = new Array<>(); - Stype sup = superclass(); - while(!sup.name().equals("Object")){ - out.add(sup); - sup = sup.superclass(); - } - return out; + return Array.with(BaseProcessor.typeu.directSupertypes(mirror())).map(Stype::of); } public Stype superclass(){ diff --git a/annotations/src/main/resources/classids.properties b/annotations/src/main/resources/classids.properties index 8df63669ff..462b3bb974 100644 --- a/annotations/src/main/resources/classids.properties +++ b/annotations/src/main/resources/classids.properties @@ -4,5 +4,6 @@ mindustry.entities.def.EntityDefs.DecalDef=1 mindustry.entities.def.EntityDefs.EffectDef=2 mindustry.entities.def.EntityDefs.TileDef=3 mindustry.entities.def.EntityDefs.GenericUnitDef=5 +mindustry.entities.def.EntityDefs.GenericBuilderDef=6 mindustry.entities.def.EntityDefs.BulletDef=0 mindustry.entities.def.EntityDefs.PlayerDef=4 \ No newline at end of file diff --git a/core/src/mindustry/core/NetClient.java b/core/src/mindustry/core/NetClient.java index 1350db1854..70c1766a3a 100644 --- a/core/src/mindustry/core/NetClient.java +++ b/core/src/mindustry/core/NetClient.java @@ -508,11 +508,11 @@ public class NetClient implements ApplicationListener{ if(timer.get(0, playerSyncTime)){ BuildRequest[] requests; //limit to 10 to prevent buffer overflows - int usedRequests = Math.min(player.buildQueue().size, 10); + int usedRequests = Math.min(player.builder().requests().size, 10); requests = new BuildRequest[usedRequests]; for(int i = 0; i < usedRequests; i++){ - requests[i] = player.buildQueue().get(i); + requests[i] = player.builder().requests().get(i); } Call.onClientShapshot(lastSent++, player.x, player.y, diff --git a/core/src/mindustry/core/NetServer.java b/core/src/mindustry/core/NetServer.java index 5d20bc2b13..2fe65a43e3 100644 --- a/core/src/mindustry/core/NetServer.java +++ b/core/src/mindustry/core/NetServer.java @@ -513,7 +513,7 @@ public class NetServer implements ApplicationListener{ player.isBoosting = boosting; player.isShooting = shooting; player.isBuilding = building; - player.buildQueue().clear(); + player.builder().requests().clear(); for(BuildRequest req : requests){ if(req == null) continue; @@ -536,7 +536,7 @@ public class NetServer implements ApplicationListener{ connection.rejectedRequests.add(req); continue; } - player.buildQueue().addLast(req); + player.builder().requests().addLast(req); } connection.rejectedRequests.clear(); diff --git a/core/src/mindustry/entities/def/EntityComps.java b/core/src/mindustry/entities/def/EntityComps.java index 8b42a06c58..d52ff89b15 100644 --- a/core/src/mindustry/entities/def/EntityComps.java +++ b/core/src/mindustry/entities/def/EntityComps.java @@ -1,6 +1,7 @@ package mindustry.entities.def; import arc.*; +import arc.func.*; import arc.graphics.*; import arc.graphics.g2d.*; import arc.math.*; @@ -677,7 +678,17 @@ public class EntityComps{ @Component abstract static class PlayerComp implements UnitController, Entityc, Syncc, Timerc{ + //TODO mock these properly private static final Unitc noUnit = GenericUnitEntity.create(); + private static final Builderc noBuilder = GenericBuilderEntity.create().with(s -> s.requests(new Queue(){ + @Override + public void addLast(BuildRequest object){ + } + + @Override + public void addFirst(BuildRequest object){ + } + })); @NonNull @ReadOnly Unitc unit = noUnit; @@ -691,6 +702,14 @@ public class EntityComps{ @Nullable String lastText; float textFadeTime; + public boolean isBuilder(){ + return unit instanceof Builderc; + } + + public boolean isMiner(){ + return unit instanceof Minerc; + } + public @Nullable Tilec closestCore(){ return state.teams.closestCore(x(), y(), team); } @@ -732,6 +751,13 @@ public class EntityComps{ return unit; } + public Builderc builder(){ + if(!(unit instanceof Builderc)){ + return noBuilder; + } + return (Builderc)unit; + } + public void unit(Unitc unit){ if(unit == null) throw new IllegalArgumentException("Unit cannot be null. Use clearUnit() instead."); this.unit = unit; @@ -1287,7 +1313,7 @@ public class EntityComps{ transient float x, y, rotation; - @ReadOnly Queue requests = new Queue<>(); + Queue requests = new Queue<>(); float buildSpeed = 1f; //boolean building; @@ -1782,6 +1808,11 @@ public class EntityComps{ return (T)this; } + T with(Cons cons){ + cons.get((T)this); + return (T)this; + } + @InternalImpl abstract int classId(); diff --git a/core/src/mindustry/entities/def/EntityDefs.java b/core/src/mindustry/entities/def/EntityDefs.java index f179911a49..3c9122c808 100644 --- a/core/src/mindustry/entities/def/EntityDefs.java +++ b/core/src/mindustry/entities/def/EntityDefs.java @@ -22,4 +22,7 @@ class EntityDefs{ @EntityDef({UnitComp.class}) class GenericUnitDef{} + + @EntityDef({BuilderComp.class}) + class GenericBuilderDef{} } diff --git a/core/src/mindustry/input/DesktopInput.java b/core/src/mindustry/input/DesktopInput.java index 583ba5a644..f777b73e44 100644 --- a/core/src/mindustry/input/DesktopInput.java +++ b/core/src/mindustry/input/DesktopInput.java @@ -376,7 +376,7 @@ public class DesktopInput extends InputHandler{ deleting = true; }else if(selected != null){ //only begin shooting if there's no cursor event - if(!tileTapped(selected) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && (player.buildQueue().size == 0 || !player.isBuilding) && !droppingItem && + if(!tileTapped(selected) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && (player.builder().requests().size == 0 || !player.isBuilding) && !droppingItem && !tryBeginMine(selected) && player.getMineTile() == null && !Core.scene.hasKeyboard()){ player.isShooting = true; } @@ -400,7 +400,7 @@ public class DesktopInput extends InputHandler{ if(Core.input.keyDown(Binding.select) && mode == none && !isPlacing() && deleting){ BuildRequest req = getRequest(cursorX, cursorY); if(req != null && req.breaking){ - player.buildQueue().remove(req); + player.builder().requests().remove(req); } }else{ deleting = false; @@ -431,7 +431,7 @@ public class DesktopInput extends InputHandler{ if(sreq != null){ if(getRequest(sreq.x, sreq.y, sreq.block.size, sreq) != null){ - player.buildQueue().remove(sreq, true); + player.builder().requests().remove(sreq, true); } sreq = null; } diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index 7c7c0eef8f..e4bfbfcfae 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -96,17 +96,17 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ @Remote(variants = Variant.one) public static void removeQueueBlock(int x, int y, boolean breaking){ - player.removeRequest(x, y, breaking); + player.builder().removeBuild(x, y, breaking); } @Remote(targets = Loc.client, called = Loc.server) public static void dropItem(Playerc player, float angle){ - if(net.server() && player.item().amount <= 0){ + if(net.server() && player.unit().stack().amount <= 0){ throw new ValidateException(player, "Player cannot drop an item."); } - Fx.dropItem.at(player.x, player.y, angle, Color.white, player.item().item); - player.clearItem(); + Fx.dropItem.at(player.x(), player.y(), angle, Color.white, player.unit().item()); + player.unit().clearItem(); } @Remote(targets = Loc.both, called = Loc.server, forward = true, unreliable = true) @@ -127,53 +127,34 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ @Remote(targets = Loc.both, forward = true, called = Loc.server) public static void transferInventory(Playerc player, Tile tile){ if(player == null) return; - if(net.server() && (player.item().amount <= 0 || player.isTransferring|| !Units.canInteract(player, tile) || + if(net.server() && (player.unit().stack().amount <= 0 || !Units.canInteract(player, tile) || !netServer.admins.allowAction(player, ActionType.depositItem, tile, action -> { - action.itemAmount = player.item().amount; - action.item = player.item().item; + action.itemAmount = player.unit().stack().amount; + action.item = player.unit().item(); }))){ throw new ValidateException(player, "Player cannot transfer an item."); } if(tile.entity == null) return; - player.isTransferring = true; - - Item item = player.item().item; - int amount = player.item().amount; - int accepted = tile.block().acceptStack(item, amount, tile, player); - player.item().amount -= accepted; + Item item = player.unit().item(); + int amount = player.unit().stack().amount; + int accepted = tile.block().acceptStack(item, amount, tile, player.unit()); + player.unit().stack().amount -= accepted; int sent = Mathf.clamp(accepted / 4, 1, 8); - int removed = accepted / sent; - int[] remaining = {accepted, accepted}; Block block = tile.block(); Core.app.post(() -> Events.fire(new DepositEvent(tile, player, item, accepted))); for(int i = 0; i < sent; i++){ - boolean end = i == sent - 1; - Time.run(i * 3, () -> { - tile.block().getStackOffset(item, tile, stackTrns); + tile.block().getStackOffset(item, tile, stackTrns); - ItemTransfer.create(item, - player.x + Angles.trnsx(player.rotation + 180f, backTrns), player.y + Angles.trnsy(player.rotation + 180f, backTrns), - new Vec2(tile.drawx() + stackTrns.x, tile.drawy() + stackTrns.y), () -> { - if(tile.block() != block || tile.entity == null || tile.entity.items() == null) return; + createItemTransfer(item, player.x() + Angles.trnsx(player.unit().rotation() + 180f, backTrns), player.y() + Angles.trnsy(player.unit().rotation() + 180f, backTrns), + new Vec2(tile.drawx() + stackTrns.x, tile.drawy() + stackTrns.y), () -> { + if(tile.block() != block || tile.entity == null || tile.entity.items() == null) return; - tile.block().handleStack(item, removed, tile, player); - remaining[1] -= removed; - - if(end && remaining[1] > 0){ - tile.block().handleStack(item, remaining[1], tile, player); - } - }); - - remaining[0] -= removed; - - if(end){ - player.isTransferring = false; - } + tile.block().handleStack(item, accepted, tile, player.unit()); }); } } @@ -199,7 +180,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ public Eachable allRequests(){ return cons -> { - for(BuildRequest request : player.buildQueue()) cons.get(request); + for(BuildRequest request : player.builder().requests()) cons.get(request); for(BuildRequest request : selectRequests) cons.get(request); for(BuildRequest request : lineRequests) cons.get(request); }; @@ -275,7 +256,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } public void useSchematic(Schematic schem){ - selectRequests.addAll(schematics.toRequests(schem, world.toTile(player.x), world.toTile(player.y))); + selectRequests.addAll(schematics.toRequests(schem, player.tileX(), player.tileY())); } protected void showSchematicSave(){ @@ -401,7 +382,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ return r2.overlaps(r1); }; - for(BuildRequest req : player.buildQueue()){ + for(BuildRequest req : player.builder().requests()){ if(test.get(req)) return req; } @@ -430,7 +411,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ Draw.color(Pal.remove); Lines.stroke(1f); - for(BuildRequest req : player.buildQueue()){ + for(BuildRequest req : player.builder().requests()){ if(req.breaking) continue; if(req.bounds(Tmp.r2).overlaps(Tmp.r1)){ drawBreaking(req); @@ -491,7 +472,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ if(copy.hasConfig && copy.block.posConfig){ copy.config = Pos.get(Pos.x(copy.config) + copy.x - copy.originalX, Pos.y(copy.config) + copy.y - copy.originalY); } - player.addBuildRequest(copy); + player.builder().addBuild(copy); } } } @@ -535,7 +516,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ //remove build requests Tmp.r1.set(result.x * tilesize, result.y * tilesize, (result.x2 - result.x) * tilesize, (result.y2 - result.y) * tilesize); - Iterator it = player.buildQueue().iterator(); + Iterator it = player.builder().requests().iterator(); while(it.hasNext()){ BuildRequest req = it.next(); if(!req.breaking && req.bounds(Tmp.r2).overlaps(Tmp.r1)){ @@ -646,7 +627,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } boolean canTapPlayer(float x, float y){ - return Mathf.dst(x, y, player.x, player.y) <= playerSelectRange && player.item().amount > 0; + return Mathf.dst(x, y, player.x, player.y) <= playerSelectRange && player.unit().stack().amount > 0; } /** Tries to begin mining a tile, returns true if successful. */ @@ -663,7 +644,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ return !Core.scene.hasMouse() && tile.drop() != null && tile.drop().hardness <= player.mech.drillPower && !(tile.floor().playerUnmineable && tile.overlay().itemDrop == null) - && player.acceptsItem(tile.drop()) + && player.unit().acceptsItem(tile.drop()) && tile.block() == Blocks.air && player.dst(tile.worldx(), tile.worldy()) <= Playerc.mineDistance; } @@ -749,10 +730,6 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ frag.add(); } - - if(player != null){ - player.isBuilding = true; - } } public boolean canShoot(){ @@ -768,16 +745,16 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } public void tryDropItems(Tile tile, float x, float y){ - if(!droppingItem || player.item().amount <= 0 || canTapPlayer(x, y) || state.isPaused() ){ + if(!droppingItem || player.unit().stack().amount <= 0 || canTapPlayer(x, y) || state.isPaused() ){ droppingItem = false; return; } droppingItem = false; - ItemStack stack = player.item(); + ItemStack stack = player.unit().stack(); - if(tile.block().acceptStack(stack.item, stack.amount, tile, player) > 0 && tile.interactable(player.team()) && tile.block().hasItems && player.item().amount > 0 && !player.isTransferring && tile.interactable(player.team())){ + if(tile.block().acceptStack(stack.item, stack.amount, tile, player.unit()) > 0 && tile.interactable(player.team()) && tile.block().hasItems && player.unit().stack().amount > 0 && tile.interactable(player.team())){ Call.transferInventory(player, tile); }else{ Call.dropItem(player.angleTo(x, y)); @@ -801,7 +778,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } public boolean validPlace(int x, int y, Block type, int rotation, BuildRequest ignore){ - for(BuildRequest req : player.buildQueue()){ + for(BuildRequest req : player.builder().requests()){ if(req != ignore && !req.breaking && req.block.bounds(req.x, req.y, Tmp.r1).overlaps(type.bounds(x, y, Tmp.r2)) @@ -819,14 +796,14 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ public void placeBlock(int x, int y, Block block, int rotation){ BuildRequest req = getRequest(x, y); if(req != null){ - player.buildQueue().remove(req); + player.builder().requests().remove(req); } - player.addBuildRequest(new BuildRequest(x, y, rotation, block)); + player.builder().addBuild(new BuildRequest(x, y, rotation, block)); } public void breakBlock(int x, int y){ Tile tile = world.ltile(x, y); - player.addBuildRequest(new BuildRequest(tile.x, tile.y)); + player.builder().addBuild(new BuildRequest(tile.x, tile.y)); } public void drawArrow(Block block, int x, int y, int rotation){ diff --git a/core/src/mindustry/input/MobileInput.java b/core/src/mindustry/input/MobileInput.java index 02fff918a5..80000d4828 100644 --- a/core/src/mindustry/input/MobileInput.java +++ b/core/src/mindustry/input/MobileInput.java @@ -109,7 +109,7 @@ public class MobileInput extends InputHandler implements GestureListener{ } } - for(BuildRequest req : player.buildQueue()){ + for(BuildRequest req : player.builder().requests()){ Tile other = world.tile(req.x, req.y); if(other == null || req.breaking) continue; @@ -224,10 +224,10 @@ public class MobileInput extends InputHandler implements GestureListener{ } if(other == null){ - player.addBuildRequest(copy); + player.builder().addBuild(copy); }else if(!other.breaking && other.x == request.x && other.y == request.y && other.block.size == request.block.size){ - player.buildQueue().remove(other); - player.addBuildRequest(copy); + player.builder().requests().remove(other); + player.builder().addBuild(copy); } } diff --git a/core/src/mindustry/ui/fragments/PlacementFragment.java b/core/src/mindustry/ui/fragments/PlacementFragment.java index 22ba8b4517..da31fb1f5a 100644 --- a/core/src/mindustry/ui/fragments/PlacementFragment.java +++ b/core/src/mindustry/ui/fragments/PlacementFragment.java @@ -89,11 +89,11 @@ public class PlacementFragment extends Fragment{ boolean gridUpdate(InputHandler input){ scrollPositions.put(currentCategory, blockPane.getScrollY()); - if(Core.input.keyDown(Binding.pick)){ //mouse eyedropper select + if(Core.input.keyDown(Binding.pick) && player.isBuilder()){ //mouse eyedropper select Tile tile = world.ltileWorld(Core.input.mouseWorld().x, Core.input.mouseWorld().y); Block tryRecipe = tile == null ? null : tile.block(); - for(BuildRequest req : player.buildQueue()){ + for(BuildRequest req : player.builder().requests()){ if(!req.breaking && req.block.bounds(req.x, req.y, Tmp.r1).contains(Core.input.mouseWorld())){ tryRecipe = req.block; break; diff --git a/core/src/mindustry/world/blocks/BuildBlock.java b/core/src/mindustry/world/blocks/BuildBlock.java index 7680b406a3..7cb2a4917f 100644 --- a/core/src/mindustry/world/blocks/BuildBlock.java +++ b/core/src/mindustry/world/blocks/BuildBlock.java @@ -147,7 +147,7 @@ public class BuildBlock extends Block{ player.isBuilding = true; } //player.clearBuilding(); - player.addBuildRequest(new BuildRequest(tile.x, tile.y, tile.rotation(), entity.cblock), false); + player.builder().addBuild(new BuildRequest(tile.x, tile.y, tile.rotation(), entity.cblock), false); }*/ } diff --git a/gradle.properties b/gradle.properties index 30403179dc..5d8543ab5e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ org.gradle.daemon=true org.gradle.jvmargs=-Xms256m -Xmx1024m -archash=50973a6e5c025f6f9573206d5f49f03d3a4ee914 +archash=e9bd792158afc4f72017d9bed995e448934e472e