mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-14 04:00:30 +00:00
Access capabilities using PlatformHelper
We provide a new abstraction: ComponentAccess, which is a view of capabilities (or block lookups for Fabric) for adjacent blocks.
This commit is contained in:
parent
320007dbc6
commit
7d47b219c5
@ -111,7 +111,8 @@ minecraft {
|
||||
mods.register("cctest") {
|
||||
source(sourceSets["testMod"])
|
||||
source(sourceSets["testFixtures"])
|
||||
// FIXME: We need this for running in-dev but not from Gradle: source(project(":core").sourceSets.testFixtures.get())
|
||||
// FIXME: We need this for running in-dev but not from Gradle:
|
||||
// source(project(":core").sourceSets.testFixtures.get())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,11 +11,11 @@ import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.common.util.NonNullSupplier;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.function.IntSupplier;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Version of {@link net.minecraft.client.gui.components.ImageButton} which allows changing some properties
|
||||
@ -29,7 +29,7 @@ public class DynamicImageButton extends Button {
|
||||
private final int yDiffTex;
|
||||
private final int textureWidth;
|
||||
private final int textureHeight;
|
||||
private final NonNullSupplier<List<Component>> tooltip;
|
||||
private final Supplier<List<Component>> tooltip;
|
||||
|
||||
public DynamicImageButton(
|
||||
Screen screen, int x, int y, int width, int height, int xTexStart, int yTexStart, int yDiffTex,
|
||||
@ -47,7 +47,7 @@ public class DynamicImageButton extends Button {
|
||||
public DynamicImageButton(
|
||||
Screen screen, int x, int y, int width, int height, IntSupplier xTexStart, int yTexStart, int yDiffTex,
|
||||
ResourceLocation texture, int textureWidth, int textureHeight,
|
||||
OnPress onPress, NonNullSupplier<List<Component>> tooltip
|
||||
OnPress onPress, Supplier<List<Component>> tooltip
|
||||
) {
|
||||
super(x, y, width, height, Component.empty(), onPress);
|
||||
this.screen = screen;
|
||||
|
@ -5,25 +5,28 @@
|
||||
*/
|
||||
package dan200.computercraft.shared.computer.blocks;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.core.computer.ComputerSide;
|
||||
import dan200.computercraft.shared.BundledRedstone;
|
||||
import dan200.computercraft.shared.Peripherals;
|
||||
import dan200.computercraft.shared.common.TileGeneric;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.computer.core.ComputerState;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||
import dan200.computercraft.shared.computer.core.ServerContext;
|
||||
import dan200.computercraft.shared.network.container.ComputerContainerData;
|
||||
import dan200.computercraft.shared.platform.ComponentAccess;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import dan200.computercraft.shared.util.DirectionUtil;
|
||||
import dan200.computercraft.shared.util.IDAssigner;
|
||||
import dan200.computercraft.shared.util.RedstoneUtil;
|
||||
import joptsimple.internal.Strings;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.*;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
@ -32,7 +35,6 @@ import net.minecraft.world.level.block.entity.BaseContainerBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraftforge.common.util.NonNullConsumer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@ -51,7 +53,7 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
private boolean fresh = false;
|
||||
|
||||
private int invalidSides = 0;
|
||||
private final NonNullConsumer<Object>[] invalidate;
|
||||
private final ComponentAccess<IPeripheral> peripherals = PlatformHelper.get().createPeripheralAccess(d -> invalidSides |= 1 << d.ordinal());
|
||||
|
||||
private LockCode lockCode = LockCode.NO_LOCK;
|
||||
|
||||
@ -60,14 +62,6 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
public TileComputerBase(BlockEntityType<? extends TileGeneric> type, BlockPos pos, BlockState state, ComputerFamily family) {
|
||||
super(type, pos, state);
|
||||
this.family = family;
|
||||
|
||||
// We cache these so we can guarantee we only ever register one listener for adjacent capabilities.
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
var invalidate = this.invalidate = new NonNullConsumer[6];
|
||||
for (var direction : Direction.values()) {
|
||||
var mask = 1 << direction.ordinal();
|
||||
invalidate[direction.ordinal()] = o -> invalidSides |= mask;
|
||||
}
|
||||
}
|
||||
|
||||
protected void unload() {
|
||||
@ -231,8 +225,7 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
var localDir = remapToLocalSide(dir);
|
||||
if (isPeripheralBlockedOnSide(localDir)) return;
|
||||
|
||||
var offsetSide = dir.getOpposite();
|
||||
var peripheral = Peripherals.getPeripheral(getLevel(), getBlockPos().relative(dir), offsetSide, invalidate[dir.ordinal()]);
|
||||
var peripheral = peripherals.get((ServerLevel) getLevel(), getBlockPos(), dir);
|
||||
computer.setPeripheral(localDir, peripheral);
|
||||
}
|
||||
|
||||
|
@ -6,9 +6,9 @@
|
||||
package dan200.computercraft.shared.peripheral.modem.wired;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import dan200.computercraft.api.ForgeComputerCraftAPI;
|
||||
import dan200.computercraft.shared.ModRegistry;
|
||||
import dan200.computercraft.shared.common.BlockGeneric;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import dan200.computercraft.shared.util.WaterloggableHelpers;
|
||||
import dan200.computercraft.shared.util.WorldUtil;
|
||||
import net.minecraft.core.BlockPos;
|
||||
@ -76,10 +76,10 @@ public class BlockCable extends BlockGeneric implements SimpleWaterloggedBlock {
|
||||
return state.getValue(BlockCable.CABLE) && state.getValue(BlockCable.MODEM).getFacing() != direction;
|
||||
}
|
||||
|
||||
public static boolean doesConnectVisually(BlockState state, BlockGetter world, BlockPos pos, Direction direction) {
|
||||
public static boolean doesConnectVisually(BlockState state, Level level, BlockPos pos, Direction direction) {
|
||||
if (!state.getValue(CABLE)) return false;
|
||||
if (state.getValue(MODEM).getFacing() == direction) return true;
|
||||
return ForgeComputerCraftAPI.getWiredElementAt(world, pos.relative(direction), direction.getOpposite()).isPresent();
|
||||
return PlatformHelper.get().hasWiredElementIn(level, pos, direction);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ -171,7 +171,7 @@ public class BlockCable extends BlockGeneric implements SimpleWaterloggedBlock {
|
||||
return getFluidState(state).createLegacyBlock();
|
||||
}
|
||||
|
||||
return state.setValue(CONNECTIONS.get(side), doesConnectVisually(state, world, pos, side));
|
||||
return world instanceof Level level ? state.setValue(CONNECTIONS.get(side), doesConnectVisually(state, level, pos, side)) : state;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -6,7 +6,6 @@
|
||||
package dan200.computercraft.shared.peripheral.modem.wired;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import dan200.computercraft.api.ForgeComputerCraftAPI;
|
||||
import dan200.computercraft.api.network.wired.IWiredElement;
|
||||
import dan200.computercraft.api.network.wired.IWiredNode;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
@ -14,12 +13,15 @@ import dan200.computercraft.shared.ModRegistry;
|
||||
import dan200.computercraft.shared.command.text.ChatHelpers;
|
||||
import dan200.computercraft.shared.common.TileGeneric;
|
||||
import dan200.computercraft.shared.peripheral.modem.ModemState;
|
||||
import dan200.computercraft.shared.platform.ComponentAccess;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import dan200.computercraft.shared.util.DirectionUtil;
|
||||
import dan200.computercraft.shared.util.TickScheduler;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
@ -30,8 +32,6 @@ import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.common.util.NonNullConsumer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@ -99,7 +99,7 @@ public class TileCable extends TileGeneric {
|
||||
}
|
||||
};
|
||||
|
||||
private final NonNullConsumer<LazyOptional<IWiredElement>> connectedNodeChanged = x -> connectionsChanged();
|
||||
private final ComponentAccess<IWiredElement> connectedElements = PlatformHelper.get().createWiredElementAccess(x -> connectionsChanged());
|
||||
|
||||
public TileCable(BlockEntityType<? extends TileCable> type, BlockPos pos, BlockState state) {
|
||||
super(type, pos, state);
|
||||
@ -284,11 +284,10 @@ public class TileCable extends TileGeneric {
|
||||
var offset = current.relative(facing);
|
||||
if (!world.isLoaded(offset)) continue;
|
||||
|
||||
var element = ForgeComputerCraftAPI.getWiredElementAt(world, offset, facing.getOpposite());
|
||||
if (!element.isPresent()) continue;
|
||||
var element = connectedElements.get((ServerLevel) world, current, facing);
|
||||
if (element == null) continue;
|
||||
|
||||
element.addListener(connectedNodeChanged);
|
||||
var node = element.orElseThrow(NullPointerException::new).getNode();
|
||||
var node = element.getNode();
|
||||
if (BlockCable.canConnectIn(state, facing)) {
|
||||
// If we can connect to it then do so
|
||||
this.node.connectTo(node);
|
||||
|
@ -6,19 +6,21 @@
|
||||
package dan200.computercraft.shared.peripheral.modem.wired;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import dan200.computercraft.api.ForgeComputerCraftAPI;
|
||||
import dan200.computercraft.api.network.wired.IWiredElement;
|
||||
import dan200.computercraft.api.network.wired.IWiredNode;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.shared.command.text.ChatHelpers;
|
||||
import dan200.computercraft.shared.common.TileGeneric;
|
||||
import dan200.computercraft.shared.peripheral.modem.ModemState;
|
||||
import dan200.computercraft.shared.platform.ComponentAccess;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import dan200.computercraft.shared.util.DirectionUtil;
|
||||
import dan200.computercraft.shared.util.TickScheduler;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
@ -27,8 +29,6 @@ import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.common.util.NonNullConsumer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@ -89,7 +89,7 @@ public class TileWiredModemFull extends TileGeneric {
|
||||
private final WiredModemElement element = new FullElement(this);
|
||||
private final IWiredNode node = element.getNode();
|
||||
|
||||
private final NonNullConsumer<LazyOptional<IWiredElement>> connectedNodeChanged = x -> connectionsChanged();
|
||||
private final ComponentAccess<IWiredElement> connectedElements = PlatformHelper.get().createWiredElementAccess(x -> connectionsChanged());
|
||||
|
||||
private int invalidSides = 0;
|
||||
|
||||
@ -252,11 +252,10 @@ public class TileWiredModemFull extends TileGeneric {
|
||||
var offset = current.relative(facing);
|
||||
if (!world.isLoaded(offset)) continue;
|
||||
|
||||
var element = ForgeComputerCraftAPI.getWiredElementAt(world, offset, facing.getOpposite());
|
||||
if (!element.isPresent()) continue;
|
||||
var element = connectedElements.get((ServerLevel) getLevel(), getBlockPos(), facing);
|
||||
if (element == null) return;
|
||||
|
||||
element.addListener(connectedNodeChanged);
|
||||
node.connectTo(element.orElseThrow(NullPointerException::new).getNode());
|
||||
node.connectTo(element.getNode());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,14 +7,15 @@ package dan200.computercraft.shared.peripheral.modem.wired;
|
||||
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.shared.ModRegistry;
|
||||
import dan200.computercraft.shared.Peripherals;
|
||||
import dan200.computercraft.shared.computer.core.ServerContext;
|
||||
import dan200.computercraft.shared.platform.ComponentAccess;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.common.util.NonNullConsumer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@ -35,10 +36,10 @@ public final class WiredModemLocalPeripheral {
|
||||
private String type;
|
||||
|
||||
private IPeripheral peripheral;
|
||||
private final NonNullConsumer<Object> invalidate;
|
||||
private final ComponentAccess<IPeripheral> peripherals;
|
||||
|
||||
public WiredModemLocalPeripheral(@Nonnull Runnable invalidate) {
|
||||
this.invalidate = x -> invalidate.run();
|
||||
peripherals = PlatformHelper.get().createPeripheralAccess(x -> invalidate.run());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -126,7 +127,7 @@ public final class WiredModemLocalPeripheral {
|
||||
var block = world.getBlockState(offset).getBlock();
|
||||
if (block == ModRegistry.Blocks.WIRED_MODEM_FULL.get() || block == ModRegistry.Blocks.CABLE.get()) return null;
|
||||
|
||||
var peripheral = Peripherals.getPeripheral(world, offset, direction.getOpposite(), invalidate);
|
||||
var peripheral = peripherals.get((ServerLevel) world, pos, direction);
|
||||
return peripheral instanceof WiredModemPeripheral ? null : peripheral;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.shared.platform;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A (possibly cached) provider of a component at a specific location.
|
||||
*
|
||||
* @param <T> The type of the component.
|
||||
*/
|
||||
public interface ComponentAccess<T> {
|
||||
/**
|
||||
* Get a peripheral for the current block.
|
||||
* <p>
|
||||
* Both {@code level} and {@code pos} must be constant for the lifetime of the store.
|
||||
*
|
||||
* @param level The current level.
|
||||
* @param pos The position of the block fetching the peripheral, for instance the computer or modem.
|
||||
* @param direction The direction the peripheral is in.
|
||||
* @return The peripheral, or {@literal null} if not found.
|
||||
* @throws IllegalStateException If the level or position have changed.
|
||||
*/
|
||||
@Nullable
|
||||
T get(ServerLevel level, BlockPos pos, Direction direction);
|
||||
}
|
@ -5,10 +5,13 @@
|
||||
*/
|
||||
package dan200.computercraft.shared.platform;
|
||||
|
||||
import dan200.computercraft.api.network.wired.IWiredElement;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import dan200.computercraft.shared.network.client.ClientNetworkContext;
|
||||
import dan200.computercraft.shared.network.container.ContainerData;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
@ -20,6 +23,7 @@ import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
@ -30,6 +34,7 @@ import net.minecraft.world.phys.Vec3;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
@ -146,4 +151,34 @@ public interface PlatformHelper extends dan200.computercraft.impl.PlatformHelper
|
||||
* @param chunk The chunk players must be tracking.
|
||||
*/
|
||||
void sendToAllTracking(NetworkMessage<ClientNetworkContext> message, LevelChunk chunk);
|
||||
|
||||
/**
|
||||
* Create a {@link ComponentAccess} for surrounding peripherals.
|
||||
*
|
||||
* @param invalidate The function to call when a neighbouring peripheral potentially changes. This <em>MAY NOT</em>
|
||||
* include all changes, and so block updates should still be listened to.
|
||||
* @return The peripheral component access.
|
||||
*/
|
||||
ComponentAccess<IPeripheral> createPeripheralAccess(Consumer<Direction> invalidate);
|
||||
|
||||
/**
|
||||
* Create a {@link ComponentAccess} for surrounding wired nodes.
|
||||
*
|
||||
* @param invalidate The function to call when a neighbouring wired node potentially changes. This <em>MAY NOT</em>
|
||||
* include all changes, and so block updates should still be listened to.
|
||||
* @return The peripheral component access.
|
||||
*/
|
||||
ComponentAccess<IWiredElement> createWiredElementAccess(Consumer<Direction> invalidate);
|
||||
|
||||
/**
|
||||
* Determine if there is a wired element in the given direction. This is equivalent to
|
||||
* {@code createWiredElementAt(x -> {}).get(level, pos, dir) != null}, but is intended for when we don't need the
|
||||
* cache.
|
||||
*
|
||||
* @param level The current level.
|
||||
* @param pos The <em>current</em> block's position.
|
||||
* @param direction The direction to check in.
|
||||
* @return Whether there is a wired element in the given direction.
|
||||
*/
|
||||
boolean hasWiredElementIn(Level level, BlockPos pos, Direction direction);
|
||||
}
|
||||
|
@ -7,10 +7,16 @@ package dan200.computercraft.shared.platform;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.network.wired.IWiredElement;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.shared.Capabilities;
|
||||
import dan200.computercraft.shared.Peripherals;
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import dan200.computercraft.shared.network.client.ClientNetworkContext;
|
||||
import dan200.computercraft.shared.network.container.ContainerData;
|
||||
import dan200.computercraft.shared.util.CapabilityUtil;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
@ -24,13 +30,16 @@ import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.extensions.IForgeMenuType;
|
||||
import net.minecraftforge.common.util.NonNullConsumer;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.minecraftforge.network.NetworkHooks;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
@ -43,6 +52,7 @@ import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@ -118,6 +128,24 @@ public class PlatformHelperImpl implements PlatformHelper {
|
||||
NetworkHandler.sendToAllTracking(message, chunk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentAccess<IPeripheral> createPeripheralAccess(Consumer<Direction> invalidate) {
|
||||
return new PeripheralAccess(invalidate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentAccess<IWiredElement> createWiredElementAccess(Consumer<Direction> invalidate) {
|
||||
return new CapabilityAccess<>(Capabilities.CAPABILITY_WIRED_ELEMENT, invalidate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasWiredElementIn(Level level, BlockPos pos, Direction direction) {
|
||||
if (!level.isLoaded(pos)) return false;
|
||||
|
||||
var blockEntity = level.getBlockEntity(pos.relative(direction));
|
||||
return blockEntity != null && blockEntity.getCapability(Capabilities.CAPABILITY_WIRED_ELEMENT, direction.getOpposite()).isPresent();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CompoundTag getShareTag(ItemStack item) {
|
||||
@ -190,4 +218,62 @@ public class PlatformHelperImpl implements PlatformHelper {
|
||||
return object.get();
|
||||
}
|
||||
}
|
||||
|
||||
private abstract static class ComponentAccessImpl<T> implements ComponentAccess<T> {
|
||||
private final NonNullConsumer<Object>[] invalidators;
|
||||
private @Nullable Level level;
|
||||
private @Nullable BlockPos pos;
|
||||
|
||||
ComponentAccessImpl(Consumer<Direction> invalidate) {
|
||||
// Generate a cache of invalidation functions so we can guarantee we only ever have one registered per
|
||||
// capability - there's no way to remove these callbacks!
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
var invalidators = this.invalidators = new NonNullConsumer[6];
|
||||
for (var dir : Direction.values()) invalidators[dir.ordinal()] = x -> invalidate.accept(dir);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract T get(ServerLevel world, BlockPos pos, Direction side, NonNullConsumer<Object> invalidate);
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public T get(ServerLevel level, BlockPos pos, Direction direction) {
|
||||
if (this.level != null && this.level != level) throw new IllegalStateException("Level has changed");
|
||||
if (this.pos != null && this.pos != pos) throw new IllegalStateException("Position has changed");
|
||||
|
||||
this.level = level;
|
||||
this.pos = pos;
|
||||
return get(level, pos.relative(direction), direction.getOpposite(), invalidators[direction.ordinal()]);
|
||||
}
|
||||
}
|
||||
|
||||
private static class PeripheralAccess extends ComponentAccessImpl<IPeripheral> {
|
||||
PeripheralAccess(Consumer<Direction> invalidate) {
|
||||
super(invalidate);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected IPeripheral get(ServerLevel world, BlockPos pos, Direction side, NonNullConsumer<Object> invalidate) {
|
||||
return Peripherals.getPeripheral(world, pos, side, invalidate);
|
||||
}
|
||||
}
|
||||
|
||||
private static class CapabilityAccess<T> extends ComponentAccessImpl<T> {
|
||||
private final Capability<T> capability;
|
||||
|
||||
CapabilityAccess(Capability<T> capability, Consumer<Direction> invalidate) {
|
||||
super(invalidate);
|
||||
this.capability = capability;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected T get(ServerLevel world, BlockPos pos, Direction side, NonNullConsumer<Object> invalidate) {
|
||||
if (!world.isLoaded(pos)) return null;
|
||||
|
||||
var blockEntity = world.getBlockEntity(pos);
|
||||
return blockEntity != null ? CapabilityUtil.unwrap(blockEntity.getCapability(capability, side), invalidate) : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user