9
0
mirror of https://github.com/Samsuik/Sakura.git synced 2025-12-28 11:19:08 +00:00

fix entity data becoming desynced after an explosion

This commit is contained in:
Samsuik
2025-11-05 13:32:14 +00:00
parent 8f1e16bd0e
commit 2e55f58b6b
2 changed files with 26 additions and 0 deletions

View File

@@ -4,6 +4,7 @@ import ca.spottedleaf.moonrise.common.util.WorldUtil;
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices;
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup;
import it.unimi.dsi.fastutil.objects.*;
import me.samsuik.sakura.entity.EntityState;
import me.samsuik.sakura.mechanics.MechanicVersion;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
@@ -26,11 +27,13 @@ public abstract class SpecialisedExplosion<T extends Entity> extends ServerExplo
private static final double ENTITY_DISPATCH_DISTANCE_SQR = 32.0 * 32.0;
protected final T cause; // preferred over source
protected final Deque<Entity> sourceEntities = new ArrayDeque<>();
private Vec3 dispatchPosition;
private final List<Vec3> bufferedExplosions = new ObjectArrayList<>();
private AABB bounds;
private final Set<BlockPos> gameEvents = new ObjectOpenHashSet<>();
private final Deque<ExplosionToSend> explosionsToSend = new ArrayDeque<>();
private final Map<Entity, EntityState> entityStates = new Reference2ObjectOpenHashMap<>();
public SpecialisedExplosion(
final ServerLevel level,
@@ -46,6 +49,7 @@ public abstract class SpecialisedExplosion<T extends Entity> extends ServerExplo
this.cause = entity;
this.dispatchPosition = center;
this.bounds = new AABB(center, center);
this.sourceEntities.add(entity);
}
public final Queue<ExplosionToSend> getExplosionsToSend() {
@@ -61,7 +65,16 @@ public abstract class SpecialisedExplosion<T extends Entity> extends ServerExplo
@Override
public final int explode() {
this.createBlockCache();
// Handle batching, entities, blocks and events
final int blocksDestroyed = this.handleExplosion();
// Apply entity states (this is so plugins have up to date entity information)
this.entityStates.forEach((entity, state) -> {
state.apply(entity);
entity.updateBukkitHandle(entity); // restore entity handle
});
this.clearBlockCache();
return blocksDestroyed;
}
@@ -77,6 +90,12 @@ public abstract class SpecialisedExplosion<T extends Entity> extends ServerExplo
? this.calculateExplodedPositions()
: List.of();
// Poll the sourceEntities queue and keep track of the entity state
final Entity head = this.sourceEntities.poll();
if (head != null) {
this.entityStates.put(head, EntityState.of(this.cause));
}
// Buffer explosions to reduce the amount of calculations and improve locality
this.bounds = this.bounds.expand(center);
this.bufferedExplosions.add(center);

View File

@@ -70,6 +70,13 @@ public final class TntExplosion extends SpecialisedExplosion<PrimedTnt> {
// Merge the found entity into the explosion source
this.level().mergeHandler.mergeEntity(mergeEntity, cause);
// To keep track of this for merged entities we'd need to sort the connected entity list.
// Which I don't think is worth the cost. If you're running a cannon server and want people
// to have access to accurate entity data consider turning off merging or make it accessible.
// Add the found entity to the source entities
this.sourceEntities.add(foundEntity);
}
entities.finishRawIterator();
}