From 19b61b78526fdc1e325bae84296c365709c23a08 Mon Sep 17 00:00:00 2001 From: anonymous123-code <61744596+anonymous123-code@users.noreply.github.com> Date: Wed, 31 May 2023 23:28:20 +0200 Subject: [PATCH 01/11] Initial spark perf improvements --- .../botania/api/mana/spark/ManaSpark.java | 5 ++ .../common/entity/ManaSparkEntity.java | 84 ++++++++++++++----- 2 files changed, 69 insertions(+), 20 deletions(-) diff --git a/Xplat/src/main/java/vazkii/botania/api/mana/spark/ManaSpark.java b/Xplat/src/main/java/vazkii/botania/api/mana/spark/ManaSpark.java index 7f7aee2abb..906be87985 100644 --- a/Xplat/src/main/java/vazkii/botania/api/mana/spark/ManaSpark.java +++ b/Xplat/src/main/java/vazkii/botania/api/mana/spark/ManaSpark.java @@ -41,6 +41,11 @@ public interface ManaSpark extends SparkEntity { */ void registerTransfer(ManaSpark entity); + /** + * Makes that spark register transfers for all relevant sparks, decided + */ + void updateTransfers(); + SparkUpgradeType getUpgrade(); void setUpgrade(SparkUpgradeType upgrade); diff --git a/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java b/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java index 07dd830543..1ed5e8c8e7 100644 --- a/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java @@ -60,6 +60,8 @@ public class ManaSparkEntity extends SparkBaseEntity implements ManaSpark { private final Set transfers = Collections.newSetFromMap(new WeakHashMap<>()); private int removeTransferants = 2; + private boolean shouldFilterTransfers = true; + private boolean wasFull = true; public ManaSparkEntity(EntityType type, Level world) { super(type, world); @@ -163,42 +165,39 @@ public void tick() { } case DOMINANT -> { - List validSparks = SparkHelper.getSparksAround(level(), getX(), getY() + (getBbHeight() / 2), getZ(), getNetwork()); - validSparks.removeIf(s -> { - SparkUpgradeType otherUpgrade = s.getUpgrade(); - return s == this || otherUpgrade != SparkUpgradeType.NONE || !(s.getAttachedManaReceiver() instanceof ManaPool); - }); - if (!validSparks.isEmpty()) { - validSparks.get(level().random.nextInt(validSparks.size())).registerTransfer(this); + if (wasFull && !receiver.isFull()) { + updateTransfers(); } - } case RECESSIVE -> { - var otherSparks = SparkHelper.getSparksAround(level(), getX(), getY() + (getBbHeight() / 2), getZ(), getNetwork()); - for (var otherSpark : otherSparks) { - SparkUpgradeType otherUpgrade = otherSpark.getUpgrade(); - if (otherSpark != this - && otherUpgrade != SparkUpgradeType.DOMINANT - && otherUpgrade != SparkUpgradeType.RECESSIVE - && otherUpgrade != SparkUpgradeType.ISOLATED) { - transfers.add(otherSpark); - } - } + // updateTransfers(); } default -> {} } + if (receiver != null) { + wasFull = receiver.isFull(); + } else { + wasFull = true; + } + if (!transfers.isEmpty()) { int manaTotal = Math.min(TRANSFER_RATE * transfers.size(), receiver.getCurrentMana()); int count = transfers.size(); int manaSpent = 0; if (manaTotal > 0) { + if (shouldFilterTransfers) { + filterTransfers(); + shouldFilterTransfers = false; + } + for (ManaSpark spark : transfers) { count--; SparkAttachable attached = spark.getAttachedTile(); var attachedReceiver = spark.getAttachedManaReceiver(); if (attached == null || attachedReceiver == null || attachedReceiver.isFull() || spark.areIncomingTransfersDone()) { + shouldFilterTransfers = true; continue; } @@ -215,7 +214,34 @@ public void tick() { if (removeTransferants > 0) { removeTransferants--; } - filterTransfers(); + } + + @Override + public void updateTransfers() { + switch (getUpgrade()) { + case RECESSIVE -> { + var otherSparks = SparkHelper.getSparksAround(getLevel(), getX(), getY() + (getBbHeight() / 2), getZ(), getNetwork()); + for (var otherSpark : otherSparks) { + SparkUpgradeType otherUpgrade = otherSpark.getUpgrade(); + if (otherSpark != this + && otherUpgrade != SparkUpgradeType.DOMINANT + && otherUpgrade != SparkUpgradeType.RECESSIVE + && otherUpgrade != SparkUpgradeType.ISOLATED) { + transfers.add(otherSpark); + } + } + filterTransfers(); + } + case DOMINANT -> { + List validSparks = SparkHelper.getSparksAround(getLevel(), getX(), getY() + (getBbHeight() / 2), getZ(), getNetwork()); + for (var spark : validSparks) { + SparkUpgradeType otherUpgrade = spark.getUpgrade(); + if (spark != this && otherUpgrade == SparkUpgradeType.NONE && spark.getAttachedManaReceiver() instanceof ManaPool) { + spark.registerTransfer(this); + } + } + } + } } private void particlesTowards(Entity e) { @@ -244,6 +270,12 @@ private void dropAndKill() { discard(); } + @Override + public void remove(RemovalReason removalReason) { + super.remove(removalReason); + notifyOthers(); + } + @Override public InteractionResult interact(Player player, InteractionHand hand) { ItemStack stack = player.getItemInHand(hand); @@ -258,6 +290,7 @@ public InteractionResult interact(Player player, InteractionHand hand) { transfers.clear(); removeTransferants = 2; + notifyOthers(); } else { dropAndKill(); } @@ -272,6 +305,8 @@ public InteractionResult interact(Player player, InteractionHand hand) { if (!level().isClientSide) { setUpgrade(newUpgrade.type); stack.shrink(1); + updateTransfers(); + notifyOthers(); } return InteractionResult.sidedSuccess(level().isClientSide); } else if (stack.is(BotaniaItems.phantomInk)) { @@ -285,6 +320,8 @@ public InteractionResult interact(Player player, InteractionHand hand) { if (!level().isClientSide) { setNetwork(color); stack.shrink(1); + updateTransfers(); + notifyOthers(); } return InteractionResult.sidedSuccess(level().isClientSide); } @@ -341,7 +378,6 @@ private void filterTransfers() { @Override public Collection getTransfers() { - filterTransfers(); return transfers; } @@ -355,6 +391,13 @@ public void registerTransfer(ManaSpark entity) { return; } transfers.add(entity); + filterTransfers(); + } + + private void notifyOthers() { + for (var spark : SparkHelper.getSparksAround(getLevel(), getX(), getY() + (getBbHeight() / 2), getZ(), getNetwork())) { + spark.updateTransfers(); + } } @Override @@ -365,6 +408,7 @@ public SparkUpgradeType getUpgrade() { @Override public void setUpgrade(SparkUpgradeType upgrade) { entityData.set(UPGRADE, upgrade.ordinal()); + notifyOthers(); } @Override From c0478d9bbb6affea9163214bb85794a2ff1e88b1 Mon Sep 17 00:00:00 2001 From: anonymous123-code <61744596+anonymous123-code@users.noreply.github.com> Date: Thu, 1 Jun 2023 13:12:26 +0200 Subject: [PATCH 02/11] Cache getManaReceiver --- .../botania/fabric/xplat/FabricXplatImpl.java | 24 +++++++++++++++++++ .../mana/ManaSpreaderBlockEntity.java | 7 ++---- .../common/item/FloralObedienceStickItem.java | 4 +--- .../common/item/lens/MagnetizingLens.java | 4 +--- .../common/item/lens/RedirectiveLens.java | 3 +-- 5 files changed, 29 insertions(+), 13 deletions(-) diff --git a/Fabric/src/main/java/vazkii/botania/fabric/xplat/FabricXplatImpl.java b/Fabric/src/main/java/vazkii/botania/fabric/xplat/FabricXplatImpl.java index 3b27bb6946..e107a20f07 100644 --- a/Fabric/src/main/java/vazkii/botania/fabric/xplat/FabricXplatImpl.java +++ b/Fabric/src/main/java/vazkii/botania/fabric/xplat/FabricXplatImpl.java @@ -6,6 +6,7 @@ import net.fabricmc.api.EnvType; import net.fabricmc.fabric.api.item.v1.FabricItemSettings; +import net.fabricmc.fabric.api.lookup.v1.block.BlockApiCache; import net.fabricmc.fabric.api.networking.v1.PlayerLookup; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder; @@ -110,6 +111,8 @@ import vazkii.botania.network.BotaniaPacket; import vazkii.botania.xplat.XplatAbstractions; +import java.nio.file.Path; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -122,6 +125,8 @@ import static vazkii.botania.common.lib.ResourceLocationHelper.prefix; public class FabricXplatImpl implements XplatAbstractions { + private final HashMap, BlockApiCache> lookupCache = new HashMap<>(); + @Override public boolean isFabric() { return true; @@ -208,6 +213,25 @@ public ManaReceiver findManaReceiver(Level level, BlockPos pos, BlockState state return BotaniaFabricCapabilities.MANA_RECEIVER.find(level, pos, state, be, direction); } + @Override + public @Nullable ManaReceiver findManaReceiver(Level level, BlockPos pos, @Nullable Direction direction) { + if (level instanceof ServerLevel) { + return findCachedManaReceiver((ServerLevel) level, pos, direction); + } else { + return findManaReceiver(level, pos, level.getBlockState(pos), level.getBlockEntity(pos), direction); + } + } + + private @Nullable ManaReceiver findCachedManaReceiver(ServerLevel level, BlockPos pos, @Nullable Direction direction) { + var pair = Pair.of(level, pos); + var cache = lookupCache.get(pair); + if (cache == null) { + cache = BlockApiCache.create(BotaniaFabricCapabilities.MANA_RECEIVER, level, pos); + lookupCache.put(pair, cache); + } + return cache.find(direction); + } + @Nullable @Override public SparkAttachable findSparkAttachable(Level level, BlockPos pos, BlockState blockState, @Nullable BlockEntity be, Direction direction) { diff --git a/Xplat/src/main/java/vazkii/botania/common/block/block_entity/mana/ManaSpreaderBlockEntity.java b/Xplat/src/main/java/vazkii/botania/common/block/block_entity/mana/ManaSpreaderBlockEntity.java index d817ccea29..c3134a298e 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/block_entity/mana/ManaSpreaderBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/block_entity/mana/ManaSpreaderBlockEntity.java @@ -167,8 +167,7 @@ public static void commonTick(Level level, BlockPos worldPosition, BlockState st for (Direction dir : Direction.values()) { var relPos = worldPosition.relative(dir); if (level.hasChunkAt(relPos)) { - var receiverAt = XplatAbstractions.INSTANCE.findManaReceiver(level, relPos, - level.getBlockState(relPos), level.getBlockEntity(relPos), dir.getOpposite()); + var receiverAt = XplatAbstractions.INSTANCE.findManaReceiver(level, relPos, dir.getOpposite()); if (receiverAt instanceof ManaPool pool) { if (wasInNetwork && (pool != self.receiver || self.getVariant() == ManaSpreaderBlock.Variant.REDSTONE)) { if (pool instanceof KeyLocked locked && !locked.getOutputKey().equals(self.getInputKey())) { @@ -348,9 +347,7 @@ public void readPacketNBT(CompoundTag cmp) { int z = cmp.getInt(TAG_FORCE_CLIENT_BINDING_Z); if (y != Integer.MIN_VALUE) { var pos = new BlockPos(x, y, z); - var state = level.getBlockState(pos); - var be = level.getBlockEntity(pos); - receiver = XplatAbstractions.INSTANCE.findManaReceiver(level, pos, state, be, null); + receiver = XplatAbstractions.INSTANCE.findManaReceiver(level, pos, null); } else { receiver = null; } diff --git a/Xplat/src/main/java/vazkii/botania/common/item/FloralObedienceStickItem.java b/Xplat/src/main/java/vazkii/botania/common/item/FloralObedienceStickItem.java index 2cf2e33b4e..21b7fc34aa 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/FloralObedienceStickItem.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/FloralObedienceStickItem.java @@ -42,9 +42,7 @@ public InteractionResult useOn(UseOnContext ctx) { } public static boolean applyStick(Level world, BlockPos pos) { - var state = world.getBlockState(pos); - var be = world.getBlockEntity(pos); - var receiver = XplatAbstractions.INSTANCE.findManaReceiver(world, pos, state, be, null); + var receiver = XplatAbstractions.INSTANCE.findManaReceiver(world, pos, null); if (receiver instanceof ManaPool || receiver instanceof ManaCollector) { int range = receiver instanceof ManaPool ? FunctionalFlowerBlockEntity.LINK_RANGE : GeneratingFlowerBlockEntity.LINK_RANGE; diff --git a/Xplat/src/main/java/vazkii/botania/common/item/lens/MagnetizingLens.java b/Xplat/src/main/java/vazkii/botania/common/item/lens/MagnetizingLens.java index dbaf3c802a..311e3c031d 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/lens/MagnetizingLens.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/lens/MagnetizingLens.java @@ -31,9 +31,7 @@ public void updateBurst(ManaBurst burst, ItemStack stack) { final boolean sourceless = source.equals(ManaBurst.NO_SOURCE); Predicate predicate = pos -> { - var state = entity.level().getBlockState(pos); - var be = entity.level().getBlockEntity(pos); - var receiver = XplatAbstractions.INSTANCE.findManaReceiver(entity.level(), pos, state, be, null); + var receiver = XplatAbstractions.INSTANCE.findManaReceiver(entity.level(), pos, null); return receiver != null && (sourceless || pos.distSqr(source) > 9) && receiver.canReceiveManaFromBursts() diff --git a/Xplat/src/main/java/vazkii/botania/common/item/lens/RedirectiveLens.java b/Xplat/src/main/java/vazkii/botania/common/item/lens/RedirectiveLens.java index a5f4dedbeb..057ebfa44a 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/lens/RedirectiveLens.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/lens/RedirectiveLens.java @@ -84,8 +84,7 @@ private void handleHitBlock(ManaBurst burst, BlockHitResult result) { var entity = burst.entity(); var hitPos = result.getBlockPos(); - var receiver = XplatAbstractions.INSTANCE.findManaReceiver(entity.level(), hitPos, - entity.level().getBlockState(hitPos), entity.level().getBlockEntity(hitPos), result.getDirection()); + var receiver = XplatAbstractions.INSTANCE.findManaReceiver(entity.level(), hitPos, result.getDirection()); if (receiver instanceof ManaSpreader spreader) { Vec3 tileVec = Vec3.atCenterOf(hitPos); Vec3 diffVec = sourceVec.subtract(tileVec); From 8cceb0ecc7e9789c8af3f20a6611cefec1b668a2 Mon Sep 17 00:00:00 2001 From: anonymous123-code <61744596+anonymous123-code@users.noreply.github.com> Date: Fri, 2 Jun 2023 00:45:49 +0200 Subject: [PATCH 03/11] Fix some transfer update bugs --- .../common/entity/ManaSparkEntity.java | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java b/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java index 1ed5e8c8e7..54f4d3a6c3 100644 --- a/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java @@ -62,6 +62,7 @@ public class ManaSparkEntity extends SparkBaseEntity implements ManaSpark { private int removeTransferants = 2; private boolean shouldFilterTransfers = true; private boolean wasFull = true; + private boolean firstTick = true; public ManaSparkEntity(EntityType type, Level world) { super(type, world); @@ -91,6 +92,10 @@ public void tick() { return; } + if (firstTick) { + updateTransfers(); + } + SparkAttachable tile = getAttachedTile(); if (tile == null) { dropAndKill(); @@ -172,7 +177,11 @@ public void tick() { case RECESSIVE -> { // updateTransfers(); } - default -> {} + default -> { + if (wasFull && !receiver.isFull()) { + notifyOthers(getNetwork()); + } + } } if (receiver != null) { @@ -214,6 +223,7 @@ public void tick() { if (removeTransferants > 0) { removeTransferants--; } + firstTick = false; } @Override @@ -230,7 +240,6 @@ public void updateTransfers() { transfers.add(otherSpark); } } - filterTransfers(); } case DOMINANT -> { List validSparks = SparkHelper.getSparksAround(getLevel(), getX(), getY() + (getBbHeight() / 2), getZ(), getNetwork()); @@ -242,6 +251,7 @@ public void updateTransfers() { } } } + filterTransfers(); } private void particlesTowards(Entity e) { @@ -273,7 +283,7 @@ private void dropAndKill() { @Override public void remove(RemovalReason removalReason) { super.remove(removalReason); - notifyOthers(); + notifyOthers(getNetwork()); } @Override @@ -289,8 +299,7 @@ public InteractionResult interact(Player player, InteractionHand hand) { setUpgrade(SparkUpgradeType.NONE); transfers.clear(); - removeTransferants = 2; - notifyOthers(); + notifyOthers(getNetwork()); } else { dropAndKill(); } @@ -306,7 +315,7 @@ public InteractionResult interact(Player player, InteractionHand hand) { setUpgrade(newUpgrade.type); stack.shrink(1); updateTransfers(); - notifyOthers(); + notifyOthers(getNetwork()); } return InteractionResult.sidedSuccess(level().isClientSide); } else if (stack.is(BotaniaItems.phantomInk)) { @@ -318,10 +327,12 @@ public InteractionResult interact(Player player, InteractionHand hand) { DyeColor color = dye.getDyeColor(); if (color != getNetwork()) { if (!level().isClientSide) { + var previousNetwork = getNetwork(); setNetwork(color); stack.shrink(1); updateTransfers(); - notifyOthers(); + notifyOthers(getNetwork()); + notifyOthers(previousNetwork); } return InteractionResult.sidedSuccess(level().isClientSide); } @@ -394,8 +405,8 @@ public void registerTransfer(ManaSpark entity) { filterTransfers(); } - private void notifyOthers() { - for (var spark : SparkHelper.getSparksAround(getLevel(), getX(), getY() + (getBbHeight() / 2), getZ(), getNetwork())) { + private void notifyOthers(DyeColor network) { + for (var spark : SparkHelper.getSparksAround(getLevel(), getX(), getY() + (getBbHeight() / 2), getZ(), network)) { spark.updateTransfers(); } } @@ -408,13 +419,13 @@ public SparkUpgradeType getUpgrade() { @Override public void setUpgrade(SparkUpgradeType upgrade) { entityData.set(UPGRADE, upgrade.ordinal()); - notifyOthers(); + notifyOthers(getNetwork()); } @Override public boolean areIncomingTransfersDone() { if (getAttachedManaReceiver() instanceof ManaPool) { - return removeTransferants > 0; + return false; } SparkAttachable attachable = getAttachedTile(); From d3c0aa107547bdccf8a1623f6b3f8d705849b29d Mon Sep 17 00:00:00 2001 From: anonymous123-code <61744596+anonymous123-code@users.noreply.github.com> Date: Fri, 2 Jun 2023 19:44:25 +0200 Subject: [PATCH 04/11] Integration with other blocks fixes (everything should work now) --- .../block_entity/SparkTinkererBlockEntity.java | 4 ---- .../botania/common/entity/ManaSparkEntity.java | 16 ++++++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Xplat/src/main/java/vazkii/botania/common/block/block_entity/SparkTinkererBlockEntity.java b/Xplat/src/main/java/vazkii/botania/common/block/block_entity/SparkTinkererBlockEntity.java index 7c8eb45ea0..00dcf61c89 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/block_entity/SparkTinkererBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/block_entity/SparkTinkererBlockEntity.java @@ -59,10 +59,6 @@ public void doSwap() { ItemStack sparkStack = SparkAugmentItem.getByType(upg); SparkUpgradeType newUpg = changeStack.isEmpty() ? SparkUpgradeType.NONE : ((SparkAugmentItem) changeStack.getItem()).type; spark.setUpgrade(newUpg); - Collection transfers = spark.getTransfers(); - if (transfers != null) { - transfers.clear(); - } getItemHandler().setItem(0, sparkStack); } } diff --git a/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java b/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java index 54f4d3a6c3..eec2306a90 100644 --- a/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java @@ -314,8 +314,6 @@ public InteractionResult interact(Player player, InteractionHand hand) { if (!level().isClientSide) { setUpgrade(newUpgrade.type); stack.shrink(1); - updateTransfers(); - notifyOthers(getNetwork()); } return InteractionResult.sidedSuccess(level().isClientSide); } else if (stack.is(BotaniaItems.phantomInk)) { @@ -327,12 +325,8 @@ public InteractionResult interact(Player player, InteractionHand hand) { DyeColor color = dye.getDyeColor(); if (color != getNetwork()) { if (!level().isClientSide) { - var previousNetwork = getNetwork(); setNetwork(color); stack.shrink(1); - updateTransfers(); - notifyOthers(getNetwork()); - notifyOthers(previousNetwork); } return InteractionResult.sidedSuccess(level().isClientSide); } @@ -419,9 +413,19 @@ public SparkUpgradeType getUpgrade() { @Override public void setUpgrade(SparkUpgradeType upgrade) { entityData.set(UPGRADE, upgrade.ordinal()); + updateTransfers(); notifyOthers(getNetwork()); } + @Override + public void setNetwork(DyeColor color) { + var previousNetwork = getNetwork(); + super.setNetwork(color); + updateTransfers(); + notifyOthers(color); + notifyOthers(previousNetwork); + } + @Override public boolean areIncomingTransfersDone() { if (getAttachedManaReceiver() instanceof ManaPool) { From 1920c22f40b47113d76eb41b31cc4f546358d3ad Mon Sep 17 00:00:00 2001 From: anonymous123-code <61744596+anonymous123-code@users.noreply.github.com> Date: Fri, 2 Jun 2023 20:23:07 +0200 Subject: [PATCH 05/11] Final changes: Remove unnecessary removeTransfers --- .../java/vazkii/botania/common/entity/ManaSparkEntity.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java b/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java index eec2306a90..8afff3a5e1 100644 --- a/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java @@ -59,7 +59,6 @@ public class ManaSparkEntity extends SparkBaseEntity implements ManaSpark { private final Set transfers = Collections.newSetFromMap(new WeakHashMap<>()); - private int removeTransferants = 2; private boolean shouldFilterTransfers = true; private boolean wasFull = true; private boolean firstTick = true; @@ -220,9 +219,6 @@ public void tick() { } } - if (removeTransferants > 0) { - removeTransferants--; - } firstTick = false; } From a81f652deda64fde6242fd50a21cf4c05b17c31f Mon Sep 17 00:00:00 2001 From: anonymous123-code <61744596+anonymous123-code@users.noreply.github.com> Date: Sat, 3 Jun 2023 11:47:28 +0200 Subject: [PATCH 06/11] Fix weird behavior when transferring low mana amounts --- .../block/block_entity/SparkTinkererBlockEntity.java | 1 - .../vazkii/botania/common/entity/ManaSparkEntity.java | 9 ++++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Xplat/src/main/java/vazkii/botania/common/block/block_entity/SparkTinkererBlockEntity.java b/Xplat/src/main/java/vazkii/botania/common/block/block_entity/SparkTinkererBlockEntity.java index 00dcf61c89..272b3722e2 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/block_entity/SparkTinkererBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/block_entity/SparkTinkererBlockEntity.java @@ -22,7 +22,6 @@ import vazkii.botania.xplat.XplatAbstractions; import java.util.ArrayList; -import java.util.Collection; import java.util.List; public class SparkTinkererBlockEntity extends ExposedSimpleInventoryBlockEntity { diff --git a/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java b/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java index 8afff3a5e1..273d988c29 100644 --- a/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java @@ -59,6 +59,8 @@ public class ManaSparkEntity extends SparkBaseEntity implements ManaSpark { private final Set transfers = Collections.newSetFromMap(new WeakHashMap<>()); + private final ArrayList transfersTowardsSelfToRegister = new ArrayList<>(); + private boolean shouldFilterTransfers = true; private boolean wasFull = true; private boolean firstTick = true; @@ -172,6 +174,9 @@ public void tick() { if (wasFull && !receiver.isFull()) { updateTransfers(); } + if (transfersTowardsSelfToRegister.size() > 0) { + transfersTowardsSelfToRegister.remove(0).registerTransfer(this); + } } case RECESSIVE -> { // updateTransfers(); @@ -227,6 +232,7 @@ public void updateTransfers() { switch (getUpgrade()) { case RECESSIVE -> { var otherSparks = SparkHelper.getSparksAround(getLevel(), getX(), getY() + (getBbHeight() / 2), getZ(), getNetwork()); + Collections.shuffle(otherSparks); for (var otherSpark : otherSparks) { SparkUpgradeType otherUpgrade = otherSpark.getUpgrade(); if (otherSpark != this @@ -242,9 +248,10 @@ public void updateTransfers() { for (var spark : validSparks) { SparkUpgradeType otherUpgrade = spark.getUpgrade(); if (spark != this && otherUpgrade == SparkUpgradeType.NONE && spark.getAttachedManaReceiver() instanceof ManaPool) { - spark.registerTransfer(this); + transfersTowardsSelfToRegister.add(spark); } } + Collections.shuffle(transfersTowardsSelfToRegister); } } filterTransfers(); From 443e2223eaa288d11b9c99bb7841cf6d39d63e5b Mon Sep 17 00:00:00 2001 From: anonymous123-code <61744596+anonymous123-code@users.noreply.github.com> Date: Sat, 3 Jun 2023 14:30:54 +0200 Subject: [PATCH 07/11] Better Caching impl --- .../botania/fabric/xplat/FabricXplatImpl.java | 20 ++++++++++++++++++ .../common/entity/SparkBaseEntity.java | 10 +++++++++ .../botania/xplat/XplatAbstractions.java | 21 +++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/Fabric/src/main/java/vazkii/botania/fabric/xplat/FabricXplatImpl.java b/Fabric/src/main/java/vazkii/botania/fabric/xplat/FabricXplatImpl.java index e107a20f07..3c971c6d2c 100644 --- a/Fabric/src/main/java/vazkii/botania/fabric/xplat/FabricXplatImpl.java +++ b/Fabric/src/main/java/vazkii/botania/fabric/xplat/FabricXplatImpl.java @@ -222,6 +222,26 @@ public ManaReceiver findManaReceiver(Level level, BlockPos pos, BlockState state } } + @Override + public CapabilityFindCache getFindManaReceiverCache(Level level, BlockPos pos) { + if (level instanceof ServerLevel) { + return new CapabilityFindCache<>() { + private final BlockApiCache cache = BlockApiCache.create(BotaniaFabricCapabilities.MANA_RECEIVER, (ServerLevel) level, pos); + + @Override + public @Nullable ManaReceiver find(Direction context) { + return cache.find(context); + } + + @Override + public @Nullable ManaReceiver find(@Nullable BlockState state, Direction context) { + return cache.find(state, context); + } + }; + } + return XplatAbstractions.super.getFindManaReceiverCache(level, pos); + } + private @Nullable ManaReceiver findCachedManaReceiver(ServerLevel level, BlockPos pos, @Nullable Direction direction) { var pair = Pair.of(level, pos); var cache = lookupCache.get(pair); diff --git a/Xplat/src/main/java/vazkii/botania/common/entity/SparkBaseEntity.java b/Xplat/src/main/java/vazkii/botania/common/entity/SparkBaseEntity.java index c4e8aa0976..df4f98e234 100644 --- a/Xplat/src/main/java/vazkii/botania/common/entity/SparkBaseEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/entity/SparkBaseEntity.java @@ -28,6 +28,7 @@ public abstract class SparkBaseEntity extends Entity implements SparkEntity { private static final String TAG_INVIS = "invis"; private static final String TAG_NETWORK = "network"; private static final EntityDataAccessor NETWORK = SynchedEntityData.defineId(SparkBaseEntity.class, EntityDataSerializers.INT); + private XplatAbstractions.CapabilityFindCache attachedManaReceiverCache; public SparkBaseEntity(EntityType type, Level world) { super(type, world); @@ -46,6 +47,15 @@ public BlockPos getAttachPos() { return new BlockPos(x, y, z); } + @Nullable + @Override + public ManaReceiver getAttachedManaReceiver() { + if (attachedManaReceiverCache == null) { + attachedManaReceiverCache = XplatAbstractions.INSTANCE.getFindManaReceiverCache(getLevel(), getAttachPos()); + } + return attachedManaReceiverCache.find(Direction.UP); + } + @Override public DyeColor getNetwork() { return DyeColor.byId(entityData.get(NETWORK)); diff --git a/Xplat/src/main/java/vazkii/botania/xplat/XplatAbstractions.java b/Xplat/src/main/java/vazkii/botania/xplat/XplatAbstractions.java index f6c2e3c4a8..17de8873da 100644 --- a/Xplat/src/main/java/vazkii/botania/xplat/XplatAbstractions.java +++ b/Xplat/src/main/java/vazkii/botania/xplat/XplatAbstractions.java @@ -119,6 +119,20 @@ default ManaReceiver findManaReceiver(Level level, BlockPos pos, @Nullable Direc return findManaReceiver(level, pos, level.getBlockState(pos), level.getBlockEntity(pos), direction); } + default CapabilityFindCache getFindManaReceiverCache(Level level, BlockPos pos) { + return new CapabilityFindCache<>() { + @Override + public @Nullable ManaReceiver find(Direction context) { + return findManaReceiver(level, pos, context); + } + + @Override + public @Nullable ManaReceiver find(@Nullable BlockState state, Direction context) { + return findManaReceiver(level, pos, state, level.getBlockEntity(pos), context); + } + }; + } + @Nullable ManaReceiver findManaReceiver(Level level, BlockPos pos, BlockState state, @Nullable BlockEntity be, @Nullable Direction direction); @@ -218,4 +232,11 @@ default WoodType registerWoodType(String name, BlockSetType blockSetType) { WoodType registerWoodType(String name, BlockSetType setType, SoundType soundType, SoundType hangingSignSoundType, SoundEvent fenceGateClose, SoundEvent fenceGateOpen); XplatAbstractions INSTANCE = ServiceUtil.findService(XplatAbstractions.class, null); + + interface CapabilityFindCache { + @Nullable + A find(C context); + @Nullable + A find(@Nullable BlockState state, C context); + } } From 0c1fe1e8b3e6b998eb95b1b4dfce632027b8f6ce Mon Sep 17 00:00:00 2001 From: anonymous123-code <61744596+anonymous123-code@users.noreply.github.com> Date: Sat, 7 Oct 2023 18:21:03 +0200 Subject: [PATCH 08/11] Rebase fixes and remove caching Having done some profiling, caching doesn't seem to be worth the effort, with some of my tests without caching performing better than with --- .../botania/fabric/xplat/FabricXplatImpl.java | 44 ------------------- .../common/entity/ManaSparkEntity.java | 6 +-- .../common/entity/SparkBaseEntity.java | 10 ----- .../botania/xplat/XplatAbstractions.java | 21 --------- 4 files changed, 3 insertions(+), 78 deletions(-) diff --git a/Fabric/src/main/java/vazkii/botania/fabric/xplat/FabricXplatImpl.java b/Fabric/src/main/java/vazkii/botania/fabric/xplat/FabricXplatImpl.java index 3c971c6d2c..3b27bb6946 100644 --- a/Fabric/src/main/java/vazkii/botania/fabric/xplat/FabricXplatImpl.java +++ b/Fabric/src/main/java/vazkii/botania/fabric/xplat/FabricXplatImpl.java @@ -6,7 +6,6 @@ import net.fabricmc.api.EnvType; import net.fabricmc.fabric.api.item.v1.FabricItemSettings; -import net.fabricmc.fabric.api.lookup.v1.block.BlockApiCache; import net.fabricmc.fabric.api.networking.v1.PlayerLookup; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder; @@ -111,8 +110,6 @@ import vazkii.botania.network.BotaniaPacket; import vazkii.botania.xplat.XplatAbstractions; -import java.nio.file.Path; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -125,8 +122,6 @@ import static vazkii.botania.common.lib.ResourceLocationHelper.prefix; public class FabricXplatImpl implements XplatAbstractions { - private final HashMap, BlockApiCache> lookupCache = new HashMap<>(); - @Override public boolean isFabric() { return true; @@ -213,45 +208,6 @@ public ManaReceiver findManaReceiver(Level level, BlockPos pos, BlockState state return BotaniaFabricCapabilities.MANA_RECEIVER.find(level, pos, state, be, direction); } - @Override - public @Nullable ManaReceiver findManaReceiver(Level level, BlockPos pos, @Nullable Direction direction) { - if (level instanceof ServerLevel) { - return findCachedManaReceiver((ServerLevel) level, pos, direction); - } else { - return findManaReceiver(level, pos, level.getBlockState(pos), level.getBlockEntity(pos), direction); - } - } - - @Override - public CapabilityFindCache getFindManaReceiverCache(Level level, BlockPos pos) { - if (level instanceof ServerLevel) { - return new CapabilityFindCache<>() { - private final BlockApiCache cache = BlockApiCache.create(BotaniaFabricCapabilities.MANA_RECEIVER, (ServerLevel) level, pos); - - @Override - public @Nullable ManaReceiver find(Direction context) { - return cache.find(context); - } - - @Override - public @Nullable ManaReceiver find(@Nullable BlockState state, Direction context) { - return cache.find(state, context); - } - }; - } - return XplatAbstractions.super.getFindManaReceiverCache(level, pos); - } - - private @Nullable ManaReceiver findCachedManaReceiver(ServerLevel level, BlockPos pos, @Nullable Direction direction) { - var pair = Pair.of(level, pos); - var cache = lookupCache.get(pair); - if (cache == null) { - cache = BlockApiCache.create(BotaniaFabricCapabilities.MANA_RECEIVER, level, pos); - lookupCache.put(pair, cache); - } - return cache.find(direction); - } - @Nullable @Override public SparkAttachable findSparkAttachable(Level level, BlockPos pos, BlockState blockState, @Nullable BlockEntity be, Direction direction) { diff --git a/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java b/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java index 273d988c29..58c218160b 100644 --- a/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java @@ -231,7 +231,7 @@ public void tick() { public void updateTransfers() { switch (getUpgrade()) { case RECESSIVE -> { - var otherSparks = SparkHelper.getSparksAround(getLevel(), getX(), getY() + (getBbHeight() / 2), getZ(), getNetwork()); + var otherSparks = SparkHelper.getSparksAround(level(), getX(), getY() + (getBbHeight() / 2), getZ(), getNetwork()); Collections.shuffle(otherSparks); for (var otherSpark : otherSparks) { SparkUpgradeType otherUpgrade = otherSpark.getUpgrade(); @@ -244,7 +244,7 @@ public void updateTransfers() { } } case DOMINANT -> { - List validSparks = SparkHelper.getSparksAround(getLevel(), getX(), getY() + (getBbHeight() / 2), getZ(), getNetwork()); + List validSparks = SparkHelper.getSparksAround(level(), getX(), getY() + (getBbHeight() / 2), getZ(), getNetwork()); for (var spark : validSparks) { SparkUpgradeType otherUpgrade = spark.getUpgrade(); if (spark != this && otherUpgrade == SparkUpgradeType.NONE && spark.getAttachedManaReceiver() instanceof ManaPool) { @@ -403,7 +403,7 @@ public void registerTransfer(ManaSpark entity) { } private void notifyOthers(DyeColor network) { - for (var spark : SparkHelper.getSparksAround(getLevel(), getX(), getY() + (getBbHeight() / 2), getZ(), network)) { + for (var spark : SparkHelper.getSparksAround(level(), getX(), getY() + (getBbHeight() / 2), getZ(), network)) { spark.updateTransfers(); } } diff --git a/Xplat/src/main/java/vazkii/botania/common/entity/SparkBaseEntity.java b/Xplat/src/main/java/vazkii/botania/common/entity/SparkBaseEntity.java index df4f98e234..c4e8aa0976 100644 --- a/Xplat/src/main/java/vazkii/botania/common/entity/SparkBaseEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/entity/SparkBaseEntity.java @@ -28,7 +28,6 @@ public abstract class SparkBaseEntity extends Entity implements SparkEntity { private static final String TAG_INVIS = "invis"; private static final String TAG_NETWORK = "network"; private static final EntityDataAccessor NETWORK = SynchedEntityData.defineId(SparkBaseEntity.class, EntityDataSerializers.INT); - private XplatAbstractions.CapabilityFindCache attachedManaReceiverCache; public SparkBaseEntity(EntityType type, Level world) { super(type, world); @@ -47,15 +46,6 @@ public BlockPos getAttachPos() { return new BlockPos(x, y, z); } - @Nullable - @Override - public ManaReceiver getAttachedManaReceiver() { - if (attachedManaReceiverCache == null) { - attachedManaReceiverCache = XplatAbstractions.INSTANCE.getFindManaReceiverCache(getLevel(), getAttachPos()); - } - return attachedManaReceiverCache.find(Direction.UP); - } - @Override public DyeColor getNetwork() { return DyeColor.byId(entityData.get(NETWORK)); diff --git a/Xplat/src/main/java/vazkii/botania/xplat/XplatAbstractions.java b/Xplat/src/main/java/vazkii/botania/xplat/XplatAbstractions.java index 17de8873da..f6c2e3c4a8 100644 --- a/Xplat/src/main/java/vazkii/botania/xplat/XplatAbstractions.java +++ b/Xplat/src/main/java/vazkii/botania/xplat/XplatAbstractions.java @@ -119,20 +119,6 @@ default ManaReceiver findManaReceiver(Level level, BlockPos pos, @Nullable Direc return findManaReceiver(level, pos, level.getBlockState(pos), level.getBlockEntity(pos), direction); } - default CapabilityFindCache getFindManaReceiverCache(Level level, BlockPos pos) { - return new CapabilityFindCache<>() { - @Override - public @Nullable ManaReceiver find(Direction context) { - return findManaReceiver(level, pos, context); - } - - @Override - public @Nullable ManaReceiver find(@Nullable BlockState state, Direction context) { - return findManaReceiver(level, pos, state, level.getBlockEntity(pos), context); - } - }; - } - @Nullable ManaReceiver findManaReceiver(Level level, BlockPos pos, BlockState state, @Nullable BlockEntity be, @Nullable Direction direction); @@ -232,11 +218,4 @@ default WoodType registerWoodType(String name, BlockSetType blockSetType) { WoodType registerWoodType(String name, BlockSetType setType, SoundType soundType, SoundType hangingSignSoundType, SoundEvent fenceGateClose, SoundEvent fenceGateOpen); XplatAbstractions INSTANCE = ServiceUtil.findService(XplatAbstractions.class, null); - - interface CapabilityFindCache { - @Nullable - A find(C context); - @Nullable - A find(@Nullable BlockState state, C context); - } } From a6a21fdc25b1f169a8e81d5bf03494fd66c80e32 Mon Sep 17 00:00:00 2001 From: anonymous123-code <61744596+anonymous123-code@users.noreply.github.com> Date: Sun, 8 Oct 2023 12:23:26 +0200 Subject: [PATCH 09/11] Comment, rename wasFull for better readability --- .../botania/api/mana/spark/ManaSpark.java | 2 +- .../common/entity/ManaSparkEntity.java | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Xplat/src/main/java/vazkii/botania/api/mana/spark/ManaSpark.java b/Xplat/src/main/java/vazkii/botania/api/mana/spark/ManaSpark.java index 906be87985..530ca3969a 100644 --- a/Xplat/src/main/java/vazkii/botania/api/mana/spark/ManaSpark.java +++ b/Xplat/src/main/java/vazkii/botania/api/mana/spark/ManaSpark.java @@ -42,7 +42,7 @@ public interface ManaSpark extends SparkEntity { void registerTransfer(ManaSpark entity); /** - * Makes that spark register transfers for all relevant sparks, decided + * Makes that spark register transfers for all relevant sparks, needs to be called whenever the connected sparks may change (setNetwork, remove and setUpgrade should already do this) */ void updateTransfers(); diff --git a/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java b/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java index 58c218160b..933c93288b 100644 --- a/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java @@ -62,7 +62,7 @@ public class ManaSparkEntity extends SparkBaseEntity implements ManaSpark { private final ArrayList transfersTowardsSelfToRegister = new ArrayList<>(); private boolean shouldFilterTransfers = true; - private boolean wasFull = true; + private boolean receiverWasFull = true; private boolean firstTick = true; public ManaSparkEntity(EntityType type, Level world) { @@ -93,6 +93,7 @@ public void tick() { return; } + // When loaded, initialize transfers if (firstTick) { updateTransfers(); } @@ -171,27 +172,25 @@ public void tick() { } case DOMINANT -> { - if (wasFull && !receiver.isFull()) { + if (receiverWasFull && !receiver.isFull()) { updateTransfers(); } - if (transfersTowardsSelfToRegister.size() > 0) { + if (!transfersTowardsSelfToRegister.isEmpty()) { transfersTowardsSelfToRegister.remove(0).registerTransfer(this); } } - case RECESSIVE -> { - // updateTransfers(); - } + // Recessive does not need to be handled because recessive sparks get notified in all relevant cases default -> { - if (wasFull && !receiver.isFull()) { + if (receiverWasFull && !receiver.isFull()) { notifyOthers(getNetwork()); } } } if (receiver != null) { - wasFull = receiver.isFull(); + receiverWasFull = receiver.isFull(); } else { - wasFull = true; + receiverWasFull = true; } if (!transfers.isEmpty()) { @@ -301,6 +300,7 @@ public InteractionResult interact(Player player, InteractionHand hand) { spawnAtLocation(SparkAugmentItem.getByType(upgrade), 0F); setUpgrade(SparkUpgradeType.NONE); + // Recalculate transfers, recessive and dominant will register the proper transfers transfers.clear(); notifyOthers(getNetwork()); } else { @@ -422,6 +422,7 @@ public void setUpgrade(SparkUpgradeType upgrade) { @Override public void setNetwork(DyeColor color) { + // The previous network needs to filter this spark out var previousNetwork = getNetwork(); super.setNetwork(color); updateTransfers(); From 5eb322aa0ad0af4cf205c63d2aeea1e40234d49d Mon Sep 17 00:00:00 2001 From: anonymous123-code <61744596+anonymous123-code@users.noreply.github.com> Date: Sun, 8 Oct 2023 12:31:00 +0200 Subject: [PATCH 10/11] Format --- .../src/main/java/vazkii/botania/api/mana/spark/ManaSpark.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Xplat/src/main/java/vazkii/botania/api/mana/spark/ManaSpark.java b/Xplat/src/main/java/vazkii/botania/api/mana/spark/ManaSpark.java index 530ca3969a..29a42dc7f4 100644 --- a/Xplat/src/main/java/vazkii/botania/api/mana/spark/ManaSpark.java +++ b/Xplat/src/main/java/vazkii/botania/api/mana/spark/ManaSpark.java @@ -42,7 +42,8 @@ public interface ManaSpark extends SparkEntity { void registerTransfer(ManaSpark entity); /** - * Makes that spark register transfers for all relevant sparks, needs to be called whenever the connected sparks may change (setNetwork, remove and setUpgrade should already do this) + * Makes that spark register transfers for all relevant sparks, needs to be called whenever the connected sparks may + * change (setNetwork, remove and setUpgrade should already do this) */ void updateTransfers(); From d33ba5dfdce0cc7f88e46c11adcebbd4481f03e9 Mon Sep 17 00:00:00 2001 From: anonymous123-code <61744596+anonymous123-code@users.noreply.github.com> Date: Sat, 14 Oct 2023 22:46:28 +0200 Subject: [PATCH 11/11] Address review: Better names Remove at end, to save copying performance Avoid potential memory leak when dominant is switched in and out quickly --- .../botania/api/mana/spark/ManaSpark.java | 2 +- .../common/entity/ManaSparkEntity.java | 21 ++++++++++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Xplat/src/main/java/vazkii/botania/api/mana/spark/ManaSpark.java b/Xplat/src/main/java/vazkii/botania/api/mana/spark/ManaSpark.java index 29a42dc7f4..f38d36c367 100644 --- a/Xplat/src/main/java/vazkii/botania/api/mana/spark/ManaSpark.java +++ b/Xplat/src/main/java/vazkii/botania/api/mana/spark/ManaSpark.java @@ -34,7 +34,7 @@ public interface ManaSpark extends SparkEntity { /** * Gets a collection of all Sparks this is tranfering to. */ - Collection getTransfers(); + Collection getOutgoingTransfers(); /** * Registers the Spark passed in as a Spark meant for mana to be transfered towards. diff --git a/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java b/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java index 933c93288b..88f9502a80 100644 --- a/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/entity/ManaSparkEntity.java @@ -57,7 +57,7 @@ public class ManaSparkEntity extends SparkBaseEntity implements ManaSpark { private static final String TAG_UPGRADE = "upgrade"; private static final EntityDataAccessor UPGRADE = SynchedEntityData.defineId(ManaSparkEntity.class, EntityDataSerializers.INT); - private final Set transfers = Collections.newSetFromMap(new WeakHashMap<>()); + private final Set outgoingTransfers = Collections.newSetFromMap(new WeakHashMap<>()); private final ArrayList transfersTowardsSelfToRegister = new ArrayList<>(); @@ -106,7 +106,7 @@ public void tick() { var receiver = getAttachedManaReceiver(); SparkUpgradeType upgrade = getUpgrade(); - Collection transfers = getTransfers(); + Collection transfers = getOutgoingTransfers(); switch (upgrade) { case DISPERSIVE -> { @@ -176,7 +176,7 @@ public void tick() { updateTransfers(); } if (!transfersTowardsSelfToRegister.isEmpty()) { - transfersTowardsSelfToRegister.remove(0).registerTransfer(this); + transfersTowardsSelfToRegister.remove(transfersTowardsSelfToRegister.size() - 1).registerTransfer(this); } } // Recessive does not need to be handled because recessive sparks get notified in all relevant cases @@ -228,6 +228,7 @@ public void tick() { @Override public void updateTransfers() { + transfersTowardsSelfToRegister.clear(); switch (getUpgrade()) { case RECESSIVE -> { var otherSparks = SparkHelper.getSparksAround(level(), getX(), getY() + (getBbHeight() / 2), getZ(), getNetwork()); @@ -238,7 +239,7 @@ public void updateTransfers() { && otherUpgrade != SparkUpgradeType.DOMINANT && otherUpgrade != SparkUpgradeType.RECESSIVE && otherUpgrade != SparkUpgradeType.ISOLATED) { - transfers.add(otherSpark); + outgoingTransfers.add(otherSpark); } } } @@ -301,7 +302,7 @@ public InteractionResult interact(Player player, InteractionHand hand) { setUpgrade(SparkUpgradeType.NONE); // Recalculate transfers, recessive and dominant will register the proper transfers - transfers.clear(); + outgoingTransfers.clear(); notifyOthers(getNetwork()); } else { dropAndKill(); @@ -363,7 +364,7 @@ public ManaReceiver getAttachedManaReceiver() { } private void filterTransfers() { - Iterator iter = transfers.iterator(); + Iterator iter = outgoingTransfers.iterator(); while (iter.hasNext()) { ManaSpark spark = iter.next(); SparkUpgradeType upgr = getUpgrade(); @@ -385,12 +386,12 @@ private void filterTransfers() { } @Override - public Collection getTransfers() { - return transfers; + public Collection getOutgoingTransfers() { + return outgoingTransfers; } private boolean hasTransfer(ManaSpark entity) { - return transfers.contains(entity); + return outgoingTransfers.contains(entity); } @Override @@ -398,7 +399,7 @@ public void registerTransfer(ManaSpark entity) { if (hasTransfer(entity)) { return; } - transfers.add(entity); + outgoingTransfers.add(entity); filterTransfers(); }