Skip to content

Commit 6a19ada

Browse files
committed
feat: ✨ Added linked storage support
1 parent c5b61e4 commit 6a19ada

63 files changed

Lines changed: 3760 additions & 19 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ loader_version_range=[4,)
1515
mod_id=sophisticatedcore
1616
mod_name=Sophisticated Core
1717
mod_license=All Rights Reserved
18-
mod_version=1.4.90
18+
mod_version=1.5.0
1919
mod_group_id=net.p3pp3rf1y
2020
mod_authors=P3pp3rF1y
2121
mod_description=A library / shared functionality mod for Sophisticated Storage and Backpacks
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{
2+
"neoforge:conditions": [
3+
{
4+
"type": "sophisticatedcore:item_enabled",
5+
"itemRegistryName": "sophisticatedcore:ender_linker"
6+
},
7+
{
8+
"type": "neoforge:or",
9+
"values": [
10+
{
11+
"type": "neoforge:mod_loaded",
12+
"modid": "sophisticatedbackpacks"
13+
},
14+
{
15+
"type": "neoforge:mod_loaded",
16+
"modid": "sophisticatedstorage"
17+
}
18+
]
19+
}
20+
],
21+
"parent": "minecraft:recipes/root",
22+
"criteria": {
23+
"has_ender_pearl": {
24+
"conditions": {
25+
"items": [
26+
{
27+
"items": "minecraft:ender_pearl"
28+
}
29+
]
30+
},
31+
"trigger": "minecraft:inventory_changed"
32+
},
33+
"has_the_recipe": {
34+
"conditions": {
35+
"recipe": "sophisticatedcore:ender_linker"
36+
},
37+
"trigger": "minecraft:recipe_unlocked"
38+
}
39+
},
40+
"requirements": [
41+
[
42+
"has_the_recipe",
43+
"has_ender_pearl"
44+
]
45+
],
46+
"rewards": {
47+
"recipes": [
48+
"sophisticatedcore:ender_linker"
49+
]
50+
}
51+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"neoforge:conditions": [
3+
{
4+
"type": "sophisticatedcore:item_enabled",
5+
"itemRegistryName": "sophisticatedcore:ender_linker"
6+
},
7+
{
8+
"type": "neoforge:or",
9+
"values": [
10+
{
11+
"type": "neoforge:mod_loaded",
12+
"modid": "sophisticatedbackpacks"
13+
},
14+
{
15+
"type": "neoforge:mod_loaded",
16+
"modid": "sophisticatedstorage"
17+
}
18+
]
19+
}
20+
],
21+
"type": "minecraft:crafting_shaped",
22+
"category": "misc",
23+
"key": {
24+
"B": {
25+
"item": "minecraft:blaze_rod"
26+
},
27+
"E": {
28+
"item": "minecraft:ender_pearl"
29+
},
30+
"O": {
31+
"item": "minecraft:obsidian"
32+
}
33+
},
34+
"pattern": [
35+
"OEO",
36+
"BOB",
37+
"OEO"
38+
],
39+
"result": {
40+
"count": 1,
41+
"id": "sophisticatedcore:ender_linker"
42+
}
43+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"neoforge:conditions": [
3+
{
4+
"type": "neoforge:or",
5+
"values": [
6+
{
7+
"type": "neoforge:mod_loaded",
8+
"modid": "sophisticatedbackpacks"
9+
},
10+
{
11+
"type": "neoforge:mod_loaded",
12+
"modid": "sophisticatedstorage"
13+
}
14+
]
15+
}
16+
],
17+
"type": "sophisticatedcore:ender_linker_clear",
18+
"category": "misc"
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"neoforge:conditions": [
3+
{
4+
"type": "neoforge:or",
5+
"values": [
6+
{
7+
"type": "neoforge:mod_loaded",
8+
"modid": "sophisticatedbackpacks"
9+
},
10+
{
11+
"type": "neoforge:mod_loaded",
12+
"modid": "sophisticatedstorage"
13+
}
14+
]
15+
}
16+
],
17+
"type": "sophisticatedcore:ender_linker_endpoint",
18+
"category": "misc"
19+
}

src/main/java/net/p3pp3rf1y/sophisticatedcore/SophisticatedCore.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import net.p3pp3rf1y.sophisticatedcore.data.DataGenerators;
2525
import net.p3pp3rf1y.sophisticatedcore.init.ModCompat;
2626
import net.p3pp3rf1y.sophisticatedcore.init.ModCoreDataComponents;
27+
import net.p3pp3rf1y.sophisticatedcore.init.ModItems;
2728
import net.p3pp3rf1y.sophisticatedcore.inventory.StorageWrapperRepository;
2829
import net.p3pp3rf1y.sophisticatedcore.settings.DatapackSettingsTemplateManager;
2930
import net.p3pp3rf1y.sophisticatedcore.util.RecipeHelper;
@@ -52,6 +53,7 @@ public SophisticatedCore(IEventBus modBus, Dist dist, ModContainer container) {
5253
}
5354
Config.COMMON.initListeners(modBus);
5455
ModCoreDataComponents.register(modBus);
56+
ModItems.register(modBus);
5557
modBus.addListener((FMLConstructModEvent event) -> construct(event, modBus));
5658
modBus.addListener(SophisticatedCore::setup);
5759
modBus.addListener(DataGenerators::gatherData);

src/main/java/net/p3pp3rf1y/sophisticatedcore/client/ClientEventHandler.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@
1010
import net.minecraft.client.gui.screens.Screen;
1111
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
1212
import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen;
13+
import net.minecraft.client.renderer.item.ItemProperties;
1314
import net.minecraft.network.chat.Component;
1415
import net.minecraft.resources.ResourceLocation;
1516
import net.minecraft.world.inventory.AbstractContainerMenu;
1617
import net.minecraft.world.inventory.Slot;
1718
import net.minecraft.world.inventory.tooltip.TooltipComponent;
1819
import net.minecraft.world.item.ItemStack;
1920
import net.neoforged.bus.api.IEventBus;
21+
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
2022
import net.neoforged.neoforge.client.event.ClientTickEvent;
2123
import net.neoforged.neoforge.client.event.ContainerScreenEvent;
2224
import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent;
@@ -27,6 +29,7 @@
2729
import net.neoforged.neoforge.client.settings.IKeyConflictContext;
2830
import net.neoforged.neoforge.client.settings.KeyModifier;
2931
import net.neoforged.neoforge.common.NeoForge;
32+
import net.neoforged.neoforge.event.entity.player.ItemTooltipEvent;
3033
import net.p3pp3rf1y.sophisticatedcore.SophisticatedCore;
3134
import net.p3pp3rf1y.sophisticatedcore.api.IStashStorageItem;
3235
import net.p3pp3rf1y.sophisticatedcore.client.gui.StorageScreenBase;
@@ -36,7 +39,9 @@
3639
import net.p3pp3rf1y.sophisticatedcore.client.render.BlockHighlightRenderer;
3740
import net.p3pp3rf1y.sophisticatedcore.common.gui.StorageContainerMenuBase;
3841
import net.p3pp3rf1y.sophisticatedcore.init.ModFluids;
42+
import net.p3pp3rf1y.sophisticatedcore.init.ModItems;
3943
import net.p3pp3rf1y.sophisticatedcore.inventory.ItemStackKey;
44+
import net.p3pp3rf1y.sophisticatedcore.linkedstorage.EnderLinkerItem;
4045
import net.p3pp3rf1y.sophisticatedcore.upgrades.jukebox.StorageSoundHandler;
4146
import org.lwjgl.glfw.GLFW;
4247

@@ -61,19 +66,26 @@ private ClientEventHandler() {
6166

6267
public static void registerHandlers(IEventBus modBus) {
6368
modBus.addListener(ModParticles::registerFactories);
69+
modBus.addListener(ClientEventHandler::setup);
6470
modBus.addListener(ClientEventHandler::registerFluidClientExtension);
6571
modBus.addListener(ClientEventHandler::registerKeyMappings);
6672
IEventBus eventBus = NeoForge.EVENT_BUS;
6773
eventBus.addListener(StorageSoundHandler::tick);
6874
eventBus.addListener(StorageSoundHandler::onWorldUnload);
6975
eventBus.addListener(ClientEventHandler::onDrawScreen);
7076
eventBus.addListener(ClientEventHandler::onContainerScreenForeground);
77+
eventBus.addListener(ClientEventHandler::onItemTooltip);
7178
eventBus.addListener(ClientEventHandler::handleGuiKeyPress);
7279
eventBus.addListener(ClientEventHandler::handleGuiMouseKeyPress);
7380
eventBus.addListener(ClientEventHandler::renderLevelStage);
7481
eventBus.addListener(ClientEventHandler::onTickEnd);
7582
}
7683

84+
private static void setup(FMLClientSetupEvent event) {
85+
event.enqueueWork(() -> ItemProperties.register(ModItems.ENDER_LINKER.get(), SophisticatedCore.getRL("bound"),
86+
(stack, level, entity, seed) -> EnderLinkerItem.hasBoundPresentation(stack) ? 1.0F : 0.0F));
87+
}
88+
7789
private static void onTickEnd(ClientTickEvent.Post event) {
7890
ItemStackKey.clearCache();
7991
}
@@ -180,6 +192,8 @@ private static void onContainerScreenForeground(ContainerScreenEvent.Render.Fore
180192
return;
181193
}
182194
AbstractContainerMenu menu = containerGui.getMenu();
195+
LinkerCraftingDiagnostics.requestIfChanged(menu);
196+
renderLinkerCraftingDiagnostics(event.getGuiGraphics(), menu);
183197
ItemStack held = menu.getCarried();
184198
if (held.isEmpty()) {
185199
return;
@@ -196,6 +210,35 @@ private static void onContainerScreenForeground(ContainerScreenEvent.Render.Fore
196210
}
197211
}
198212

213+
private static void renderLinkerCraftingDiagnostics(GuiGraphics guiGraphics, AbstractContainerMenu menu) {
214+
for (Slot slot : menu.slots) {
215+
renderLinkerCraftingDiagnostic(guiGraphics, slot);
216+
}
217+
if (menu instanceof StorageContainerMenuBase<?> storageContainer) {
218+
storageContainer.upgradeSlots.forEach(slot -> renderLinkerCraftingDiagnostic(guiGraphics, slot));
219+
}
220+
}
221+
222+
private static void renderLinkerCraftingDiagnostic(GuiGraphics guiGraphics, Slot slot) {
223+
if (LinkerCraftingDiagnostics.getStatusMessage(slot.index) != null) {
224+
guiGraphics.fill(slot.x, slot.y, slot.x + 16, slot.y + 16, 0x80FF0000);
225+
}
226+
}
227+
228+
private static void onItemTooltip(ItemTooltipEvent event) {
229+
if (!(Minecraft.getInstance().screen instanceof AbstractContainerScreen<?> screen)) {
230+
return;
231+
}
232+
Slot slot = screen.getSlotUnderMouse();
233+
if (slot == null || slot.getItem() != event.getItemStack()) {
234+
return;
235+
}
236+
String statusMessage = LinkerCraftingDiagnostics.getStatusMessage(slot.index);
237+
if (statusMessage != null) {
238+
event.getToolTip().add(TranslationHelper.INSTANCE.translStatusMessage(statusMessage).withStyle(ChatFormatting.RED));
239+
}
240+
}
241+
199242
private static void renderStashSign(Minecraft mc, GuiGraphics guiGraphics, Slot s, ItemStack stack, IStashStorageItem.StashResult stashResult) {
200243
int x = s.x;
201244
int y = s.y;
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package net.p3pp3rf1y.sophisticatedcore.client;
2+
3+
import net.minecraft.client.Minecraft;
4+
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
5+
import net.minecraft.world.inventory.AbstractContainerMenu;
6+
import net.minecraft.world.inventory.CraftingContainer;
7+
import net.minecraft.world.inventory.Slot;
8+
import net.neoforged.neoforge.network.PacketDistributor;
9+
import net.p3pp3rf1y.sophisticatedcore.common.gui.ICraftingContainer;
10+
import net.p3pp3rf1y.sophisticatedcore.common.gui.StorageContainerMenuBase;
11+
import net.p3pp3rf1y.sophisticatedcore.common.gui.UpgradeContainerBase;
12+
import net.p3pp3rf1y.sophisticatedcore.network.RequestLinkerCraftingDiagnosticsPayload;
13+
import net.p3pp3rf1y.sophisticatedcore.network.SyncLinkerCraftingDiagnosticsPayload;
14+
15+
import javax.annotation.Nullable;
16+
17+
import java.util.HashMap;
18+
import java.util.List;
19+
import java.util.Map;
20+
21+
public final class LinkerCraftingDiagnostics {
22+
private static int lastRequestedContainerId = -1;
23+
private static int lastRequestedSignature;
24+
@Nullable
25+
private static AbstractContainerMenu lastRequestedMenu;
26+
private static final Map<Integer, String> diagnostics = new HashMap<>();
27+
28+
private LinkerCraftingDiagnostics() {
29+
}
30+
31+
public static void requestIfChanged(AbstractContainerMenu menu) {
32+
if (menu != lastRequestedMenu) {
33+
lastRequestedMenu = menu;
34+
lastRequestedContainerId = -1;
35+
diagnostics.clear();
36+
}
37+
int signature = 1;
38+
boolean hasCraftingGrid = false;
39+
for (Slot slot : menu.slots) {
40+
if (slot.container instanceof CraftingContainer) {
41+
signature = 31 * signature + 31 * slot.index + slot.getItem().hashCode();
42+
hasCraftingGrid = true;
43+
}
44+
}
45+
if (menu instanceof StorageContainerMenuBase<?> storageContainer) {
46+
for (UpgradeContainerBase<?, ?> upgradeContainer : storageContainer.getUpgradeContainers().values()) {
47+
if (upgradeContainer instanceof ICraftingContainer craftingContainer) {
48+
for (int slot = 0; slot < craftingContainer.getCraftMatrix().getContainerSize(); slot++) {
49+
signature = 31 * signature + craftingContainer.getCraftMatrix().getItem(slot).hashCode();
50+
}
51+
hasCraftingGrid = true;
52+
}
53+
}
54+
}
55+
if (!hasCraftingGrid) {
56+
diagnostics.clear();
57+
lastRequestedMenu = null;
58+
lastRequestedContainerId = -1;
59+
return;
60+
}
61+
if (menu.containerId == lastRequestedContainerId && signature == lastRequestedSignature) {
62+
return;
63+
}
64+
lastRequestedContainerId = menu.containerId;
65+
lastRequestedSignature = signature;
66+
diagnostics.clear();
67+
PacketDistributor.sendToServer(new RequestLinkerCraftingDiagnosticsPayload(menu.containerId));
68+
}
69+
70+
public static void update(int containerId, List<SyncLinkerCraftingDiagnosticsPayload.Diagnostic> updatedDiagnostics) {
71+
if (!(Minecraft.getInstance().screen instanceof AbstractContainerScreen<?> screen) || screen.getMenu().containerId != containerId) {
72+
return;
73+
}
74+
diagnostics.clear();
75+
updatedDiagnostics.forEach(diagnostic -> diagnostics.put(diagnostic.slot(), diagnostic.statusMessageKey()));
76+
}
77+
78+
@Nullable
79+
public static String getStatusMessage(int slot) {
80+
return diagnostics.get(slot);
81+
}
82+
}

0 commit comments

Comments
 (0)