diff --git a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmBlockEntity.java index 7ea5a89d84..98b96a38a7 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmBlockEntity.java @@ -54,10 +54,16 @@ public class ArmBlockEntity extends KineticBlockEntity implements TransformableBlockEntity { + // Server Statics + private static final int SearchInputsRate = 20; // the rate at which the arm will search for targets while in SEARCH_INPUTS phase + private static int LastRandomSearchTickOffset = 0; + // Server List inputs; List outputs; ListTag interactionPointTag; + int randomSearchTickOffset; + int forceSearchInputsTicks = 1; // ticks for how long the arm will search on every tick instead of every SearchInputsRate ticks (while in SEARCH_INPUTS phase) // Both float chasedPointProgress; @@ -142,12 +148,24 @@ public void tick() { if (level.isClientSide) return; - if (phase == Phase.MOVE_TO_INPUT) - collectItem(); - else if (phase == Phase.MOVE_TO_OUTPUT) - depositItem(); - else if (phase == Phase.SEARCH_INPUTS || phase == Phase.DANCING) - searchForItem(); + switch (phase) { + case MOVE_TO_INPUT: + collectItem(); + break; + case MOVE_TO_OUTPUT: + depositItem(); + break; + case SEARCH_INPUTS: + case DANCING: + boolean forcedSearch = forceSearchInputsTicks > 0; + if (forcedSearch || (level.getGameTime() + randomSearchTickOffset) % SearchInputsRate == 0) { + if(forcedSearch) { + forceSearchInputsTicks--; + } + searchForItem(); + } + break; + } if (targetReached) lazyTick(); @@ -161,10 +179,16 @@ public void lazyTick() { return; if (chasedPointProgress < .5f) return; - if (phase == Phase.SEARCH_INPUTS || phase == Phase.DANCING) - checkForMusic(); - if (phase == Phase.SEARCH_OUTPUTS) - searchForDestination(); + + switch (phase){ + case SEARCH_INPUTS: + case DANCING: + checkForMusic(); + break; + case SEARCH_OUTPUTS: + searchForDestination(); + break; + } } private void checkForMusic() { @@ -240,10 +264,21 @@ public void destroy() { private ArmInteractionPoint getTargetedInteractionPoint() { if (chasedPointIndex == -1) return null; - if (phase == Phase.MOVE_TO_INPUT && chasedPointIndex < inputs.size()) - return inputs.get(chasedPointIndex); - if (phase == Phase.MOVE_TO_OUTPUT && chasedPointIndex < outputs.size()) - return outputs.get(chasedPointIndex); + + switch (phase){ + case MOVE_TO_INPUT: + if(chasedPointIndex < inputs.size()) + { + return inputs.get(chasedPointIndex); + } + break; + case MOVE_TO_OUTPUT: + if(chasedPointIndex < outputs.size()) + { + return outputs.get(chasedPointIndex); + } + break; + } return null; } @@ -267,7 +302,9 @@ protected void searchForItem() { ArmInteractionPoint armInteractionPoint = inputs.get(i); if (!armInteractionPoint.isValid()) continue; - for (int j = 0; j < armInteractionPoint.getSlotCount(); j++) { + + int slotCount = armInteractionPoint.getSlotCount(); + for (int j = 0; j < slotCount; j++) { if (getDistributableAmount(armInteractionPoint, j) == 0) continue; @@ -365,6 +402,7 @@ protected void depositItem() { ItemStack toInsert = heldItem.copy(); ItemStack remainder = armInteractionPoint.insert(toInsert, false); heldItem = remainder; + forceSearchInputsTicks = 5; // might need it's own static variable. this should be atleast one tick if you want the arm to jump to another action quickly (for example when refilling blaze burners) if (armInteractionPoint instanceof JukeboxPoint && remainder.isEmpty()) award(AllAdvancements.MUSICAL_ARM); @@ -382,8 +420,10 @@ protected void depositItem() { protected void collectItem() { ArmInteractionPoint armInteractionPoint = getTargetedInteractionPoint(); - if (armInteractionPoint != null && armInteractionPoint.isValid()) - for (int i = 0; i < armInteractionPoint.getSlotCount(); i++) { + if (armInteractionPoint != null && armInteractionPoint.isValid()) { + + int slotCount = armInteractionPoint.getSlotCount(); + for (int i = 0; i < slotCount; i++) { int amountExtracted = getDistributableAmount(armInteractionPoint, i); if (amountExtracted == 0) continue; @@ -401,6 +441,7 @@ protected void collectItem() { .5f + Create.RANDOM.nextFloat() * .25f); return; } + } phase = Phase.SEARCH_INPUTS; chasedPointProgress = 0; @@ -608,6 +649,12 @@ public void setLevel(Level level) { for (ArmInteractionPoint output : outputs) { output.setLevel(level); } + + // ensures that not all mechanical arms search for targets on the same tick while in SEARCH_INPUTS phase + // this only needs to be done on the server side + if (!level.isClientSide) { + randomSearchTickOffset = LastRandomSearchTickOffset++; + } } private class SelectionModeValueBox extends CenteredSideValueBoxTransform {