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 04b8a6ff07
commit 238fd68ef4
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 java.util.List;
import org.jetbrains.annotations.NotNull;
import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.Instance;
@ -65,6 +67,6 @@ public interface Engine extends InstancerProvider {
* @param pos The position of the block. * @param pos The position of the block.
* @param instances The instances associated with the BE at this position. * @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; package com.jozufozu.flywheel.api.instance;
import org.jetbrains.annotations.Nullable;
/** /**
* An instancer is how you interact with an instanced model. * An instancer is how you interact with an instanced model.
* <p> * <p>
@ -31,11 +33,13 @@ public interface Instancer<I extends Instance> {
* <br><br> * <br><br>
* If the given instance is already owned by this instancer, this method does nothing. * If the given instance is already owned by this instancer, this method does nothing.
* <br> * <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. * If the given instance was created by a different backend, the behavior of this method is undefined.
* *
* @param instance The instance to steal. * @param instance The instance to steal.
*/ */
void stealInstance(I instance); void stealInstance(@Nullable I instance);
/** /**
* Populate arr with new instances of this model. * 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 java.util.function.Consumer;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.Instance;
import net.minecraft.world.level.block.entity.BlockEntity; 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 * Collect all instances that should render with a crumbling overlay
* when the block corresponding to this visual is being broken. * 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. * @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 @Override
public void stealInstance(I instance) { public void stealInstance(I instance) {
if (instance == null) {
return;
}
var instanceHandle = instance.handle(); var instanceHandle = instance.handle();
if (!(instanceHandle instanceof InstanceHandleImpl handle)) { if (!(instanceHandle instanceof InstanceHandleImpl handle)) {

View File

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