Move field initializations out of constructor injects

They should be less fragile for breakages.

Additionally, modify PoiManagerMixin to work around an issue where
our getOrCreate() method is not being invoked _because_ its return
type was PoiSection and not Object. Apparently, the JVM will search
the superclass when a direct match (params+return type) is not found.
This commit is contained in:
Spottedleaf
2024-06-19 17:36:57 -07:00
parent 044a23f34a
commit 30cb658845
18 changed files with 44 additions and 136 deletions

View File

@@ -64,7 +64,7 @@ public abstract class ChunkHolderMixin extends GenerationChunkHolder implements
private NewChunkHolder newChunkHolder;
@Unique
private ReferenceList<ServerPlayer> playersSentChunkTo;
private final ReferenceList<ServerPlayer> playersSentChunkTo = new ReferenceList<>(EMPTY_PLAYER_ARRAY, 0);
@Unique
private ChunkMap getChunkMap() {
@@ -134,8 +134,6 @@ public abstract class ChunkHolderMixin extends GenerationChunkHolder implements
)
)
private void initFields(final CallbackInfo ci) {
this.playersSentChunkTo = new ReferenceList<>(EMPTY_PLAYER_ARRAY, 0);
this.fullChunkFuture = null;
this.tickingChunkFuture = null;
this.entityTickingChunkFuture = null;

View File

@@ -26,13 +26,13 @@ public abstract class ChunkStatusMixin implements ChunkSystemChunkStatus {
private boolean emptyLoadTask;
@Unique
private int writeRadius;
private int writeRadius = -1;
@Unique
private ChunkStatus nextStatus;
private ChunkStatus nextStatus = (ChunkStatus)(Object)this;
@Unique
private AtomicBoolean warnedAboutNoImmediateComplete;
private final AtomicBoolean warnedAboutNoImmediateComplete = new AtomicBoolean();
@Override
public final boolean moonrise$isParallelCapable() {
@@ -90,12 +90,8 @@ public abstract class ChunkStatusMixin implements ChunkSystemChunkStatus {
)
)
private void initFields(ChunkStatus prevStatus, EnumSet<Heightmap.Types> enumSet, ChunkType chunkType, CallbackInfo ci) {
this.isParallelCapable = false;
this.writeRadius = -1;
this.nextStatus = (ChunkStatus)(Object)this;
if (prevStatus != null) {
((ChunkStatusMixin)(Object)prevStatus).nextStatus = (ChunkStatus)(Object)this;
}
this.warnedAboutNoImmediateComplete = new AtomicBoolean();
}
}

View File

@@ -50,13 +50,13 @@ public abstract class EntityMixin implements ChunkSystemEntity {
private FullChunkStatus chunkStatus;
@Unique
private int sectionX;
private int sectionX = Integer.MIN_VALUE;
@Unique
private int sectionY;
private int sectionY = Integer.MIN_VALUE;
@Unique
private int sectionZ;
private int sectionZ = Integer.MIN_VALUE;
@Unique
private boolean updatingSectionStatus;
@@ -124,20 +124,6 @@ public abstract class EntityMixin implements ChunkSystemEntity {
return this.getIndirectPassengersStream().anyMatch((entity) -> entity instanceof Player);
}
/**
* @reason Initialise fields
* @author Spottedleaf
*/
@Inject(
method = "<init>",
at = @At(
value = "RETURN"
)
)
private void initHook(final CallbackInfo ci) {
this.sectionX = this.sectionY = this.sectionZ = Integer.MIN_VALUE;
}
/**
* @reason Stop bad mods from moving entities during section status updates, which otherwise would cause CMEs
* @author Spottedleaf

View File

@@ -26,7 +26,7 @@ public abstract class EntityTickListMixin {
private Int2ObjectMap<Entity> passive;
@Unique
private IteratorSafeOrderedReferenceSet<Entity> entities;
private final IteratorSafeOrderedReferenceSet<Entity> entities = new IteratorSafeOrderedReferenceSet<>();
/**
* @reason Initialise new fields and destroy old state
@@ -41,7 +41,6 @@ public abstract class EntityTickListMixin {
private void initHook(final CallbackInfo ci) {
this.active = null;
this.passive = null;
this.entities = new IteratorSafeOrderedReferenceSet<>();
}

View File

@@ -43,21 +43,7 @@ public abstract class LevelChunkTicksMixin<T> implements ChunkSystemLevelChunkTi
private boolean dirty;
@Unique
private long lastSaved;
/**
* @reason Hook to init fields
* @author Spottedleaf
*/
@Inject(
method = "<init>()V",
at = @At(
value = "RETURN"
)
)
private void init(final CallbackInfo ci) {
this.lastSaved = Long.MIN_VALUE;
}
private long lastSaved = Long.MIN_VALUE;
@Override
public final boolean moonrise$isDirty(final long tick) {

View File

@@ -34,7 +34,6 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
@@ -44,7 +43,9 @@ import java.util.function.Predicate;
import java.util.stream.Stream;
@Mixin(PoiManager.class)
public abstract class PoiManagerMixin extends SectionStorage<PoiSection> implements ChunkSystemPoiManager {
// Declare the generic type as Object so that our Overrides match the method signature of the superclass
// Specifically, getOrCreate must return Object so that existing invokes do not route to the superclass
public abstract class PoiManagerMixin extends SectionStorage<Object> implements ChunkSystemPoiManager {
@Shadow
abstract boolean isVillageCenter(long l);
@@ -52,7 +53,7 @@ public abstract class PoiManagerMixin extends SectionStorage<PoiSection> impleme
@Shadow
public abstract void checkConsistencyWithBlocks(SectionPos sectionPos, LevelChunkSection levelChunkSection);
public PoiManagerMixin(SimpleRegionStorage simpleRegionStorage, Function<Runnable, Codec<PoiSection>> function, Function<Runnable, PoiSection> function2, RegistryAccess registryAccess, ChunkIOErrorReporter chunkIOErrorReporter, LevelHeightAccessor levelHeightAccessor) {
public PoiManagerMixin(SimpleRegionStorage simpleRegionStorage, Function<Runnable, Codec<Object>> function, Function<Runnable, Object> function2, RegistryAccess registryAccess, ChunkIOErrorReporter chunkIOErrorReporter, LevelHeightAccessor levelHeightAccessor) {
super(simpleRegionStorage, function, function2, registryAccess, chunkIOErrorReporter, levelHeightAccessor);
}
@@ -62,7 +63,7 @@ public abstract class PoiManagerMixin extends SectionStorage<PoiSection> impleme
// the vanilla tracker needs to be replaced because it does not support level removes, and we need level removes
// to support poi unloading
@Unique
private Delayed26WayDistancePropagator3D villageDistanceTracker;
private final Delayed26WayDistancePropagator3D villageDistanceTracker = new Delayed26WayDistancePropagator3D();
@Unique
private static final int POI_DATA_SOURCE = 7;
@@ -95,7 +96,6 @@ public abstract class PoiManagerMixin extends SectionStorage<PoiSection> impleme
RegistryAccess registryAccess, ChunkIOErrorReporter chunkIOErrorReporter,
LevelHeightAccessor levelHeightAccessor, CallbackInfo ci) {
this.world = (ServerLevel)levelHeightAccessor;
this.villageDistanceTracker = new Delayed26WayDistancePropagator3D();
}
/**
@@ -145,7 +145,7 @@ public abstract class PoiManagerMixin extends SectionStorage<PoiSection> impleme
}
@Override
public Optional<PoiSection> get(final long pos) {
public Optional<Object> get(final long pos) {
final int chunkX = CoordinateUtils.getChunkSectionX(pos);
final int chunkY = CoordinateUtils.getChunkSectionY(pos);
final int chunkZ = CoordinateUtils.getChunkSectionZ(pos);
@@ -155,11 +155,11 @@ public abstract class PoiManagerMixin extends SectionStorage<PoiSection> impleme
final ChunkHolderManager manager = ((ChunkSystemServerLevel)this.world).moonrise$getChunkTaskScheduler().chunkHolderManager;
final PoiChunk ret = manager.getPoiChunkIfLoaded(chunkX, chunkZ, true);
return ret == null ? Optional.empty() : ret.getSectionForVanilla(chunkY);
return ret == null ? Optional.empty() : (Optional)ret.getSectionForVanilla(chunkY);
}
@Override
public Optional<PoiSection> getOrLoad(final long pos) {
public Optional<Object> getOrLoad(final long pos) {
final int chunkX = CoordinateUtils.getChunkSectionX(pos);
final int chunkY = CoordinateUtils.getChunkSectionY(pos);
final int chunkZ = CoordinateUtils.getChunkSectionZ(pos);
@@ -171,9 +171,9 @@ public abstract class PoiManagerMixin extends SectionStorage<PoiSection> impleme
if (chunkY >= WorldUtil.getMinSection(this.world) && chunkY <= WorldUtil.getMaxSection(this.world)) {
final PoiChunk ret = manager.getPoiChunkIfLoaded(chunkX, chunkZ, true);
if (ret != null) {
return ret.getSectionForVanilla(chunkY);
return (Optional)ret.getSectionForVanilla(chunkY);
} else {
return manager.loadPoiChunk(chunkX, chunkZ).getSectionForVanilla(chunkY);
return (Optional)manager.loadPoiChunk(chunkX, chunkZ).getSectionForVanilla(chunkY);
}
}
// retain vanilla behavior: do not load section if out of bounds!
@@ -181,7 +181,7 @@ public abstract class PoiManagerMixin extends SectionStorage<PoiSection> impleme
}
@Override
protected PoiSection getOrCreate(final long pos) {
protected Object getOrCreate(final long pos) {
final int chunkX = CoordinateUtils.getChunkSectionX(pos);
final int chunkY = CoordinateUtils.getChunkSectionY(pos);
final int chunkZ = CoordinateUtils.getChunkSectionZ(pos);

View File

@@ -34,21 +34,7 @@ public abstract class PoiSectionMixin implements ChunkSystemPoiSection {
@Unique
private Optional<PoiSection> noAllocOptional;
/**
* @reason Initialise fields
* @author Spottedleaf
*/
@Inject(
method = "<init>(Ljava/lang/Runnable;ZLjava/util/List;)V",
at = @At(
value = "RETURN"
)
)
private void init(final CallbackInfo ci) {
this.noAllocOptional = Optional.of((PoiSection)(Object)this);
}
private final Optional<PoiSection> noAllocOptional = Optional.of((PoiSection)(Object)this);;
@Override
public final boolean moonrise$isEmpty() {

View File

@@ -83,10 +83,10 @@ public abstract class ServerLevelMixin extends Level implements ChunkSystemServe
private EntityDataController entityDataController;
@Unique
private PoiDataController poiDataController;
private final PoiDataController poiDataController = new PoiDataController((ServerLevel)(Object)this);
@Unique
private ChunkDataController chunkDataController;
private final ChunkDataController chunkDataController = new ChunkDataController((ServerLevel)(Object)this);
@Unique
private ChunkTaskScheduler chunkTaskScheduler;
@@ -115,8 +115,6 @@ public abstract class ServerLevelMixin extends Level implements ChunkSystemServe
minecraftServer.forceSynchronousWrites()
)
);
this.poiDataController = new PoiDataController((ServerLevel)(Object)this);
this.chunkDataController = new ChunkDataController((ServerLevel)(Object)this);
this.moonrise$setEntityLookup(new ServerEntityLookup((ServerLevel)(Object)this, ((ServerLevel)(Object)this).new EntityCallbacks()));
this.chunkTaskScheduler = new ChunkTaskScheduler((ServerLevel)(Object)this, MoonriseCommon.WORKER_POOL);
}

View File

@@ -26,21 +26,7 @@ public abstract class ServerPlayerMixin extends Player implements ChunkSystemSer
private RegionizedPlayerChunkLoader.PlayerChunkLoaderData chunkLoader;
@Unique
private RegionizedPlayerChunkLoader.ViewDistanceHolder viewDistanceHolder;
/**
* @reason Initialise fields
* @author Spottedleaf
*/
@Inject(
method = "<init>",
at = @At(
value = "RETURN"
)
)
private void init(final CallbackInfo ci) {
this.viewDistanceHolder = new RegionizedPlayerChunkLoader.ViewDistanceHolder();
}
private RegionizedPlayerChunkLoader.ViewDistanceHolder viewDistanceHolder = new RegionizedPlayerChunkLoader.ViewDistanceHolder();
@Override
public final boolean moonrise$isRealPlayer() {

View File

@@ -48,7 +48,9 @@ public abstract class BlockStateBaseMixin extends StateHolder<Block, BlockState>
private static final AtomicInteger ID_GENERATOR = new AtomicInteger();
@Unique
private int id1, id2;
private final int id1 = HashCommon.murmurHash3(HashCommon.murmurHash3(ID_GENERATOR.getAndIncrement() + RANDOM_OFFSET) + RANDOM_OFFSET);
@Unique
private final int id2 = HashCommon.murmurHash3(HashCommon.murmurHash3(ID_GENERATOR.getAndIncrement() + RANDOM_OFFSET) + RANDOM_OFFSET);
@Unique
private boolean occludesFullBlock;
@@ -72,18 +74,6 @@ public abstract class BlockStateBaseMixin extends StateHolder<Block, BlockState>
}
}
@Inject(
method = "<init>",
at = @At(
value = "RETURN"
)
)
private void init(final CallbackInfo ci) {
// note: murmurHash3 has an inverse, so the field is still unique
this.id1 = HashCommon.murmurHash3(HashCommon.murmurHash3(ID_GENERATOR.getAndIncrement() + RANDOM_OFFSET) + RANDOM_OFFSET);
this.id2 = HashCommon.murmurHash3(HashCommon.murmurHash3(ID_GENERATOR.getAndIncrement() + RANDOM_OFFSET) + RANDOM_OFFSET);
}
/**
* @reason Init collision state only after cache is set up
* @author Spottedleaf

View File

@@ -12,7 +12,7 @@ import java.util.Arrays;
@Mixin(DiscreteVoxelShape.class)
public abstract class DiscreteVoxelShapeMixin implements CollisionDiscreteVoxelShape {
// ignore race conditions here: the shape is static, so it doesn't matter
// ignore race conditions on field read/write: the shape is static, so it doesn't matter
@Unique
private CachedShapeData cachedShapeData;

View File

@@ -80,7 +80,9 @@ public abstract class ExplosionMixin {
@Final
private boolean fire;
@Shadow @Final private DamageSource damageSource;
@Shadow
@Final private DamageSource damageSource;
@Unique
private static final double[] CACHED_RAYS;

View File

@@ -36,7 +36,7 @@ public abstract class AcquirePoiMixin {
final List<Pair<Holder<PoiType>, BlockPos>> ret = new ArrayList<>();
PoiAccess.findNearestPoiPositions(
poiManager, predicate, predicate2, blockPos, i, Double.MAX_VALUE, occup, true, 5, ret
poiManager, predicate, predicate2, blockPos, i, Double.MAX_VALUE, occup, PoiAccess.LOAD_FOR_SEARCHING, 5, ret
);
return ret.stream();

View File

@@ -39,8 +39,7 @@ public abstract class PoiManagerMixin extends SectionStorage<PoiSection> {
@Overwrite
public Optional<BlockPos> find(Predicate<Holder<PoiType>> typePredicate, Predicate<BlockPos> posPredicate, BlockPos pos,
int radius, PoiManager.Occupancy occupationStatus) {
// Diff from Paper: use load=true
BlockPos ret = PoiAccess.findAnyPoiPosition((PoiManager)(Object)this, typePredicate, posPredicate, pos, radius, occupationStatus, true);
BlockPos ret = PoiAccess.findAnyPoiPosition((PoiManager)(Object)this, typePredicate, posPredicate, pos, radius, occupationStatus, PoiAccess.LOAD_FOR_SEARCHING);
return Optional.ofNullable(ret);
}
@@ -51,8 +50,7 @@ public abstract class PoiManagerMixin extends SectionStorage<PoiSection> {
@Overwrite
public Optional<BlockPos> findClosest(Predicate<Holder<PoiType>> typePredicate, BlockPos pos, int radius,
PoiManager.Occupancy occupationStatus) {
// Diff from Paper: use load=true
BlockPos ret = PoiAccess.findClosestPoiDataPosition((PoiManager)(Object)this, typePredicate, null, pos, radius, radius * radius, occupationStatus, true);
BlockPos ret = PoiAccess.findClosestPoiDataPosition((PoiManager)(Object)this, typePredicate, null, pos, radius, radius * radius, occupationStatus, PoiAccess.LOAD_FOR_SEARCHING);
return Optional.ofNullable(ret);
}
@@ -63,9 +61,8 @@ public abstract class PoiManagerMixin extends SectionStorage<PoiSection> {
@Overwrite
public Optional<Pair<Holder<PoiType>, BlockPos>> findClosestWithType(Predicate<Holder<PoiType>> typePredicate, BlockPos pos,
int radius, PoiManager.Occupancy occupationStatus) {
// Diff from Paper: use load=true
return Optional.ofNullable(PoiAccess.findClosestPoiDataTypeAndPosition(
(PoiManager)(Object)this, typePredicate, null, pos, radius, radius * radius, occupationStatus, true
(PoiManager)(Object)this, typePredicate, null, pos, radius, radius * radius, occupationStatus, PoiAccess.LOAD_FOR_SEARCHING
));
}
@@ -76,8 +73,7 @@ public abstract class PoiManagerMixin extends SectionStorage<PoiSection> {
@Overwrite
public Optional<BlockPos> findClosest(Predicate<Holder<PoiType>> typePredicate, Predicate<BlockPos> posPredicate, BlockPos pos,
int radius, PoiManager.Occupancy occupationStatus) {
// Diff from Paper: use load=true
BlockPos ret = PoiAccess.findClosestPoiDataPosition((PoiManager)(Object)this, typePredicate, posPredicate, pos, radius, radius * radius, occupationStatus, true);
BlockPos ret = PoiAccess.findClosestPoiDataPosition((PoiManager)(Object)this, typePredicate, posPredicate, pos, radius, radius * radius, occupationStatus, PoiAccess.LOAD_FOR_SEARCHING);
return Optional.ofNullable(ret);
}
@@ -88,9 +84,8 @@ public abstract class PoiManagerMixin extends SectionStorage<PoiSection> {
@Overwrite
public Optional<BlockPos> take(Predicate<Holder<PoiType>> typePredicate, BiPredicate<Holder<PoiType>, BlockPos> biPredicate,
BlockPos pos, int radius) {
// Diff from Paper: use load=true
final PoiRecord closest = PoiAccess.findClosestPoiDataRecord(
(PoiManager)(Object)this, typePredicate, biPredicate, pos, radius, radius * radius, PoiManager.Occupancy.HAS_SPACE, true
(PoiManager)(Object)this, typePredicate, biPredicate, pos, radius, radius * radius, PoiManager.Occupancy.HAS_SPACE, PoiAccess.LOAD_FOR_SEARCHING
);
return Optional.ofNullable(closest).map(poi -> {
poi.acquireTicket();
@@ -106,9 +101,8 @@ public abstract class PoiManagerMixin extends SectionStorage<PoiSection> {
public Optional<BlockPos> getRandom(Predicate<Holder<PoiType>> typePredicate, Predicate<BlockPos> positionPredicate,
PoiManager.Occupancy occupationStatus, BlockPos pos, int radius, RandomSource random) {
List<PoiRecord> list = new ArrayList<>();
// Diff from Paper: use load=true
PoiAccess.findAnyPoiRecords(
(PoiManager)(Object)this, typePredicate, positionPredicate, pos, radius, occupationStatus, true, Integer.MAX_VALUE, list
(PoiManager)(Object)this, typePredicate, positionPredicate, pos, radius, occupationStatus, PoiAccess.LOAD_FOR_SEARCHING, Integer.MAX_VALUE, list
);
// the old method shuffled the list and then tried to find the first element in it that
@@ -131,7 +125,7 @@ public abstract class PoiManagerMixin extends SectionStorage<PoiSection> {
List<Pair<Holder<PoiType>, BlockPos>> ret = new ArrayList<>();
PoiAccess.findAnyPoiPositions(
(PoiManager)(Object)this, predicate, predicate2, blockPos, i, occupancy, true,
(PoiManager)(Object)this, predicate, predicate2, blockPos, i, occupancy, PoiAccess.LOAD_FOR_SEARCHING,
Integer.MAX_VALUE, ret
);
@@ -149,7 +143,7 @@ public abstract class PoiManagerMixin extends SectionStorage<PoiSection> {
List<Pair<Holder<PoiType>, BlockPos>> ret = new ArrayList<>();
PoiAccess.findNearestPoiPositions(
(PoiManager)(Object)this, predicate, predicate2, blockPos, i, Double.MAX_VALUE, occupancy, true, Integer.MAX_VALUE, ret
(PoiManager)(Object)this, predicate, predicate2, blockPos, i, Double.MAX_VALUE, occupancy, PoiAccess.LOAD_FOR_SEARCHING, Integer.MAX_VALUE, ret
);
return ret.stream();

View File

@@ -40,5 +40,4 @@ public abstract class SectionRenderDispatcherMixin {
}
);
}
}

View File

@@ -28,21 +28,7 @@ public abstract class ConnectionMixin extends SimpleChannelInboundHandler<Packet
private static final int DEFAULT_TIMEOUT = 30;
@Unique
private volatile int timeout;
/**
* @reason Initialise fields during construction
* @author Spottedleaf
*/
@Inject(
method = "<init>",
at = @At(
value = "RETURN"
)
)
private void init(final CallbackInfo ci) {
this.timeout = DEFAULT_TIMEOUT;
}
private volatile int timeout = DEFAULT_TIMEOUT;
@Override
public final int moonrise$getReadTimeout() {

View File

@@ -726,7 +726,7 @@ public final class ChunkTaskScheduler {
final int neighbourReadRadius = Math.max(
0,
chunkPyramid.getStepTo(toStatus).getAccumulatedRadiusOf(ChunkStatus.EMPTY)
chunkStep.getAccumulatedRadiusOf(ChunkStatus.EMPTY)
);
boolean unGeneratedNeighbours = false;

View File

@@ -29,6 +29,8 @@ import java.util.function.Predicate;
*/
public final class PoiAccess {
public static final boolean LOAD_FOR_SEARCHING = true;
protected static double clamp(final double val, final double min, final double max) {
return (val < min ? min : (val > max ? max : val));
}