Merge remote-tracking branch 'LasmGratel/async-itemrepo' into AE2-Omnifactory

This commit is contained in:
PrototypeTrousers
2022-09-25 13:52:30 -03:00
5 changed files with 134 additions and 80 deletions
@@ -39,7 +39,7 @@ import appeng.api.storage.IStorageChannel;
* - For fluids: AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class).createList() * - For fluids: AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class).createList()
* - Replace with the corresponding {@link IStorageChannel} type for non native channels * - Replace with the corresponding {@link IStorageChannel} type for non native channels
*/ */
public interface IItemList<T extends IAEStack<T>> extends IItemContainer<T>, Iterable<T> public interface IItemList<T extends IAEStack<T>> extends IItemContainer<T>, Iterable<T>, Cloneable
{ {
/** /**
@@ -85,4 +85,9 @@ public interface IItemList<T extends IAEStack<T>> extends IItemContainer<T>, Ite
* resets stack sizes to 0. * resets stack sizes to 0.
*/ */
void resetStatus(); void resetStatus();
}
/**
* create a copy of this list.
*/
IItemList<T> clone();
}
+107 -78
View File
@@ -39,19 +39,20 @@ import javax.annotation.Nonnull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class ItemRepo { public class ItemRepo {
private final IItemList<IAEItemStack> list = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class).createList(); private final IItemList<IAEItemStack> list = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class).createList();
private final ArrayList<IAEItemStack> view = new ArrayList<>(); private final List<IAEItemStack> view;
private final IScrollSource src; private final IScrollSource src;
private final ISortSource sortSrc; private final ISortSource sortSrc;
private int rowSize = 9; private int rowSize = 9;
private String searchString = ""; private volatile String searchString = "";
private IPartitionList<IAEItemStack> myPartitionList; private IPartitionList<IAEItemStack> myPartitionList;
private String innerSearch = ""; private String innerSearch = "";
private boolean hasPower; private boolean hasPower;
@@ -59,6 +60,9 @@ public class ItemRepo {
public ItemRepo(final IScrollSource src, final ISortSource sortSrc) { public ItemRepo(final IScrollSource src, final ISortSource sortSrc) {
this.src = src; this.src = src;
this.sortSrc = sortSrc; this.sortSrc = sortSrc;
this.view = Collections.synchronizedList(new ArrayList<>());
list.forEach(this.view::add);
} }
public IAEItemStack getReferenceItem(int idx) { public IAEItemStack getReferenceItem(int idx) {
@@ -95,111 +99,123 @@ public class ItemRepo {
this.updateView(); this.updateView();
} }
private CompletableFuture<Void> searchTask = null;
public void updateView() { public void updateView() {
this.view.clear(); if (searchTask != null) {
searchTask.cancel(true);
this.view.ensureCapacity(this.list.size());
final Enum viewMode = this.sortSrc.getSortDisplay();
final Enum searchMode = AEConfig.instance().getConfigManager().getSetting(Settings.SEARCH_MODE);
final boolean needsZeroCopy = viewMode == ViewItems.CRAFTABLE;
if (searchMode == SearchBoxMode.JEI_AUTOSEARCH || searchMode == SearchBoxMode.JEI_MANUAL_SEARCH || searchMode == SearchBoxMode.JEI_AUTOSEARCH_KEEP || searchMode == SearchBoxMode.JEI_MANUAL_SEARCH_KEEP) {
this.updateJEI(this.searchString);
} }
final boolean terminalSearchToolTips = AEConfig.instance().getConfigManager().getSetting(Settings.SEARCH_TOOLTIPS) != YesNo.NO; // Since sortSrc is final, so we can safely call it inside lambda
searchTask = CompletableFuture.supplyAsync(() -> {
IItemList<IAEItemStack> list = this.list.clone();
List<IAEItemStack> view = new ArrayList<>(list.size());
Enum viewMode = this.sortSrc.getSortDisplay();
boolean searchMod = false; boolean needsZeroCopy = viewMode == ViewItems.CRAFTABLE;
this.innerSearch = searchString.toLowerCase(); boolean terminalSearchToolTips = AEConfig.instance().getConfigManager().getSetting(Settings.SEARCH_TOOLTIPS) != YesNo.NO;
if (this.innerSearch.startsWith("@")) {
searchMod = true;
this.innerSearch = this.innerSearch.substring(1);
}
Pattern m = null; boolean searchMod = false;
try {
m = Pattern.compile(this.innerSearch, Pattern.CASE_INSENSITIVE); String innerSearch = searchString.toLowerCase();
} catch (final Throwable ignore) { if (innerSearch.startsWith("@")) {
try { searchMod = true;
m = Pattern.compile(Pattern.quote(this.innerSearch), Pattern.CASE_INSENSITIVE); innerSearch = innerSearch.substring(1);
} catch (final Throwable __) {
return;
} }
}
boolean notDone = false; Pattern m = null;
for (IAEItemStack is : this.list) { try {
if (this.myPartitionList != null) { m = Pattern.compile(innerSearch, Pattern.CASE_INSENSITIVE);
if (!this.myPartitionList.isListed(is)) { } catch (final Throwable ignore) {
continue; try {
m = Pattern.compile(Pattern.quote(innerSearch), Pattern.CASE_INSENSITIVE);
} catch (final Throwable __) {
return Collections.<IAEItemStack>emptyList();
} }
} }
if (viewMode == ViewItems.CRAFTABLE && !is.isCraftable()) {
continue;
}
if (viewMode == ViewItems.STORED && is.getStackSize() == 0) { for (IAEItemStack is : list) {
continue; if (this.myPartitionList != null) {
} if (!this.myPartitionList.isListed(is)) {
continue;
}
}
final String dspName = (searchMod ? Platform.getModId(is) : Platform.getItemDisplayName(is)).toLowerCase(); if (viewMode == ViewItems.CRAFTABLE && !is.isCraftable()) {
boolean foundMatchingItemStack = true; continue;
}
for (String term : innerSearch.split(" ")) { if (viewMode == ViewItems.STORED && is.getStackSize() == 0) {
if (term.length() > 1 && (term.startsWith("-") || term.startsWith("!"))) { continue;
term = term.substring(1); }
if (dspName.contains(term)) {
final String dspName = (searchMod ? Platform.getModId(is) : Platform.getItemDisplayName(is)).toLowerCase();
boolean foundMatchingItemStack = true;
for (String term : innerSearch.split(" ")) {
if (term.length() > 1 && (term.startsWith("-") || term.startsWith("!"))) {
term = term.substring(1);
if (dspName.contains(term)) {
foundMatchingItemStack = false;
break;
}
} else if (!dspName.contains(term)) {
foundMatchingItemStack = false; foundMatchingItemStack = false;
break; break;
} }
} else if (!dspName.contains(term)) {
foundMatchingItemStack = false;
break;
} }
}
if (terminalSearchToolTips && !foundMatchingItemStack) { if (terminalSearchToolTips && !foundMatchingItemStack) {
final List<String> tooltip = Platform.getTooltip(is); final List<String> tooltip = Platform.getTooltip(is);
for (final String line : tooltip) { for (final String line : tooltip) {
if (m.matcher(line).find()) { if (m.matcher(line).find()) {
foundMatchingItemStack = true; foundMatchingItemStack = true;
break; break;
}
} }
} }
}
if (foundMatchingItemStack) { if (foundMatchingItemStack) {
if (needsZeroCopy) { if (needsZeroCopy) {
is = is.copy(); is = is.copy();
is.setStackSize(0); is.setStackSize(0);
}
view.add(is);
} }
this.view.add(is);
} }
}
final Enum SortBy = this.sortSrc.getSortBy(); final Enum SortBy = this.sortSrc.getSortBy();
final Enum SortDir = this.sortSrc.getSortDir(); final Enum SortDir = this.sortSrc.getSortDir();
ItemSorters.setDirection((appeng.api.config.SortDir) SortDir); ItemSorters.setDirection((appeng.api.config.SortDir) SortDir);
ItemSorters.init(); ItemSorters.init();
if (SortBy == SortOrder.MOD) { if (SortBy == SortOrder.MOD) {
Collections.sort(this.view, ItemSorters.CONFIG_BASED_SORT_BY_MOD); view.sort(ItemSorters.CONFIG_BASED_SORT_BY_MOD);
} else if (SortBy == SortOrder.AMOUNT) { } else if (SortBy == SortOrder.AMOUNT) {
Collections.sort(this.view, ItemSorters.CONFIG_BASED_SORT_BY_SIZE); view.sort(ItemSorters.CONFIG_BASED_SORT_BY_SIZE);
} else if (SortBy == SortOrder.INVTWEAKS) { } else if (SortBy == SortOrder.INVTWEAKS) {
if (InventoryBogoSortModule.isLoaded()) { if (InventoryBogoSortModule.isLoaded()) {
Collections.sort(this.view, InventoryBogoSortModule.COMPARATOR); Collections.sort(this.view, InventoryBogoSortModule.COMPARATOR);
} else {
Collections.sort(this.view, ItemSorters.CONFIG_BASED_SORT_BY_INV_TWEAKS);
}
} else { } else {
Collections.sort(this.view, ItemSorters.CONFIG_BASED_SORT_BY_INV_TWEAKS); view.sort(ItemSorters.CONFIG_BASED_SORT_BY_NAME);
} }
} else {
Collections.sort(this.view, ItemSorters.CONFIG_BASED_SORT_BY_NAME); return view;
} }).thenAcceptAsync(view -> {
this.view.clear();
this.view.addAll(view);
}).thenRunAsync(() -> {
this.searchTask = null; // Prevent redundant cancellation
});
} }
private void updateJEI(String filter) { private void updateJEI(String filter) {
@@ -211,6 +227,8 @@ public class ItemRepo {
} }
public void clear() { public void clear() {
searchTask.cancel(true);
searchTask = null;
this.list.resetStatus(); this.list.resetStatus();
} }
@@ -236,5 +254,16 @@ public class ItemRepo {
public void setSearchString(@Nonnull final String searchString) { public void setSearchString(@Nonnull final String searchString) {
this.searchString = searchString; this.searchString = searchString;
if (searchTask != null) {
searchTask.cancel(true);
searchTask = null;
}
// Passive JEI auto search
final Enum<?> searchMode = AEConfig.instance().getConfigManager().getSetting(Settings.SEARCH_MODE);
if (searchMode == SearchBoxMode.JEI_AUTOSEARCH || searchMode == SearchBoxMode.JEI_MANUAL_SEARCH || searchMode == SearchBoxMode.JEI_AUTOSEARCH_KEEP || searchMode == SearchBoxMode.JEI_MANUAL_SEARCH_KEEP) {
this.updateJEI(this.searchString);
}
} }
} }
@@ -161,6 +161,13 @@ public final class FluidList implements IItemList<IAEFluidStack> {
} }
} }
@Override
public FluidList clone() {
FluidList list = new FluidList();
list.records.putAll(records);
return list;
}
private IAEFluidStack getFluidRecord(final IAEFluidStack fluid) { private IAEFluidStack getFluidRecord(final IAEFluidStack fluid) {
return this.records.get(fluid); return this.records.get(fluid);
} }
@@ -94,4 +94,9 @@ public class ItemListIgnoreCrafting<T extends IAEStack<T>> implements IItemList<
public void resetStatus() { public void resetStatus() {
this.target.resetStatus(); this.target.resetStatus();
} }
@Override
public ItemListIgnoreCrafting<T> clone() {
return new ItemListIgnoreCrafting<>(target);
}
} }
@@ -140,6 +140,14 @@ public final class ItemList implements IItemList<IAEItemStack> {
} }
} }
@Override
public ItemList clone() {
ItemList list = new ItemList();
list.records.putAll(records);
list.version.set(version.get());
return list;
}
private ItemVariantList getOrCreateRecord(Item item) { private ItemVariantList getOrCreateRecord(Item item) {
return this.records.computeIfAbsent(item, this::makeRecordMap); return this.records.computeIfAbsent(item, this::makeRecordMap);
} }