-
Notifications
You must be signed in to change notification settings - Fork 219
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Unify the generic peirpheral system a litte
Allows registering arbitrary block lookup functions instead of a platform-specific capability. This is roughly what Fabric did before, but generalised to also take an invalidation callback. This callback is a little nasty - it needs to be a NonNullableConsumer on Forge, but that class isn't available on Fabric. For now, we make the lookup function (and thus the generic peripheral provider) generic on some <T extends Runnable> type, then specialise that on the Forge side. Hopefully we can clean this up when NeoForge reworks capabilities.
- Loading branch information
Showing
13 changed files
with
245 additions
and
157 deletions.
There are no files selected for viewing
36 changes: 36 additions & 0 deletions
36
.../common/src/main/java/dan200/computercraft/shared/peripheral/generic/ComponentLookup.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers | ||
// | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
package dan200.computercraft.shared.peripheral.generic; | ||
|
||
import net.minecraft.core.BlockPos; | ||
import net.minecraft.core.Direction; | ||
import net.minecraft.world.level.Level; | ||
import net.minecraft.world.level.block.entity.BlockEntity; | ||
import net.minecraft.world.level.block.state.BlockState; | ||
|
||
import javax.annotation.Nullable; | ||
|
||
/** | ||
* Extract some component (for instance a capability on Forge, or a {@code BlockApiLookup} on Fabric) from a block and | ||
* block entity. | ||
* | ||
* @param <C> A platform-specific type, used for the invalidation callback. | ||
*/ | ||
public interface ComponentLookup<C extends Runnable> { | ||
/** | ||
* Extract some component from a block in the world. | ||
* | ||
* @param level The current level. | ||
* @param pos The position of the block in the level. | ||
* @param state The block state at that position. | ||
* @param blockEntity The block entity at that position. | ||
* @param side The side of the block to extract the component from. Implementations should try to use a | ||
* sideless lookup first, but may fall back to a sided lookup if needed. | ||
* @param invalidate An invalidation function to call if this component changes. | ||
* @return The found component, or {@code null} if not present. | ||
*/ | ||
@Nullable | ||
Object find(Level level, BlockPos pos, BlockState state, BlockEntity blockEntity, Direction side, C invalidate); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
69 changes: 69 additions & 0 deletions
69
...c/main/java/dan200/computercraft/shared/peripheral/generic/GenericPeripheralProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// SPDX-FileCopyrightText: 2020 The CC: Tweaked Developers | ||
// | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
package dan200.computercraft.shared.peripheral.generic; | ||
|
||
import dan200.computercraft.api.lua.GenericSource; | ||
import dan200.computercraft.api.peripheral.IPeripheral; | ||
import dan200.computercraft.core.methods.MethodSupplier; | ||
import dan200.computercraft.core.methods.PeripheralMethod; | ||
import dan200.computercraft.shared.computer.core.ServerContext; | ||
import net.minecraft.core.BlockPos; | ||
import net.minecraft.core.Direction; | ||
import net.minecraft.world.level.Level; | ||
import net.minecraft.world.level.block.entity.BlockEntity; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import javax.annotation.Nullable; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Objects; | ||
|
||
/** | ||
* A peripheral provider which finds methods from various {@linkplain GenericSource generic sources}. | ||
* <p> | ||
* Methods are found using the original block entity itself and a registered list of {@link ComponentLookup}s. | ||
* | ||
* @param <C> A platform-specific type, used for the invalidation callback. | ||
*/ | ||
public final class GenericPeripheralProvider<C extends Runnable> { | ||
private static final Logger LOG = LoggerFactory.getLogger(GenericPeripheralProvider.class); | ||
|
||
private final List<ComponentLookup<? super C>> lookups = new ArrayList<>(); | ||
|
||
/** | ||
* Register a component lookup function. | ||
* | ||
* @param lookup The component lookup function. | ||
*/ | ||
public synchronized void registerLookup(ComponentLookup<? super C> lookup) { | ||
Objects.requireNonNull(lookup); | ||
if (!lookups.contains(lookup)) lookups.add(lookup); | ||
} | ||
|
||
public void forEachMethod(MethodSupplier<PeripheralMethod> methods, Level level, BlockPos pos, Direction side, BlockEntity blockEntity, C invalidate, MethodSupplier.TargetedConsumer<PeripheralMethod> consumer) { | ||
methods.forEachMethod(blockEntity, consumer); | ||
|
||
for (var lookup : lookups) { | ||
var contents = lookup.find(level, pos, blockEntity.getBlockState(), blockEntity, side, invalidate); | ||
if (contents != null) methods.forEachMethod(contents, consumer); | ||
} | ||
} | ||
|
||
@Nullable | ||
public IPeripheral getPeripheral(Level level, BlockPos pos, Direction side, @Nullable BlockEntity blockEntity, C invalidate) { | ||
if (blockEntity == null) return null; | ||
|
||
var server = level.getServer(); | ||
if (server == null) { | ||
LOG.warn("Fetching peripherals on a non-server level {}.", level, new IllegalStateException("Fetching peripherals on a non-server level.")); | ||
return null; | ||
} | ||
|
||
var builder = new GenericPeripheralBuilder(); | ||
forEachMethod(ServerContext.get(server).peripheralMethods(), level, pos, side, blockEntity, invalidate, builder::addMethod); | ||
return builder.toPeripheral(blockEntity, side); | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
projects/fabric/src/main/java/dan200/computercraft/impl/Peripherals.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers | ||
// | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
package dan200.computercraft.impl; | ||
|
||
import dan200.computercraft.api.peripheral.IPeripheral; | ||
import dan200.computercraft.shared.peripheral.generic.ComponentLookup; | ||
import dan200.computercraft.shared.peripheral.generic.GenericPeripheralProvider; | ||
import net.minecraft.core.BlockPos; | ||
import net.minecraft.core.Direction; | ||
import net.minecraft.world.level.Level; | ||
import net.minecraft.world.level.block.entity.BlockEntity; | ||
|
||
import javax.annotation.Nullable; | ||
|
||
/** | ||
* The registry for peripheral providers. | ||
* <p> | ||
* This lives in the {@code impl} package despite it not being part of the public API, in order to mirror Forge's class. | ||
*/ | ||
public final class Peripherals { | ||
private static final GenericPeripheralProvider<Runnable> genericProvider = new GenericPeripheralProvider<>(); | ||
|
||
private Peripherals() { | ||
} | ||
|
||
public static void addGenericLookup(ComponentLookup<? super Runnable> lookup) { | ||
genericProvider.registerLookup(lookup); | ||
} | ||
|
||
public static @Nullable IPeripheral getGenericPeripheral(Level level, BlockPos pos, Direction side, @Nullable BlockEntity blockEntity, Runnable invalidate) { | ||
return genericProvider.getPeripheral(level, pos, side, blockEntity, invalidate); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
52 changes: 0 additions & 52 deletions
52
...c/main/java/dan200/computercraft/shared/peripheral/generic/GenericPeripheralProvider.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.