Skip to content

Commit

Permalink
refactor: allow multiple containers within a single container block e…
Browse files Browse the repository at this point in the history
…ntity
  • Loading branch information
raoulvdberge committed Apr 5, 2024
1 parent 22b47e4 commit 873e141
Show file tree
Hide file tree
Showing 44 changed files with 553 additions and 345 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.refinedmods.refinedstorage2.api.network.node.container;

import com.refinedmods.refinedstorage2.api.network.node.GraphNetworkComponent;
import com.refinedmods.refinedstorage2.api.network.node.NetworkNode;

import javax.annotation.Nullable;
Expand All @@ -18,7 +17,8 @@ public interface NetworkNodeContainer {
* The key must be kept stable, and must stay the same for the lifetime of the container.
* If it changes after adding it into the graph, the container would not be removed from the key index when the
* container is removed!
* The container can be queried by {@link GraphNetworkComponent#getContainer(Object)}.
* The container can be queried by
* {@link com.refinedmods.refinedstorage2.api.network.node.GraphNetworkComponent#getContainer(Object)}.
*
* @return the key, or null if indexing is not required
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.refinedmods.refinedstorage2.api.network.Network;
import com.refinedmods.refinedstorage2.api.network.NetworkComponent;
import com.refinedmods.refinedstorage2.api.network.energy.EnergyStorage;
import com.refinedmods.refinedstorage2.api.network.node.NetworkNode;
import com.refinedmods.refinedstorage2.api.network.security.SecurityPolicy;
import com.refinedmods.refinedstorage2.api.resource.ResourceKey;
import com.refinedmods.refinedstorage2.platform.api.constructordestructor.ConstructorStrategyFactory;
Expand All @@ -30,7 +31,8 @@
import com.refinedmods.refinedstorage2.platform.api.storagemonitor.StorageMonitorExtractionStrategy;
import com.refinedmods.refinedstorage2.platform.api.storagemonitor.StorageMonitorInsertionStrategy;
import com.refinedmods.refinedstorage2.platform.api.support.energy.EnergyItemHelper;
import com.refinedmods.refinedstorage2.platform.api.support.network.PlatformNetworkNodeContainer;
import com.refinedmods.refinedstorage2.platform.api.support.network.ConnectionLogic;
import com.refinedmods.refinedstorage2.platform.api.support.network.InWorldNetworkNodeContainer;
import com.refinedmods.refinedstorage2.platform.api.support.network.bounditem.NetworkBoundItemHelper;
import com.refinedmods.refinedstorage2.platform.api.support.network.bounditem.SlotReference;
import com.refinedmods.refinedstorage2.platform.api.support.network.bounditem.SlotReferenceFactory;
Expand All @@ -46,6 +48,8 @@
import java.util.Collection;
import java.util.Optional;
import java.util.Set;
import java.util.function.Supplier;
import javax.annotation.Nullable;

import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
Expand All @@ -57,6 +61,7 @@
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
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 org.apiguardian.api.API;
Expand Down Expand Up @@ -107,11 +112,20 @@ public interface PlatformApi {

BuiltinUpgradeDestinations getBuiltinUpgradeDestinations();

void requestNetworkNodeInitialization(PlatformNetworkNodeContainer container, Level level, Runnable callback);
InWorldNetworkNodeContainer createInWorldNetworkNodeContainer(BlockEntity blockEntity,
NetworkNode node,
String name,
int priority,
@Nullable ConnectionLogic connectionLogic,
@Nullable Supplier<Object> keyProvider);

void requestNetworkNodeRemoval(PlatformNetworkNodeContainer container, Level level);
void onNetworkNodeContainerInitialized(InWorldNetworkNodeContainer container,
@Nullable Level level,
@Nullable Runnable callback);

void requestNetworkNodeUpdate(PlatformNetworkNodeContainer container, Level level);
void onNetworkNodeContainerRemoved(InWorldNetworkNodeContainer container, @Nullable Level level);

void onNetworkNodeContainerUpdated(InWorldNetworkNodeContainer container, @Nullable Level level);

GridInsertionStrategy createGridInsertionStrategy(AbstractContainerMenu containerMenu,
ServerPlayer player,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.refinedmods.refinedstorage2.api.network.Network;
import com.refinedmods.refinedstorage2.api.network.NetworkComponent;
import com.refinedmods.refinedstorage2.api.network.energy.EnergyStorage;
import com.refinedmods.refinedstorage2.api.network.node.NetworkNode;
import com.refinedmods.refinedstorage2.api.network.security.SecurityPolicy;
import com.refinedmods.refinedstorage2.api.resource.ResourceKey;
import com.refinedmods.refinedstorage2.platform.api.constructordestructor.ConstructorStrategyFactory;
Expand All @@ -30,7 +31,8 @@
import com.refinedmods.refinedstorage2.platform.api.storagemonitor.StorageMonitorExtractionStrategy;
import com.refinedmods.refinedstorage2.platform.api.storagemonitor.StorageMonitorInsertionStrategy;
import com.refinedmods.refinedstorage2.platform.api.support.energy.EnergyItemHelper;
import com.refinedmods.refinedstorage2.platform.api.support.network.PlatformNetworkNodeContainer;
import com.refinedmods.refinedstorage2.platform.api.support.network.ConnectionLogic;
import com.refinedmods.refinedstorage2.platform.api.support.network.InWorldNetworkNodeContainer;
import com.refinedmods.refinedstorage2.platform.api.support.network.bounditem.NetworkBoundItemHelper;
import com.refinedmods.refinedstorage2.platform.api.support.network.bounditem.SlotReference;
import com.refinedmods.refinedstorage2.platform.api.support.network.bounditem.SlotReferenceFactory;
Expand All @@ -46,6 +48,7 @@
import java.util.Collection;
import java.util.Optional;
import java.util.Set;
import java.util.function.Supplier;
import javax.annotation.Nullable;

import net.minecraft.core.BlockPos;
Expand All @@ -58,6 +61,7 @@
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;

Expand Down Expand Up @@ -178,20 +182,41 @@ public BuiltinUpgradeDestinations getBuiltinUpgradeDestinations() {
}

@Override
public void requestNetworkNodeInitialization(final PlatformNetworkNodeContainer container,
final Level level,
final Runnable callback) {
ensureLoaded().requestNetworkNodeInitialization(container, level, callback);
public InWorldNetworkNodeContainer createInWorldNetworkNodeContainer(
final BlockEntity blockEntity,
final NetworkNode node,
final String name,
final int priority,
@Nullable final ConnectionLogic connectionLogic,
@Nullable final Supplier<Object> keyProvider
) {
return ensureLoaded().createInWorldNetworkNodeContainer(
blockEntity,
node,
name,
priority,
connectionLogic,
keyProvider
);
}

@Override
public void requestNetworkNodeRemoval(final PlatformNetworkNodeContainer container, final Level level) {
ensureLoaded().requestNetworkNodeRemoval(container, level);
public void onNetworkNodeContainerInitialized(final InWorldNetworkNodeContainer container,
@Nullable final Level level,
@Nullable final Runnable callback) {
ensureLoaded().onNetworkNodeContainerInitialized(container, level, callback);
}

@Override
public void requestNetworkNodeUpdate(final PlatformNetworkNodeContainer container, final Level level) {
ensureLoaded().requestNetworkNodeUpdate(container, level);
public void onNetworkNodeContainerRemoved(final InWorldNetworkNodeContainer container,
@Nullable final Level level) {
ensureLoaded().onNetworkNodeContainerRemoved(container, level);
}

@Override
public void onNetworkNodeContainerUpdated(final InWorldNetworkNodeContainer container,
@Nullable final Level level) {
ensureLoaded().onNetworkNodeContainerUpdated(container, level);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,27 @@
import com.refinedmods.refinedstorage2.api.network.Network;
import com.refinedmods.refinedstorage2.api.network.node.NetworkNode;
import com.refinedmods.refinedstorage2.api.network.security.Permission;
import com.refinedmods.refinedstorage2.platform.api.support.network.InWorldNetworkNodeContainer;

import java.util.Set;

import net.minecraft.server.level.ServerPlayer;

public final class SecurityHelper {
private SecurityHelper() {
}

public static boolean isAllowed(final ServerPlayer player,
final Permission permission,
final Set<InWorldNetworkNodeContainer> containers) {
for (final InWorldNetworkNodeContainer container : containers) {
if (!isAllowed(player, permission, container.getNode())) {
return false;
}
}
return true;
}

public static boolean isAllowed(final ServerPlayer player, final Permission permission, final NetworkNode node) {
final Network network = node.getNetwork();
if (network == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,87 +3,78 @@
import com.refinedmods.refinedstorage2.api.network.node.NetworkNode;
import com.refinedmods.refinedstorage2.platform.api.PlatformApi;

import java.util.HashSet;
import java.util.Set;
import javax.annotation.Nullable;

import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.GlobalPos;
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 org.apiguardian.api.API;

import static java.util.Objects.requireNonNull;

@API(status = API.Status.STABLE, since = "2.0.0-milestone.1.2")
public abstract class AbstractNetworkNodeContainerBlockEntity<T extends NetworkNode> extends BlockEntity
implements PlatformNetworkNodeContainer {
private final T node;
implements NetworkNodeContainerBlockEntity {
protected static final String MAIN_CONTAINER_NAME = "main";

protected final T mainNode;
protected final InWorldNetworkNodeContainer mainContainer;

@Nullable
protected Runnable initializationCallback;

private final Set<InWorldNetworkNodeContainer> containers = new HashSet<>();

protected AbstractNetworkNodeContainerBlockEntity(final BlockEntityType<?> type,
final BlockPos pos,
final BlockState state,
final T node) {
final T mainNode) {
super(type, pos, state);
this.node = node;
}

@Override
public void clearRemoved() {
super.clearRemoved();
if (level == null || level.isClientSide) {
return;
}
PlatformApi.INSTANCE.requestNetworkNodeInitialization(this, level, this::onNetworkInNodeInitialized);
this.mainContainer = PlatformApi.INSTANCE.createInWorldNetworkNodeContainer(
this,
mainNode,
MAIN_CONTAINER_NAME,
getPriority(),
getConnectionLogic(),
this::createKey
);
this.containers.add(mainContainer);
this.mainNode = mainNode;
}

@Override
public boolean isContainerRemoved() {
return isRemoved();
@Nullable
protected ConnectionLogic getConnectionLogic() {
return null;
}

protected void onNetworkInNodeInitialized() {
@Nullable
protected Object createKey() {
return null;
}

@Override
public void setRemoved() {
super.setRemoved();
if (level == null || level.isClientSide) {
return;
}
PlatformApi.INSTANCE.requestNetworkNodeRemoval(this, level);
protected int getPriority() {
return 0;
}

@Override
public T getNode() {
return node;
}

@Override
public void addOutgoingConnections(final ConnectionSink sink) {
for (final Direction direction : Direction.values()) {
sink.tryConnectInSameDimension(worldPosition.relative(direction), direction.getOpposite());
}
}

@Override
public boolean canAcceptIncomingConnection(final Direction incomingDirection, final BlockState connectingState) {
return true;
}

@Override
public BlockState getContainerBlockState() {
return getBlockState();
public void clearRemoved() {
super.clearRemoved();
containers.forEach(container -> PlatformApi.INSTANCE.onNetworkNodeContainerInitialized(
container,
level,
initializationCallback
));
}

@Override
public GlobalPos getContainerPosition() {
return GlobalPos.of(requireNonNull(level).dimension(), worldPosition);
public void setRemoved() {
super.setRemoved();
containers.forEach(container -> PlatformApi.INSTANCE.onNetworkNodeContainerRemoved(container, level));
}

@Override
public String toString() {
return "NetworkNodeContainerBlockEntity{"
+ "node=" + node
+ ", worldPosition=" + worldPosition
+ "}";
public Set<InWorldNetworkNodeContainer> getContainers() {
return containers;
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
package com.refinedmods.refinedstorage2.platform.api.support.network;

import com.refinedmods.refinedstorage2.api.network.node.container.NetworkNodeContainer;
import com.refinedmods.refinedstorage2.platform.api.PlatformApi;
import com.refinedmods.refinedstorage2.platform.api.security.SecurityHelper;

import net.minecraft.core.Direction;
import net.minecraft.core.GlobalPos;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import org.apiguardian.api.API;

@API(status = API.Status.STABLE, since = "2.0.0-milestone.2.1")
public interface PlatformNetworkNodeContainer extends NetworkNodeContainer {
@API(status = API.Status.STABLE, since = "2.0.0-milestone.3.6")
public interface ConnectionLogic {
/**
* Called when a node is about to be added into the network graph.
* Add outgoing connections here.
* Called when a node is about to be added into the network graph.
* If the outgoing connections ever change, call {@link
* com.refinedmods.refinedstorage2.platform.api.PlatformApi#requestNetworkNodeUpdate(
*PlatformNetworkNodeContainer, Level)}.
* com.refinedmods.refinedstorage2.platform.api.PlatformApi#onNetworkNodeContainerUpdated(
*InWorldNetworkNodeContainer, Level)}.
*
* @param sink the sink that accepts outgoing connections
*/
Expand All @@ -28,22 +22,12 @@ public interface PlatformNetworkNodeContainer extends NetworkNodeContainer {
* Returns whether the (not yet discovered) node can accept an incoming connection.
* Changes to this return value won't cause a rebuild of the network state.
* If the return value ever changes, call {@link
* com.refinedmods.refinedstorage2.platform.api.PlatformApi#requestNetworkNodeUpdate(
*PlatformNetworkNodeContainer, Level)}.
* com.refinedmods.refinedstorage2.platform.api.PlatformApi#onNetworkNodeContainerUpdated(
*InWorldNetworkNodeContainer, Level)}.
*
* @param incomingDirection the incoming direction
* @param connectingState the state wanting to connect
* @return whether the node can accept an incoming connection
*/
boolean canAcceptIncomingConnection(Direction incomingDirection, BlockState connectingState);

BlockState getContainerBlockState();

GlobalPos getContainerPosition();

boolean isContainerRemoved();

default boolean canBreakOrRotate(final ServerPlayer player) {
return SecurityHelper.isAllowed(player, PlatformApi.INSTANCE.getBuiltinPermissions().build(), getNode());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.refinedmods.refinedstorage2.platform.api.support.network;

import com.refinedmods.refinedstorage2.api.network.node.container.NetworkNodeContainer;

import net.minecraft.core.BlockPos;
import net.minecraft.core.GlobalPos;
import net.minecraft.world.level.block.state.BlockState;
import org.apiguardian.api.API;

@API(status = API.Status.STABLE, since = "2.0.0-milestone.2.1")
public interface InWorldNetworkNodeContainer extends NetworkNodeContainer, ConnectionLogic {
BlockState getBlockState();

boolean isRemoved();

GlobalPos getPosition();

BlockPos getLocalPosition();

String getName();
}
Loading

0 comments on commit 873e141

Please sign in to comment.