Skip to content

Commit

Permalink
Merge pull request #468 from refinedmods/feat/GH-93/portable-grid-int…
Browse files Browse the repository at this point in the history
…eractions

feat: portable grid interactions
  • Loading branch information
raoulvdberge authored Jan 2, 2024
2 parents fc6d121 + 3867bfd commit 4ff04c8
Show file tree
Hide file tree
Showing 30 changed files with 561 additions and 180 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.refinedmods.refinedstorage2.api.grid.operations;

import com.refinedmods.refinedstorage2.api.storage.ExtractableStorage;
import com.refinedmods.refinedstorage2.api.storage.InsertableStorage;

public class NoopGridOperations<T> implements GridOperations<T> {
@Override
public boolean extract(final T resource,
final GridExtractMode extractMode,
final InsertableStorage<T> destination) {
return false;
}

@Override
public boolean insert(final T resource,
final GridInsertMode insertMode,
final ExtractableStorage<T> source) {
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.refinedmods.refinedstorage2.api.grid.watcher;

import com.refinedmods.refinedstorage2.api.storage.channel.StorageChannel;
import com.refinedmods.refinedstorage2.api.storage.channel.StorageChannelType;

import java.util.Set;

import org.apiguardian.api.API;

/**
* Provides the {@link GridWatcherManagerImpl} with {@link StorageChannel}s.
*/
@API(status = API.Status.STABLE, since = "2.0.0-milestone.3.3")
public interface GridStorageChannelProvider {
Set<StorageChannelType<?>> getStorageChannelTypes();

<T> StorageChannel<T> getStorageChannel(StorageChannelType<T> type);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.refinedmods.refinedstorage2.api.grid;
package com.refinedmods.refinedstorage2.api.grid.watcher;

import com.refinedmods.refinedstorage2.api.storage.channel.StorageChannelType;
import com.refinedmods.refinedstorage2.api.storage.tracked.TrackedResource;
Expand Down Expand Up @@ -38,5 +38,5 @@ <T> void onChanged(
/**
* Usually called when the grid network has been changed.
*/
void clear();
void invalidate();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.refinedmods.refinedstorage2.api.grid.watcher;

import com.refinedmods.refinedstorage2.api.storage.Actor;

import org.apiguardian.api.API;

/**
* This manager helps with attaching and detaching listeners to
* {@link com.refinedmods.refinedstorage2.api.storage.channel.StorageChannel}s.
*/
@API(status = API.Status.STABLE, since = "2.0.0-milestone.3.3")
public interface GridWatcherManager {
void addWatcher(
GridWatcher watcher,
Class<? extends Actor> actorType,
GridStorageChannelProvider storageChannelProvider
);

void attachAll(GridStorageChannelProvider storageChannelProvider);

void removeWatcher(GridWatcher watcher, GridStorageChannelProvider storageChannelProvider);

void detachAll(GridStorageChannelProvider storageChannelProvider);

void activeChanged(boolean active);
}
Original file line number Diff line number Diff line change
@@ -1,105 +1,109 @@
package com.refinedmods.refinedstorage2.api.network.impl.node.grid;
package com.refinedmods.refinedstorage2.api.grid.watcher;

import com.refinedmods.refinedstorage2.api.grid.GridWatcher;
import com.refinedmods.refinedstorage2.api.network.Network;
import com.refinedmods.refinedstorage2.api.network.component.StorageNetworkComponent;
import com.refinedmods.refinedstorage2.api.storage.Actor;
import com.refinedmods.refinedstorage2.api.storage.channel.StorageChannel;
import com.refinedmods.refinedstorage2.api.storage.channel.StorageChannelType;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.apiguardian.api.API;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class GridWatchers {
public static final Logger LOGGER = LoggerFactory.getLogger(GridWatchers.class);
@API(status = API.Status.STABLE, since = "2.0.0-milestone.3.3")
public class GridWatcherManagerImpl implements GridWatcherManager {
private static final Logger LOGGER = LoggerFactory.getLogger(GridWatcherManagerImpl.class);

private final Collection<? extends StorageChannelType<?>> storageChannelTypes;
private final Map<GridWatcher, GridWatcherRegistration> watchers = new HashMap<>();

public GridWatchers(final Collection<? extends StorageChannelType<?>> storageChannelTypes) {
this.storageChannelTypes = storageChannelTypes;
}

private <T> StorageChannel<T> getStorageChannel(final Network network, final StorageChannelType<T> type) {
return network.getComponent(StorageNetworkComponent.class).getStorageChannel(type);
}

@Override
public void addWatcher(
final GridWatcher watcher,
final Class<? extends Actor> actorType,
final Network network
final GridStorageChannelProvider storageChannelProvider
) {
if (watchers.containsKey(watcher)) {
throw new IllegalArgumentException("Watcher is already registered");
}
final GridWatcherRegistration registration = new GridWatcherRegistration(watcher, actorType);
attachAll(registration, network, false);
attachAll(registration, storageChannelProvider, false);
watchers.put(watcher, registration);
LOGGER.info("Added watcher {}, new count is {}", watcher, watchers.size());
}

public void attachAll(final Network network) {
@Override
public void attachAll(final GridStorageChannelProvider storageChannelProvider) {
// If we get here we are affected by a network split or network merge.
// At this point, all the storages that are affected by the split or merge have not yet been processed
// as the grid has the highest priority.
watchers.forEach((watcher, registration) -> {
// Invalidate all watcher data, the resources that were synced earlier are no longer valid because we have
// a brand-new network.
watcher.clear();
watcher.invalidate();
// Re-attach the watcher to the new network, and send all the resources from the new network.
// Resources from the old network are not part of the new network yet, as mentioned above,
// but those will be synced when the storages are re-added.
attachAll(registration, network, true);
attachAll(registration, storageChannelProvider, true);
});
}

private void attachAll(final GridWatcherRegistration registration, final Network network, final boolean replay) {
storageChannelTypes.forEach(storageChannelType -> attach(registration, storageChannelType, network, replay));
private void attachAll(final GridWatcherRegistration registration,
final GridStorageChannelProvider storageChannelProvider,
final boolean replay) {
storageChannelProvider.getStorageChannelTypes().forEach(storageChannelType -> attach(
registration,
storageChannelType,
storageChannelProvider,
replay
));
}

private <T> void attach(
final GridWatcherRegistration registration,
final StorageChannelType<T> storageChannelType,
final Network network,
final GridStorageChannelProvider storageChannelProvider,
final boolean replay
) {
LOGGER.info("Attaching {} to {}", registration, storageChannelType);
final StorageChannel<T> storageChannel = getStorageChannel(network, storageChannelType);
registration.attach(storageChannel, storageChannelType, replay);
registration.attach(storageChannelProvider.getStorageChannel(storageChannelType), storageChannelType, replay);
}

public void removeWatcher(final GridWatcher watcher, final Network network) {
@Override
public void removeWatcher(final GridWatcher watcher, final GridStorageChannelProvider storageChannelProvider) {
final GridWatcherRegistration registration = watchers.get(watcher);
if (registration == null) {
throw new IllegalArgumentException("Watcher is not registered");
}
detachAll(registration, network);
detachAll(registration, storageChannelProvider);
watchers.remove(watcher);
LOGGER.info("Removed watcher {}, remaining {}", watcher, watchers.size());
}

public void detachAll(final Network network) {
@Override
public void detachAll(final GridStorageChannelProvider storageChannelProvider) {
LOGGER.info("Detaching {} watchers", watchers.size());
watchers.values().forEach(w -> detachAll(w, network));
watchers.values().forEach(w -> detachAll(w, storageChannelProvider));
}

private void detachAll(final GridWatcherRegistration registration, final Network network) {
storageChannelTypes.forEach(storageChannelType -> detach(registration, storageChannelType, network));
private void detachAll(final GridWatcherRegistration registration,
final GridStorageChannelProvider storageChannelProvider) {
storageChannelProvider.getStorageChannelTypes().forEach(storageChannelType -> detach(
registration,
storageChannelType,
storageChannelProvider
));
}

private <T> void detach(
final GridWatcherRegistration registration,
final StorageChannelType<T> storageChannelType,
final Network network
final GridStorageChannelProvider storageChannelProvider
) {
LOGGER.info("Detaching {} from {}", registration, storageChannelType);
registration.detach(getStorageChannel(network, storageChannelType), storageChannelType);
registration.detach(storageChannelProvider.getStorageChannel(storageChannelType), storageChannelType);
}

@Override
public void activeChanged(final boolean active) {
watchers.keySet().forEach(watcher -> watcher.onActiveChanged(active));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.refinedmods.refinedstorage2.api.network.impl.node.grid;
package com.refinedmods.refinedstorage2.api.grid.watcher;

import com.refinedmods.refinedstorage2.api.grid.GridWatcher;
import com.refinedmods.refinedstorage2.api.resource.list.listenable.ResourceListListener;
import com.refinedmods.refinedstorage2.api.storage.Actor;
import com.refinedmods.refinedstorage2.api.storage.channel.StorageChannel;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@ParametersAreNonnullByDefault
@FieldsAndMethodsAreNonnullByDefault
package com.refinedmods.refinedstorage2.api.grid;
package com.refinedmods.refinedstorage2.api.grid.watcher;

import com.refinedmods.refinedstorage2.api.core.FieldsAndMethodsAreNonnullByDefault;

Expand Down
Loading

0 comments on commit 4ff04c8

Please sign in to comment.