Skip to content

Commit 8ef874b

Browse files
committed
WIP
1 parent 4533416 commit 8ef874b

6 files changed

Lines changed: 94 additions & 70 deletions

File tree

src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabIngredientComponentClient.java

Lines changed: 17 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,7 @@
33
import com.google.common.base.Predicates;
44
import com.google.common.collect.Lists;
55
import com.google.common.collect.Sets;
6-
import it.unimi.dsi.fastutil.ints.Int2LongMap;
7-
import it.unimi.dsi.fastutil.ints.Int2LongOpenHashMap;
8-
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
9-
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
10-
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
11-
import it.unimi.dsi.fastutil.ints.IntSet;
6+
import it.unimi.dsi.fastutil.ints.*;
127
import net.minecraft.ChatFormatting;
138
import net.minecraft.client.Minecraft;
149
import net.minecraft.client.gui.GuiGraphics;
@@ -26,12 +21,7 @@
2621
import org.cyclops.commoncapabilities.api.ingredient.IIngredientMatcher;
2722
import org.cyclops.commoncapabilities.api.ingredient.IngredientComponent;
2823
import org.cyclops.cyclopscore.client.gui.image.Images;
29-
import org.cyclops.cyclopscore.helper.GuiHelpers;
30-
import org.cyclops.cyclopscore.helper.Helpers;
31-
import org.cyclops.cyclopscore.helper.L10NHelpers;
32-
import org.cyclops.cyclopscore.helper.MinecraftHelpers;
33-
import org.cyclops.cyclopscore.helper.RenderHelpers;
34-
import org.cyclops.cyclopscore.helper.StringHelpers;
24+
import org.cyclops.cyclopscore.helper.*;
3525
import org.cyclops.cyclopscore.ingredient.collection.IIngredientCollapsedCollectionMutable;
3626
import org.cyclops.cyclopscore.ingredient.collection.IngredientArrayList;
3727
import org.cyclops.cyclopscore.ingredient.collection.IngredientCollectionHelpers;
@@ -42,11 +32,7 @@
4232
import org.cyclops.integratedterminals.IntegratedTerminals;
4333
import org.cyclops.integratedterminals.api.ingredient.IIngredientComponentTerminalStorageHandler;
4434
import org.cyclops.integratedterminals.api.ingredient.IIngredientInstanceSorter;
45-
import org.cyclops.integratedterminals.api.terminalstorage.ITerminalButton;
46-
import org.cyclops.integratedterminals.api.terminalstorage.ITerminalRowColumnProvider;
47-
import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTabClient;
48-
import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTabCommon;
49-
import org.cyclops.integratedterminals.api.terminalstorage.TerminalClickType;
35+
import org.cyclops.integratedterminals.api.terminalstorage.*;
5036
import org.cyclops.integratedterminals.api.terminalstorage.crafting.ITerminalCraftingOption;
5137
import org.cyclops.integratedterminals.api.terminalstorage.event.TerminalStorageTabClientLoadButtonsEvent;
5238
import org.cyclops.integratedterminals.api.terminalstorage.event.TerminalStorageTabClientSearchFieldUpdateEvent;
@@ -56,6 +42,7 @@
5642
import org.cyclops.integratedterminals.core.terminalstorage.button.TerminalButtonFilterCrafting;
5743
import org.cyclops.integratedterminals.core.terminalstorage.button.TerminalButtonScaleGui;
5844
import org.cyclops.integratedterminals.core.terminalstorage.button.TerminalButtonSort;
45+
import org.cyclops.integratedterminals.core.terminalstorage.crafting.CraftingOptionDelta;
5946
import org.cyclops.integratedterminals.core.terminalstorage.crafting.HandlerWrappedTerminalCraftingOption;
6047
import org.cyclops.integratedterminals.core.terminalstorage.crafting.TerminalStorageTabIngredientCraftingHandlers;
6148
import org.cyclops.integratedterminals.core.terminalstorage.query.IIngredientQuery;
@@ -65,15 +52,7 @@
6552
import org.cyclops.integratedterminals.network.packet.TerminalStorageIngredientSlotClickPacket;
6653

6754
import javax.annotation.Nullable;
68-
import java.util.Arrays;
69-
import java.util.Collection;
70-
import java.util.Comparator;
71-
import java.util.Iterator;
72-
import java.util.List;
73-
import java.util.Locale;
74-
import java.util.Optional;
75-
import java.util.Set;
76-
import java.util.TreeSet;
55+
import java.util.*;
7756
import java.util.function.Predicate;
7857
import java.util.stream.Collectors;
7958
import java.util.stream.Stream;
@@ -439,15 +418,14 @@ protected void updateActiveInstance(Optional<T> lastInstance, int channel) {
439418
}
440419
}
441420

442-
public synchronized void addCraftingOptions(int channel, List<HandlerWrappedTerminalCraftingOption<T>> craftingOptions,
443-
boolean reset, boolean firstChannel) {
421+
public synchronized void onChangeCraftingOptions(int channel, List<CraftingOptionDelta<T>> craftingOptions) {
444422
// Remember the selected instance, as this change event might change its position or quantity.
445423
// This is handled at the end of this method.
446424
Optional<T> lastInstance = getSlotInstance(channel, this.activeSlotId);
447425

448426
// Apply the change to the wildcard channel as well
449427
if (channel != IPositionedAddonsNetwork.WILDCARD_CHANNEL) {
450-
addCraftingOptions(IPositionedAddonsNetwork.WILDCARD_CHANNEL, craftingOptions, reset && firstChannel, firstChannel);
428+
onChangeCraftingOptions(IPositionedAddonsNetwork.WILDCARD_CHANNEL, craftingOptions);
451429
}
452430

453431
boolean wasEnabled = this.enabled;
@@ -456,10 +434,16 @@ public synchronized void addCraftingOptions(int channel, List<HandlerWrappedTerm
456434
this.channels.add(channel);
457435
}
458436
Collection<HandlerWrappedTerminalCraftingOption<T>> existingOptions = this.craftingOptions.get(channel);
459-
if (existingOptions == null || reset) {
460-
this.craftingOptions.put(channel, Lists.newArrayList(craftingOptions));
461-
} else {
462-
existingOptions.addAll(craftingOptions);
437+
if (existingOptions == null) {
438+
existingOptions = Sets.newTreeSet();
439+
this.craftingOptions.put(channel, existingOptions);
440+
}
441+
for (CraftingOptionDelta<T> craftingOption : craftingOptions) {
442+
if (craftingOption.changeType() == IIngredientComponentStorageObservable.Change.ADDITION) {
443+
existingOptions.add(craftingOption.craftingOption());
444+
} else {
445+
existingOptions.remove(craftingOption.craftingOption());
446+
}
463447
}
464448

465449
// Persist changes

src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabIngredientComponentServer.java

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import org.cyclops.integratedterminals.api.terminalstorage.crafting.ITerminalCraftingOption;
4545
import org.cyclops.integratedterminals.api.terminalstorage.crafting.ITerminalStorageTabIngredientCraftingHandler;
4646
import org.cyclops.integratedterminals.capability.ingredient.IngredientComponentTerminalStorageHandlerConfig;
47+
import org.cyclops.integratedterminals.core.terminalstorage.crafting.CraftingOptionDelta;
4748
import org.cyclops.integratedterminals.core.terminalstorage.crafting.HandlerWrappedTerminalCraftingOption;
4849
import org.cyclops.integratedterminals.core.terminalstorage.crafting.TerminalStorageTabIngredientCraftingHandlers;
4950
import org.cyclops.integratedterminals.network.packet.TerminalStorageIngredientChangeEventPacket;
@@ -145,6 +146,8 @@ protected void initChannel(int channel) {
145146
// We assume that crafting options don't change that often,
146147
// so we don't have any observers that listen on recipe index changes.
147148
// Consequence is: players will have to re-open the terminal when they want to see recipe changes.
149+
// TODO: introduce a change listener system for the recipe index? Will become too expensive to do diff every tick...
150+
// TODO: No: only send it once to the client on init, and keep change index as future work if needed.
148151
List<HandlerWrappedTerminalCraftingOption<T>> channeledCraftingOptions = Lists.newArrayList();
149152
for (ITerminalStorageTabIngredientCraftingHandler handler : TerminalStorageTabIngredientCraftingHandlers.REGISTRY.getHandlers()) {
150153
Collection<ITerminalCraftingOption<T>> options = handler.getCraftingOptions(this, channel);
@@ -155,10 +158,11 @@ protected void initChannel(int channel) {
155158
}
156159
}
157160
this.craftingOptions.put(channel, channeledCraftingOptions);
158-
boolean firstChannel = true;
159-
if (channeledCraftingOptions.size() > 0) {
160-
this.sendCraftingOptionsToClient(channel, channeledCraftingOptions, false, firstChannel);
161-
firstChannel = false;
161+
if (!channeledCraftingOptions.isEmpty()) {
162+
List<CraftingOptionDelta<T>> channeledCraftingDeltaOptions = channeledCraftingOptions.stream()
163+
.map(option -> new CraftingOptionDelta<>(option, IIngredientComponentStorageObservable.Change.ADDITION))
164+
.toList();
165+
this.sendCraftingOptionsToClient(channel, channeledCraftingDeltaOptions);
162166
}
163167
}
164168

@@ -263,7 +267,6 @@ public void onChange(IIngredientComponentStorageObservable.StorageChangeEvent<T,
263267
}
264268

265269
protected void reApplyFilter(@Nullable IIngredientComponentStorageObservable.StorageChangeEvent<T, M> event) {
266-
boolean firstChannel = true;
267270
for (int channel : event == null ? this.unfilteredIngredientsViews.keySet() : Collections.singleton(event.getChannel())) {
268271
Predicate<T> ingredientsFilter = getIngredientsFilter();
269272
if (ingredientsFilter != null || event == null) {
@@ -304,6 +307,7 @@ protected void reApplyFilter(@Nullable IIngredientComponentStorageObservable.Sto
304307
}
305308

306309
// Filter crafting options and re-send to client
310+
// TODO: don't do this!!! Use change events as well here!!!
307311
Collection<HandlerWrappedTerminalCraftingOption<T>> channeledCraftingOptions = this.craftingOptions.get(channel);
308312
if (channeledCraftingOptions != null) {
309313
Collection<HandlerWrappedTerminalCraftingOption<T>> channeledCraftingOptionsFiltered;
@@ -323,10 +327,8 @@ protected void reApplyFilter(@Nullable IIngredientComponentStorageObservable.Sto
323327
} else {
324328
channeledCraftingOptionsFiltered = channeledCraftingOptions;
325329
}
326-
this.sendCraftingOptionsToClient(channel, channeledCraftingOptionsFiltered, true, firstChannel);
330+
this.sendCraftingOptionsToClient(channel, channeledCraftingOptionsFiltered);
327331
}
328-
329-
firstChannel = false;
330332
}
331333

332334
initialized = true;
@@ -375,37 +377,35 @@ protected void sendToClient(IIngredientComponentStorageObservable.StorageChangeE
375377
}
376378
}
377379

378-
private void sendCraftingOptionsToClient(int channel, Collection<HandlerWrappedTerminalCraftingOption<T>> channeledCraftingOptions,
379-
boolean reset, boolean firstChannel) {
380+
private void sendCraftingOptionsToClient(int channel, Collection<CraftingOptionDelta<T>> channeledCraftingOptions) {
380381
// Only allow collection of a max given size to be sent in a packet
381382
if (channeledCraftingOptions.size() <= GeneralConfig.terminalStoragePacketMaxRecipes) {
382383
IntegratedTerminals._instance.getPacketHandler().sendToPlayer(
383-
new TerminalStorageIngredientCraftingOptionsPacket(this.getName().toString(), channel, channeledCraftingOptions, reset, firstChannel), player);
384+
new TerminalStorageIngredientCraftingOptionsPacket(this.getName().toString(), channel, channeledCraftingOptions), player);
384385
} else {
385-
List<Pair<Boolean, List<HandlerWrappedTerminalCraftingOption<T>>>> chunks = Lists.newArrayList();
386-
List<HandlerWrappedTerminalCraftingOption<T>> buffer = Lists.newArrayListWithExpectedSize(GeneralConfig.terminalStoragePacketMaxRecipes);
386+
List<List<CraftingOptionDelta<T>>> chunks = Lists.newArrayList();
387+
List<CraftingOptionDelta<T>> buffer = Lists.newArrayListWithExpectedSize(GeneralConfig.terminalStoragePacketMaxRecipes);
387388

388-
for (HandlerWrappedTerminalCraftingOption<T> instance : channeledCraftingOptions) {
389+
for (CraftingOptionDelta<T> instance : channeledCraftingOptions) {
389390
buffer.add(instance);
390391

391392
// If our buffer reaches its capacity,
392393
// flush it, and create a new buffer
393394
if (buffer.size() == GeneralConfig.terminalStoragePacketMaxRecipes) {
394-
chunks.add(Pair.of(reset, buffer));
395-
reset = false; // Only reset in first packet
395+
chunks.add(buffer);
396396
buffer = Lists.newArrayListWithExpectedSize(GeneralConfig.terminalStoragePacketMaxRecipes);
397397
}
398398
}
399399
// Our buffer can contain some remaining instances, make sure to flush them as well.
400400
if (!buffer.isEmpty()) {
401-
chunks.add(Pair.of(reset, buffer));
401+
chunks.add(buffer);
402402
}
403403

404-
for (Pair<Boolean, List<HandlerWrappedTerminalCraftingOption<T>>> chunk : chunks) {
404+
for (List<CraftingOptionDelta<T>> chunk : chunks) {
405405
if (GeneralConfig.packetSerializationEnableMultithreading) {
406-
PACKET_SERIALIZER.execute(() -> sendCraftingOptionsToClient(channel, chunk.getRight(), chunk.getLeft(), firstChannel));
406+
PACKET_SERIALIZER.execute(() -> sendCraftingOptionsToClient(channel, chunk));
407407
} else {
408-
sendCraftingOptionsToClient(channel, chunk.getRight(), chunk.getLeft(), firstChannel);
408+
sendCraftingOptionsToClient(channel, chunk);
409409
}
410410
}
411411
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.cyclops.integratedterminals.core.terminalstorage.crafting;
2+
3+
import org.cyclops.integrateddynamics.api.ingredient.IIngredientComponentStorageObservable;
4+
5+
/**
6+
* @author rubensworks
7+
*/
8+
public record CraftingOptionDelta<T>(HandlerWrappedTerminalCraftingOption<T> craftingOption,
9+
IIngredientComponentStorageObservable.Change changeType) {
10+
}

src/main/java/org/cyclops/integratedterminals/core/terminalstorage/crafting/HandlerWrappedTerminalCraftingOption.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@
66
import org.cyclops.commoncapabilities.api.ingredient.IngredientComponent;
77
import org.cyclops.integratedterminals.api.terminalstorage.crafting.ITerminalCraftingOption;
88
import org.cyclops.integratedterminals.api.terminalstorage.crafting.ITerminalStorageTabIngredientCraftingHandler;
9+
import org.jetbrains.annotations.NotNull;
10+
11+
import java.util.Objects;
912

1013
/**
1114
* Data holder for {@link ITerminalCraftingOption} wrapped with its handler.
1215
* @param <T> The instance type.
1316
* @author rubensworks
1417
*/
15-
public class HandlerWrappedTerminalCraftingOption<T> {
18+
public class HandlerWrappedTerminalCraftingOption<T> implements Comparable<HandlerWrappedTerminalCraftingOption<T>> {
1619

1720
private final ITerminalStorageTabIngredientCraftingHandler handler;
1821
private final ITerminalCraftingOption<T> craftingOption;
@@ -49,4 +52,19 @@ public static <T, M> HandlerWrappedTerminalCraftingOption<T> deserialize(Ingredi
4952
return new HandlerWrappedTerminalCraftingOption<>(handler, craftingOption);
5053
}
5154

55+
@Override
56+
public boolean equals(Object o) {
57+
if (!(o instanceof HandlerWrappedTerminalCraftingOption<?> that)) return false;
58+
return Objects.equals(craftingOption, that.craftingOption);
59+
}
60+
61+
@Override
62+
public int hashCode() {
63+
return 941 | craftingOption.hashCode();
64+
}
65+
66+
@Override
67+
public int compareTo(@NotNull HandlerWrappedTerminalCraftingOption<T> o) {
68+
return craftingOption.compareTo(o.getCraftingOption());
69+
}
5270
}

src/main/java/org/cyclops/integratedterminals/modcompat/integratedcrafting/TerminalCraftingOptionRecipeDefinition.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,17 @@ public int compareTo(ITerminalCraftingOption<T> o) {
7070
}
7171
return this.getRecipe().compareTo(((TerminalCraftingOptionRecipeDefinition) o).getRecipe());
7272
}
73+
74+
@Override
75+
public boolean equals(Object obj) {
76+
if (!(obj instanceof TerminalCraftingOptionRecipeDefinition other)) {
77+
return false;
78+
}
79+
return this.getRecipe().equals(other.getRecipe());
80+
}
81+
82+
@Override
83+
public int hashCode() {
84+
return 937 | this.getRecipe().hashCode();
85+
}
7386
}

src/main/java/org/cyclops/integratedterminals/network/packet/TerminalStorageIngredientCraftingOptionsPacket.java

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
import org.cyclops.commoncapabilities.api.ingredient.IngredientComponent;
1414
import org.cyclops.cyclopscore.network.CodecField;
1515
import org.cyclops.cyclopscore.network.PacketCodec;
16+
import org.cyclops.integrateddynamics.api.ingredient.IIngredientComponentStorageObservable;
1617
import org.cyclops.integratedterminals.core.terminalstorage.TerminalStorageTabIngredientComponentClient;
1718
import org.cyclops.integratedterminals.core.terminalstorage.TerminalStorageTabIngredientComponentItemStackCrafting;
19+
import org.cyclops.integratedterminals.core.terminalstorage.crafting.CraftingOptionDelta;
1820
import org.cyclops.integratedterminals.core.terminalstorage.crafting.HandlerWrappedTerminalCraftingOption;
1921
import org.cyclops.integratedterminals.inventory.container.ContainerTerminalStorageBase;
2022

@@ -34,30 +36,25 @@ public class TerminalStorageIngredientCraftingOptionsPacket extends PacketCodec
3436
private int channel;
3537
@CodecField
3638
private CompoundTag data;
37-
@CodecField
38-
private boolean reset;
39-
@CodecField
40-
private boolean firstChannel;
4139

4240
public TerminalStorageIngredientCraftingOptionsPacket() {
4341

4442
}
4543

4644
public <T> TerminalStorageIngredientCraftingOptionsPacket(String tabId,
4745
int channel,
48-
Collection<HandlerWrappedTerminalCraftingOption<T>> craftingOptions,
49-
boolean reset,
50-
boolean firstChannel) {
46+
Collection<CraftingOptionDelta<T>> craftingOptions) {
5147
this.tabId = tabId;
5248
this.channel = channel;
5349
this.data = new CompoundTag();
5450
ListTag list = new ListTag();
55-
for (HandlerWrappedTerminalCraftingOption<?> option : craftingOptions) {
56-
list.add(HandlerWrappedTerminalCraftingOption.serialize(option));
51+
for (CraftingOptionDelta<?> option : craftingOptions) {
52+
CompoundTag optionTag = new CompoundTag();
53+
optionTag.putBoolean("addition", option.changeType() == IIngredientComponentStorageObservable.Change.ADDITION);
54+
optionTag.put("option", HandlerWrappedTerminalCraftingOption.serialize(option.craftingOption()));
55+
list.add(optionTag);
5756
}
5857
this.data.put("craftingOptions", list);
59-
this.reset = reset;
60-
this.firstChannel = firstChannel;
6158
}
6259

6360
@Override
@@ -76,21 +73,23 @@ public void actionClient(Level world, Player player) {
7673
IngredientComponent<?, ?> ingredientComponent = tab.getIngredientComponent();
7774

7875
ListTag list = this.data.getList("craftingOptions", Tag.TAG_COMPOUND);
79-
List<HandlerWrappedTerminalCraftingOption<?>> craftingOptions = Lists.newArrayListWithExpectedSize(list.size());
76+
List<CraftingOptionDelta<?>> craftingOptions = Lists.newArrayListWithExpectedSize(list.size());
8077
for (int i = 0; i < list.size(); i++) {
78+
CompoundTag optionTag = list.getCompound(i);
79+
IIngredientComponentStorageObservable.Change changeType = optionTag.getBoolean("addition") ? IIngredientComponentStorageObservable.Change.ADDITION : IIngredientComponentStorageObservable.Change.DELETION;
8180
HandlerWrappedTerminalCraftingOption<?> option = HandlerWrappedTerminalCraftingOption
82-
.deserialize(ingredientComponent, list.getCompound(i));
83-
craftingOptions.add(option);
81+
.deserialize(ingredientComponent, optionTag.getCompound("option"));
82+
craftingOptions.add(new CraftingOptionDelta(option, changeType));
8483
}
8584

86-
tab.addCraftingOptions(channel, (List) craftingOptions, this.reset, this.firstChannel);
85+
tab.onChangeCraftingOptions(channel, (List) craftingOptions);
8786

8887
// Hard-coded crafting tab
8988
// TODO: abstract this as "auxiliary" tabs
9089
if (tabId.equals(IngredientComponents.ITEMSTACK.getName().toString())) {
9190
TerminalStorageTabIngredientComponentClient<?, ?> tabCrafting = (TerminalStorageTabIngredientComponentClient<?, ?>) container
9291
.getTabClient(TerminalStorageTabIngredientComponentItemStackCrafting.NAME.toString());
93-
tabCrafting.addCraftingOptions(channel, (List) craftingOptions, this.reset, this.firstChannel);
92+
tabCrafting.onChangeCraftingOptions(channel, (List) craftingOptions);
9493
}
9594

9695
container.refreshChannelStrings();

0 commit comments

Comments
 (0)