Skip to content

Commit

Permalink
refactor: introduce common storage container network node
Browse files Browse the repository at this point in the history
  • Loading branch information
raoulvdberge committed Jun 22, 2024
1 parent ac9755c commit 96841ec
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 108 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package com.refinedmods.refinedstorage2.api.network.impl.node;

import com.refinedmods.refinedstorage2.api.network.impl.storage.AbstractStorageNetworkNode;
import com.refinedmods.refinedstorage2.api.storage.StateTrackedStorage;
import com.refinedmods.refinedstorage2.api.storage.Storage;
import com.refinedmods.refinedstorage2.api.storage.StorageState;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nullable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class AbstractStorageContainerNetworkNode extends AbstractStorageNetworkNode {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractStorageContainerNetworkNode.class);

protected final StateTrackedStorage[] storages;

private final long energyUsage;
private final long energyUsagePerStorage;

@Nullable
private Provider provider;
@Nullable
private StateTrackedStorage.Listener listener;
private int activeStorages;

protected AbstractStorageContainerNetworkNode(final long energyUsage,
final long energyUsagePerStorage,
final int size) {
this.energyUsage = energyUsage;
this.energyUsagePerStorage = energyUsagePerStorage;
this.storages = new StateTrackedStorage[size];
}

public void setListener(final StateTrackedStorage.Listener listener) {
this.listener = listener;
}

public void setProvider(final Provider provider) {
this.provider = provider;
final List<StorageChange> changes = new ArrayList<>();
for (int i = 0; i < storages.length; ++i) {
changes.addAll(initializeStorage(i));
}
// If we are already initialized, update all the storages to keep the exposed storages in sync.
// If we are not initialized, update nothing as we have to wait for an activeness update.
if (activeStorages > 0) {
changes.forEach(this::onStorageChange);
}
updateActiveStorageCount();
}

public void onStorageChanged(final int index) {
if (index < 0 || index >= storages.length) {
LOGGER.warn("Invalid index {}", index);
return;
}
initializeStorage(index).forEach(this::onStorageChange);
updateActiveStorageCount();
}

protected void onStorageChange(final StorageChange change) {
// no op
}

private Set<StorageChange> initializeStorage(final int index) {
final Set<StorageChange> results = new HashSet<>();
if (storages[index] != null) {
results.add(new StorageChange(true, storages[index]));
}
if (provider != null) {
provider.resolve(index).ifPresentOrElse(resolved -> {
final StateTrackedStorage newStorage = new StateTrackedStorage(resolved, listener);
storages[index] = newStorage;
results.add(new StorageChange(false, newStorage));
}, () -> storages[index] = null);
}
return results;
}

private void updateActiveStorageCount() {
this.activeStorages = (int) Arrays.stream(storages).filter(Objects::nonNull).count();
}

@Override
public long getEnergyUsage() {
return energyUsage + (energyUsagePerStorage * activeStorages);
}

public int getSize() {
return storages.length;
}

public StorageState getState(final int index) {
final var storage = storages[index];
if (storage == null) {
return StorageState.NONE;
}
if (!isActive()) {
return StorageState.INACTIVE;
}
return storage.getState();
}

protected record StorageChange(boolean removed, StateTrackedStorage storage) {
}

@FunctionalInterface
public interface Provider {
Optional<Storage> resolve(int index);
}
}
Original file line number Diff line number Diff line change
@@ -1,98 +1,35 @@
package com.refinedmods.refinedstorage2.api.network.impl.node.storage;

import com.refinedmods.refinedstorage2.api.network.impl.storage.AbstractStorageNetworkNode;
import com.refinedmods.refinedstorage2.api.network.impl.node.AbstractStorageContainerNetworkNode;
import com.refinedmods.refinedstorage2.api.network.storage.StorageProvider;
import com.refinedmods.refinedstorage2.api.storage.StateTrackedStorage;
import com.refinedmods.refinedstorage2.api.storage.Storage;
import com.refinedmods.refinedstorage2.api.storage.StorageState;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nullable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class StorageNetworkNode extends AbstractStorageNetworkNode implements StorageProvider {
public class StorageNetworkNode extends AbstractStorageContainerNetworkNode implements StorageProvider {
private static final Logger LOGGER = LoggerFactory.getLogger(StorageNetworkNode.class);

@Nullable
private Provider provider;
@Nullable
private StateTrackedStorage.Listener listener;

private final long energyUsage;
private final long energyUsagePerStorage;

private final StateTrackedStorage[] cache;
private final ExposedStorage storage;
private int activeStorages;

public StorageNetworkNode(final long energyUsage, final long energyUsagePerStorage, final int size) {
this.energyUsage = energyUsage;
this.energyUsagePerStorage = energyUsagePerStorage;
super(energyUsage, energyUsagePerStorage, size);
this.storage = new ExposedStorage(this);
this.cache = new StateTrackedStorage[size];
}

public void setProvider(final Provider provider) {
this.provider = provider;
final List<StorageChange> changes = new ArrayList<>();
for (int i = 0; i < cache.length; ++i) {
changes.addAll(initializeStorage(i));
}
// If we are already initialized, update all the storages to keep the exposed storages in sync.
// If we are not initialized, update nothing as we have to wait for an activeness update.
if (activeStorages > 0) {
changes.forEach(this::processStorageChange);
}
updateActiveStorageCount();
}

public void onStorageChanged(final int index) {
if (index < 0 || index >= cache.length) {
LOGGER.warn("Invalid index {}", index);
return;
}
initializeStorage(index).forEach(this::processStorageChange);
updateActiveStorageCount();
}

private Set<StorageChange> initializeStorage(final int index) {
final Set<StorageChange> results = new HashSet<>();
if (cache[index] != null) {
results.add(new StorageChange(true, cache[index]));
}
if (provider != null) {
provider.resolve(index).ifPresentOrElse(resolved -> {
final StateTrackedStorage newStorage = new StateTrackedStorage(resolved, listener);
cache[index] = newStorage;
results.add(new StorageChange(false, newStorage));
}, () -> cache[index] = null);
}
return results;
}

private void processStorageChange(final StorageChange change) {
@Override
protected void onStorageChange(final AbstractStorageContainerNetworkNode.StorageChange change) {
if (!isActive()) {
return;
}
if (change.removed) {
storage.removeSource(change.storage);
if (change.removed()) {
storage.removeSource(change.storage());
} else {
storage.addSource(change.storage);
storage.addSource(change.storage());
}
}

private void updateActiveStorageCount() {
this.activeStorages = (int) Arrays.stream(cache).filter(Objects::nonNull).count();
}

@Override
protected void onActiveChanged(final boolean newActive) {
super.onActiveChanged(newActive);
Expand All @@ -108,7 +45,7 @@ protected void onActiveChanged(final boolean newActive) {
}

private void enableAllStorages() {
for (final StateTrackedStorage internalStorage : cache) {
for (final StateTrackedStorage internalStorage : storages) {
if (internalStorage != null) {
storage.addSource(internalStorage);
}
Expand All @@ -119,30 +56,6 @@ private void disableAllStorages() {
storage.clearSources();
}

public void setListener(final StateTrackedStorage.Listener listener) {
this.listener = listener;
}

@Override
public long getEnergyUsage() {
return energyUsage + (energyUsagePerStorage * activeStorages);
}

public int getSize() {
return cache.length;
}

public StorageState getState(final int index) {
final var cached = cache[index];
if (cached == null) {
return StorageState.NONE;
}
if (!isActive()) {
return StorageState.INACTIVE;
}
return cached.getState();
}

public long getStored() {
return storage.getStored();
}
Expand All @@ -155,12 +68,4 @@ public long getCapacity() {
public Storage getStorage() {
return storage;
}

private record StorageChange(boolean removed, StateTrackedStorage storage) {
}

@FunctionalInterface
public interface Provider {
Optional<Storage> resolve(int index);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package com.refinedmods.refinedstorage2.api.network.impl.node.storage;

import com.refinedmods.refinedstorage2.api.network.impl.node.AbstractStorageContainerNetworkNode;
import com.refinedmods.refinedstorage2.api.storage.Storage;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

class StorageNetworkNodeProviderImpl implements StorageNetworkNode.Provider {
class StorageNetworkNodeProviderImpl implements AbstractStorageContainerNetworkNode.Provider {
private final Map<Integer, Storage> storages = new HashMap<>();

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.refinedmods.refinedstorage2.platform.common.storage;

import com.refinedmods.refinedstorage2.api.network.impl.node.storage.StorageNetworkNode;
import com.refinedmods.refinedstorage2.api.network.impl.node.AbstractStorageContainerNetworkNode;
import com.refinedmods.refinedstorage2.api.storage.Storage;
import com.refinedmods.refinedstorage2.api.storage.StorageState;
import com.refinedmods.refinedstorage2.platform.api.storage.StorageContainerItem;
Expand All @@ -16,7 +16,7 @@
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.item.ItemStack;

public class DiskInventory extends SimpleContainer implements StorageNetworkNode.Provider {
public class DiskInventory extends SimpleContainer implements AbstractStorageContainerNetworkNode.Provider {
private static final String TAG_DISK_STATE = "s";
private static final String TAG_DISK_ITEM_ID = "i";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.refinedmods.refinedstorage2.platform.common.storage.storageblock;

import com.refinedmods.refinedstorage2.api.network.impl.node.AbstractStorageContainerNetworkNode;
import com.refinedmods.refinedstorage2.api.network.impl.node.storage.StorageNetworkNode;
import com.refinedmods.refinedstorage2.api.storage.Storage;
import com.refinedmods.refinedstorage2.platform.api.PlatformApi;
Expand Down Expand Up @@ -29,7 +30,7 @@

abstract class AbstractStorageBlockBlockEntity
extends AbstractRedstoneModeNetworkNodeContainerBlockEntity<StorageNetworkNode>
implements NetworkNodeMenuProvider, StorageBlockEntity, StorageNetworkNode.Provider {
implements NetworkNodeMenuProvider, StorageBlockEntity, AbstractStorageContainerNetworkNode.Provider {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractStorageBlockBlockEntity.class);

private static final String TAG_STORAGE_ID = "sid";
Expand Down

0 comments on commit 96841ec

Please sign in to comment.