Skip to content

Commit 34bf8a4

Browse files
committed
Improve internal component storage api
1 parent db678a2 commit 34bf8a4

File tree

11 files changed

+180
-100
lines changed

11 files changed

+180
-100
lines changed

src/client/java/aztech/modern_industrialization/compat/viewer/impl/MachineScreenPredicateTest.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,24 @@
2424
package aztech.modern_industrialization.compat.viewer.impl;
2525

2626
import aztech.modern_industrialization.compat.rei.machines.ReiMachineRecipes;
27-
import aztech.modern_industrialization.machines.gui.GuiComponentClient;
2827
import aztech.modern_industrialization.machines.gui.MachineScreen;
2928
import aztech.modern_industrialization.machines.guicomponents.CraftingMultiblockGuiClient;
29+
import java.util.Optional;
3030

3131
public class MachineScreenPredicateTest {
3232
public static boolean test(ReiMachineRecipes.MachineScreenPredicate predicate, MachineScreen screen) {
3333
return switch (predicate) {
3434
case ANY -> true;
35-
case MULTIBLOCK -> {
36-
for (GuiComponentClient client : screen.getMenu().components) {
37-
if (client instanceof CraftingMultiblockGuiClient cmGui) {
38-
if (cmGui.isShapeValid) {
39-
yield true;
35+
case MULTIBLOCK -> screen.getMenu().components.findOrDefault(
36+
client -> {
37+
if (client instanceof CraftingMultiblockGuiClient cmGui) {
38+
if (cmGui.isShapeValid) {
39+
return Optional.of(true);
40+
}
4041
}
41-
}
42-
}
43-
yield false;
44-
}
42+
return Optional.empty();
43+
},
44+
false);
4545
};
4646
}
4747
}

src/client/java/aztech/modern_industrialization/machines/gui/MachineMenuClient.java

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import aztech.modern_industrialization.inventory.ConfigurableItemStack;
2828
import aztech.modern_industrialization.inventory.MIInventory;
2929
import aztech.modern_industrialization.inventory.SlotPositions;
30+
import aztech.modern_industrialization.machines.ComponentStorage;
3031
import aztech.modern_industrialization.machines.GuiComponentsClient;
3132
import aztech.modern_industrialization.util.NbtHelper;
3233
import java.util.ArrayList;
@@ -52,34 +53,29 @@ public static MachineMenuClient create(int syncId, Inventory playerInventory, Re
5253
SlotPositions fluidPositions = SlotPositions.read(buf);
5354
MIInventory inventory = new MIInventory(itemStacks, fluidStacks, itemPositions, fluidPositions);
5455
// Components
55-
List<GuiComponentClient> components = new ArrayList<>();
56+
ComponentStorage<GuiComponentClient> components = new ComponentStorage<>();
5657
int componentCount = buf.readInt();
5758
for (int i = 0; i < componentCount; ++i) {
5859
ResourceLocation id = buf.readResourceLocation();
59-
components.add(GuiComponentsClient.get(id).createFromInitialData(buf));
60+
components.register(GuiComponentsClient.get(id).createFromInitialData(buf));
6061
}
6162
// GUI params
6263
MachineGuiParameters guiParams = MachineGuiParameters.read(buf);
6364

6465
return new MachineMenuClient(syncId, playerInventory, inventory, components, guiParams);
6566
}
6667

67-
public final List<GuiComponentClient> components;
68+
public final ComponentStorage<GuiComponentClient> components;
6869

69-
private MachineMenuClient(int syncId, Inventory playerInventory, MIInventory inventory, List<GuiComponentClient> components,
70+
private MachineMenuClient(int syncId, Inventory playerInventory, MIInventory inventory, ComponentStorage<GuiComponentClient> components,
7071
MachineGuiParameters guiParams) {
7172
super(syncId, playerInventory, inventory, guiParams, components);
7273
this.components = components;
7374
}
7475

7576
@Nullable
7677
public <T extends GuiComponentClient> T getComponent(Class<T> klass) {
77-
for (GuiComponentClient component : components) {
78-
if (klass.isInstance(component)) {
79-
return (T) component;
80-
}
81-
}
82-
return null;
78+
return components.get(klass).orElse(null);
8379
}
8480

8581
@Override

src/client/java/aztech/modern_industrialization/machines/gui/MachineScreen.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,7 @@ public class MachineScreen extends MIHandledScreen<MachineMenuClient> implements
6464
public MachineScreen(MachineMenuClient handler, Inventory inventory, Component title) {
6565
super(handler, inventory, title);
6666

67-
for (GuiComponentClient component : handler.components) {
68-
renderers.add(component.createRenderer(this));
69-
}
67+
handler.components.forEach(component -> renderers.add(component.createRenderer(this)));
7068

7169
this.imageHeight = handler.guiParams.backgroundHeight;
7270
this.imageWidth = handler.guiParams.backgroundWidth;
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
* MIT License
3+
*
4+
* Copyright (c) 2020 Azercoco & Technici4n
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
package aztech.modern_industrialization.machines;
25+
26+
import aztech.modern_industrialization.machines.gui.GuiComponent;
27+
import java.util.ArrayList;
28+
import java.util.Collections;
29+
import java.util.List;
30+
import java.util.Optional;
31+
import java.util.function.BiConsumer;
32+
import java.util.function.Consumer;
33+
import java.util.function.Function;
34+
import net.minecraft.resources.ResourceLocation;
35+
36+
public sealed class ComponentStorage<C> permits ComponentStorage.GuiServer, ComponentStorage.Server {
37+
protected final List<C> components = new ArrayList<>();
38+
39+
@SafeVarargs
40+
public final void register(C... components) {
41+
Collections.addAll(this.components, components);
42+
}
43+
44+
@SafeVarargs
45+
public final void unregister(C... components) {
46+
for (C component : components) {
47+
this.components.remove(component);
48+
}
49+
}
50+
51+
public final int size() {
52+
return components.size();
53+
}
54+
55+
public final C get(int index) {
56+
return components.get(index);
57+
}
58+
59+
public final void forEach(Consumer<C> action) {
60+
components.forEach(action);
61+
}
62+
63+
public final void forEachIndexed(BiConsumer<Integer, C> action) {
64+
for (int i = 0; i < components.size(); i++) {
65+
action.accept(i, components.get(i));
66+
}
67+
}
68+
69+
public final <T> Optional<T> get(Class<T> clazz) {
70+
for (C component : components) {
71+
if (clazz.isInstance(component)) {
72+
return Optional.of((T) component);
73+
}
74+
}
75+
return Optional.empty();
76+
}
77+
78+
public final <T> List<T> tryGet(Class<T> clazz) {
79+
List<T> components = new ArrayList<>();
80+
for (C component : this.components) {
81+
if (clazz.isInstance(component)) {
82+
components.add((T) component);
83+
}
84+
}
85+
return components;
86+
}
87+
88+
public final <T> void forType(Class<T> clazz, Consumer<? super T> action) {
89+
List<T> component = tryGet(clazz);
90+
for (T c : component) {
91+
action.accept(c);
92+
}
93+
}
94+
95+
public final <T, R> R mapOrDefault(Class<T> clazz, Function<? super T, ? extends R> action, R defaultValue) {
96+
List<T> components = tryGet(clazz);
97+
if (components.isEmpty()) {
98+
return defaultValue;
99+
} else if (components.size() == 1) {
100+
return action.apply(components.get(0));
101+
} else {
102+
throw new RuntimeException("Multiple components of type " + clazz.getName() + " found");
103+
}
104+
}
105+
106+
public final <R> R findOrDefault(Function<C, Optional<? extends R>> action, R defaultValue) {
107+
for (C component : components) {
108+
Optional<? extends R> result = action.apply(component);
109+
if (result.isPresent()) {
110+
return result.get();
111+
}
112+
}
113+
return defaultValue;
114+
}
115+
116+
public final <T, R> R findOrDefault(Class<T> clazz, Function<? super T, Optional<? extends R>> action, R defaultValue) {
117+
return findOrDefault(component -> clazz.isInstance(component) ? action.apply((T) component) : Optional.empty(), defaultValue);
118+
}
119+
120+
public static final class GuiServer extends ComponentStorage<GuiComponent.Server> {
121+
/**
122+
* @throws RuntimeException if the component doesn't exist.
123+
*/
124+
public <S extends GuiComponent.Server> S get(ResourceLocation componentId) {
125+
for (GuiComponent.Server component : components) {
126+
if (component.getId().equals(componentId)) {
127+
return (S) component;
128+
}
129+
}
130+
throw new RuntimeException("Couldn't find component " + componentId);
131+
}
132+
}
133+
134+
public static final class Server extends ComponentStorage<IComponent> {
135+
}
136+
}

src/main/java/aztech/modern_industrialization/machines/MachineBlockEntity.java

Lines changed: 15 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,7 @@
3737
import aztech.modern_industrialization.util.NbtHelper;
3838
import aztech.modern_industrialization.util.WorldHelper;
3939
import java.util.ArrayList;
40-
import java.util.Collections;
4140
import java.util.List;
42-
import java.util.function.Consumer;
43-
import java.util.function.Function;
4441
import net.minecraft.Util;
4542
import net.minecraft.core.Direction;
4643
import net.minecraft.core.HolderLookup;
@@ -50,7 +47,6 @@
5047
import net.minecraft.network.protocol.Packet;
5148
import net.minecraft.network.protocol.game.ClientGamePacketListener;
5249
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
53-
import net.minecraft.resources.ResourceLocation;
5450
import net.minecraft.server.level.ServerPlayer;
5551
import net.minecraft.world.InteractionHand;
5652
import net.minecraft.world.ItemInteractionResult;
@@ -75,8 +71,8 @@
7571
@SuppressWarnings("rawtypes")
7672
public abstract class MachineBlockEntity extends FastBlockEntity
7773
implements MenuProvider, WrenchableBlockEntity {
78-
public final List<GuiComponent.Server> guiComponents = new ArrayList<>();
79-
private final List<IComponent> icomponents = new ArrayList<>();
74+
protected final ComponentStorage.GuiServer guiComponents = new ComponentStorage.GuiServer();
75+
protected final ComponentStorage.Server icomponents = new ComponentStorage.Server();
8076
public final MachineGuiParameters guiParams;
8177
/**
8278
* Server-side only: true if the next call to sync() will trigger a remesh.
@@ -101,57 +97,24 @@ public MachineBlockEntity(BEP bep, MachineGuiParameters guiParams, OrientationCo
10197
}
10298

10399
protected final void registerGuiComponent(GuiComponent.Server... components) {
104-
Collections.addAll(guiComponents, components);
100+
guiComponents.register(components);
105101
}
106102

107103
protected final void registerComponents(IComponent... components) {
108-
Collections.addAll(icomponents, components);
104+
icomponents.register(components);
109105
}
110106

111107
/**
112108
* @return The inventory that will be synced with the client.
113109
*/
114110
public abstract MIInventory getInventory();
115111

116-
/**
117-
* @throws RuntimeException if the component doesn't exist.
118-
*/
119-
@SuppressWarnings("unchecked")
120-
public <S extends GuiComponent.Server> S getComponent(ResourceLocation componentId) {
121-
for (GuiComponent.Server component : guiComponents) {
122-
if (component.getId().equals(componentId)) {
123-
return (S) component;
124-
}
125-
}
126-
throw new RuntimeException("Couldn't find component " + componentId);
127-
}
128-
129-
private <T> List<T> tryGetComponent(Class<T> clazz) {
130-
List<T> components = new ArrayList<>();
131-
for (var component : icomponents) {
132-
if (clazz.isInstance(component)) {
133-
components.add((T) component);
134-
}
135-
}
136-
return components;
112+
public final ComponentStorage.GuiServer getGuiComponents() {
113+
return guiComponents;
137114
}
138115

139-
public final <T> void forComponentType(Class<T> clazz, Consumer<? super T> action) {
140-
List<T> component = tryGetComponent(clazz);
141-
for (T c : component) {
142-
action.accept(c);
143-
}
144-
}
145-
146-
public <T, R> R mapComponentOrDefault(Class<T> clazz, Function<? super T, ? extends R> action, R defaultValue) {
147-
List<T> components = tryGetComponent(clazz);
148-
if (components.isEmpty()) {
149-
return defaultValue;
150-
} else if (components.size() == 1) {
151-
return action.apply(components.get(0));
152-
} else {
153-
throw new RuntimeException("Multiple components of type " + clazz.getName() + " found");
154-
}
116+
public final ComponentStorage.Server getComponents() {
117+
return icomponents;
155118
}
156119

157120
@Override
@@ -176,10 +139,10 @@ public final void writeScreenOpeningData(RegistryFriendlyByteBuf buf) {
176139
inv.fluidPositions.write(buf);
177140
buf.writeInt(guiComponents.size());
178141
// Write components
179-
for (GuiComponent.Server component : guiComponents) {
142+
guiComponents.forEach(component -> {
180143
buf.writeResourceLocation(component.getId());
181144
component.writeInitialData(buf);
182-
}
145+
});
183146
// Write GUI params
184147
guiParams.write(buf);
185148
}
@@ -238,17 +201,13 @@ public CompoundTag getUpdateTag(HolderLookup.Provider registries) {
238201
CompoundTag tag = new CompoundTag();
239202
tag.putBoolean("remesh", syncCausesRemesh);
240203
syncCausesRemesh = false;
241-
for (IComponent component : icomponents) {
242-
component.writeClientNbt(tag, registries);
243-
}
204+
icomponents.forEach(component -> component.writeClientNbt(tag, registries));
244205
return tag;
245206
}
246207

247208
@Override
248209
public final void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
249-
for (IComponent component : icomponents) {
250-
component.writeNbt(tag, registries);
251-
}
210+
icomponents.forEach(component -> component.writeNbt(tag, registries));
252211
}
253212

254213
@Override
@@ -258,14 +217,10 @@ public final void loadAdditional(CompoundTag tag, HolderLookup.Provider registri
258217

259218
public final void load(CompoundTag tag, HolderLookup.Provider registries, boolean isUpgradingMachine) {
260219
if (!tag.contains("remesh")) {
261-
for (IComponent component : icomponents) {
262-
component.readNbt(tag, registries, isUpgradingMachine);
263-
}
220+
icomponents.forEach(component -> component.readNbt(tag, registries, isUpgradingMachine));
264221
} else {
265222
boolean forceChunkRemesh = tag.getBoolean("remesh");
266-
for (IComponent component : icomponents) {
267-
component.readClientNbt(tag, registries);
268-
}
223+
icomponents.forEach(component -> component.readClientNbt(tag, registries));
269224
if (forceChunkRemesh) {
270225
WorldHelper.forceChunkRemesh(level, worldPosition);
271226
requestModelDataUpdate();
@@ -300,7 +255,7 @@ public static void registerFluidApi(BlockEntityType<?> bet) {
300255

301256
public List<ItemStack> dropExtra() {
302257
List<ItemStack> drops = new ArrayList<>();
303-
forComponentType(DropableComponent.class, u -> drops.add(u.getDrop()));
258+
icomponents.forType(DropableComponent.class, u -> drops.add(u.getDrop()));
304259
return drops;
305260
}
306261

src/main/java/aztech/modern_industrialization/machines/blockentities/multiblocks/AbstractElectricCraftingMultiblockBlockEntity.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,13 @@ protected ItemInteractionResult useItemOn(Player player, InteractionHand hand, D
7777
result = LubricantHelper.onUse(this.crafter, player, hand);
7878
}
7979
if (!result.consumesAction()) {
80-
result = mapComponentOrDefault(UpgradeComponent.class, upgrade -> upgrade.onUse(this, player, hand), result);
80+
result = icomponents.mapOrDefault(UpgradeComponent.class, upgrade -> upgrade.onUse(this, player, hand), result);
8181
}
8282
if (!result.consumesAction()) {
8383
result = redstoneControl.onUse(this, player, hand);
8484
}
8585
if (!result.consumesAction()) {
86-
result = mapComponentOrDefault(OverdriveComponent.class, overdrive -> overdrive.onUse(this, player, hand), result);
86+
result = icomponents.mapOrDefault(OverdriveComponent.class, overdrive -> overdrive.onUse(this, player, hand), result);
8787
}
8888
return result;
8989
}

0 commit comments

Comments
 (0)