diff --git a/sakura-server/src/main/java/me/samsuik/sakura/entity/merge/MergeStrategy.java b/sakura-server/src/main/java/me/samsuik/sakura/entity/merge/MergeStrategy.java index 3b490dd..2e813d3 100644 --- a/sakura-server/src/main/java/me/samsuik/sakura/entity/merge/MergeStrategy.java +++ b/sakura-server/src/main/java/me/samsuik/sakura/entity/merge/MergeStrategy.java @@ -87,7 +87,7 @@ public interface MergeStrategy { } Entity nextEntity = this.entityTable.getAndWrite(entity); - if (nextEntity == null || !nextEntity.level().equals(entity.level())) { + if (nextEntity == null || entity == nextEntity || !nextEntity.level().equals(entity.level())) { return null; } diff --git a/sakura-server/src/main/java/me/samsuik/sakura/entity/merge/TrackedMergeHistory.java b/sakura-server/src/main/java/me/samsuik/sakura/entity/merge/TrackedMergeHistory.java index 161d565..514c795 100644 --- a/sakura-server/src/main/java/me/samsuik/sakura/entity/merge/TrackedMergeHistory.java +++ b/sakura-server/src/main/java/me/samsuik/sakura/entity/merge/TrackedMergeHistory.java @@ -5,7 +5,6 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import me.samsuik.sakura.configuration.WorldConfiguration.Cannons.Mechanics.TNTSpread; import me.samsuik.sakura.utils.TickExpiry; -import net.minecraft.server.MinecraftServer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.item.FallingBlockEntity; import org.jetbrains.annotations.NotNull; @@ -14,48 +13,64 @@ public final class TrackedMergeHistory { private final Long2ObjectMap historyMap = new Long2ObjectOpenHashMap<>(); public boolean hasPreviousMerged(@NotNull Entity entity, @NotNull Entity into) { - PositionHistory positions = this.getHistory(into); - return positions != null && positions.has(entity.getPackedOriginPosition()); - } - - public void trackHistory(@NotNull Entity entity, @NotNull MergeEntityData mergeEntityData) { - long originPosition = entity.getPackedOriginPosition(); - PositionHistory positions = this.historyMap.computeIfAbsent(originPosition, p -> new PositionHistory()); - LongOpenHashSet originPositions = mergeEntityData.getOriginPositions(); - boolean createHistory = positions.hasTimePassed(160); - if (createHistory && (entity instanceof FallingBlockEntity || entity.level().sakuraConfig().cannons.mechanics.tntSpread == TNTSpread.ALL)) { - originPositions.forEach(pos -> this.historyMap.put(pos, positions)); - } - positions.trackPositions(originPositions, !createHistory); + PositionHistory positions = this.getHistory(into, false); + return positions != null && positions.hasPosition(entity); } public boolean hasMetCondition(@NotNull Entity entity, MergeCondition condition) { - PositionHistory positions = this.getHistory(entity); + PositionHistory positions = this.getHistory(entity, false); return positions != null && positions.hasMetConditions(entity, condition); } - private PositionHistory getHistory(Entity entity) { - long originPosition = entity.getPackedOriginPosition(); - return this.historyMap.get(originPosition); + private boolean shouldTrackAllPositions(Entity entity, MergeEntityData mergeEntityData) { + return entity instanceof FallingBlockEntity + || mergeEntityData.getMergeLevel() == MergeLevel.LENIENT + || entity.level().sakuraConfig().cannons.mechanics.tntSpread == TNTSpread.ALL; } - public void expire(long tick) { - this.historyMap.values().removeIf(p -> p.expiry().isExpired(tick)); + public void trackHistory(@NotNull Entity entity, @NotNull MergeEntityData mergeEntityData) { + PositionHistory positions = this.getHistory(entity, true); + LongOpenHashSet originPositions = mergeEntityData.getOriginPositions(); + long gameTime = entity.level().getGameTime(); + boolean retainHistory = positions.hasTicksPassed(gameTime, 160); + if (!retainHistory && this.shouldTrackAllPositions(entity, mergeEntityData)) { + originPositions.forEach(pos -> this.historyMap.put(pos, positions)); + } + positions.trackPositions(originPositions, retainHistory); + } + + public void expire(long gameTime) { + this.historyMap.values().removeIf(p -> p.expiry().isExpired(gameTime)); + } + + private PositionHistory getHistory(Entity entity, boolean create) { + long originPosition = entity.getPackedOriginPosition(); + PositionHistory history = this.historyMap.get(originPosition); + if (create && history == null) { + history = new PositionHistory(entity.level().getGameTime()); + this.historyMap.put(originPosition, history); + } + return history; } private static final class PositionHistory { private final LongOpenHashSet positions = new LongOpenHashSet(); - private final TickExpiry expiry = new TickExpiry(MinecraftServer.currentTick, 200); - private final long created = MinecraftServer.currentTick; + private final TickExpiry expiry; + private final long created; private int cycles = 0; + public PositionHistory(long gameTime) { + this.expiry = new TickExpiry(gameTime, 200); + this.created = gameTime; + } + public TickExpiry expiry() { return this.expiry; } - public boolean has(long position) { - this.expiry.refresh(MinecraftServer.currentTick); - return this.positions.contains(position); + public boolean hasPosition(Entity entity) { + this.expiry.refresh(entity.level().getGameTime()); + return this.positions.contains(entity.getPackedOriginPosition()); } public void trackPositions(LongOpenHashSet positions, boolean retain) { @@ -68,16 +83,16 @@ public final class TrackedMergeHistory { } public boolean hasMetConditions(@NotNull Entity entity, @NotNull MergeCondition condition) { - this.expiry.refresh(MinecraftServer.currentTick); - return condition.accept(entity, this.cycles, this.timeSinceCreation()); + long gameTime = entity.level().getGameTime(); + return condition.accept(entity, this.cycles, this.timeSinceCreation(gameTime)); } - public boolean hasTimePassed(int ticks) { - return this.timeSinceCreation() > ticks; + public boolean hasTicksPassed(long gameTime, int ticks) { + return this.timeSinceCreation(gameTime) > ticks; } - private long timeSinceCreation() { - return MinecraftServer.currentTick - this.created; + private long timeSinceCreation(long gameTime) { + return gameTime - this.created; } } }