safety = null

- Do not crash when instances passed to api methods are null.
  - Ignore null crumbling instances.
  - Do not attempt to steal null instances.
- Add nullability annotations where relevant.
- Update docs to indicate null behavior.
This commit is contained in:
Jozufozu 2024-01-19 16:18:38 -08:00
parent 04dff58714
commit b49073ebee
5 changed files with 22 additions and 4 deletions

View file

@ -2,6 +2,8 @@ package com.jozufozu.flywheel.api.backend;
import java.util.List;
import org.jetbrains.annotations.NotNull;
import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instance.Instance;
@ -65,6 +67,6 @@ public interface Engine extends InstancerProvider {
* @param pos The position of the block.
* @param instances The instances associated with the BE at this position.
*/
record CrumblingBlock(int progress, BlockPos pos, List<Instance> instances) {
record CrumblingBlock(int progress, BlockPos pos, List<@NotNull Instance> instances) {
}
}

View file

@ -1,5 +1,7 @@
package com.jozufozu.flywheel.api.instance;
import org.jetbrains.annotations.Nullable;
/**
* An instancer is how you interact with an instanced model.
* <p>
@ -31,11 +33,13 @@ public interface Instancer<I extends Instance> {
* <br><br>
* If the given instance is already owned by this instancer, this method does nothing.
* <br>
* If the given instance is {@code null}, this method does nothing.
* <br>
* If the given instance was created by a different backend, the behavior of this method is undefined.
*
* @param instance The instance to steal.
*/
void stealInstance(I instance);
void stealInstance(@Nullable I instance);
/**
* Populate arr with new instances of this model.

View file

@ -2,6 +2,8 @@ package com.jozufozu.flywheel.api.visual;
import java.util.function.Consumer;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.instance.Instance;
import net.minecraft.world.level.block.entity.BlockEntity;
@ -10,8 +12,10 @@ public interface BlockEntityVisual<T extends BlockEntity> extends Visual {
/**
* Collect all instances that should render with a crumbling overlay
* when the block corresponding to this visual is being broken.
* <br>
* Passing {@code null} to the consumer has no effect.
*
* @param consumer A consumer to provide instances to.
*/
void collectCrumblingInstances(Consumer<Instance> consumer);
void collectCrumblingInstances(Consumer<@Nullable Instance> consumer);
}

View file

@ -36,6 +36,10 @@ public abstract class AbstractInstancer<I extends Instance> implements Instancer
@Override
public void stealInstance(I instance) {
if (instance == null) {
return;
}
var instanceHandle = instance.handle();
if (!(instanceHandle instanceof InstanceHandleImpl handle)) {

View file

@ -230,7 +230,11 @@ public class VisualizationManagerImpl implements VisualizationManager {
List<Instance> instances = new ArrayList<>();
visual.collectCrumblingInstances(instances::add);
visual.collectCrumblingInstances(instance -> {
if (instance != null) {
instances.add(instance);
}
});
if (instances.isEmpty()) {
// The visual doesn't want to render anything crumbling.