-
Notifications
You must be signed in to change notification settings - Fork 49
Expand file tree
/
Copy pathGuiManager.java
More file actions
154 lines (139 loc) · 6.85 KB
/
GuiManager.java
File metadata and controls
154 lines (139 loc) · 6.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package com.cleanroommc.modularui.factory;
import com.cleanroommc.modularui.api.IMuiScreen;
import com.cleanroommc.modularui.api.JeiSettings;
import com.cleanroommc.modularui.api.MCHelper;
import com.cleanroommc.modularui.api.UIFactory;
import com.cleanroommc.modularui.network.NetworkHandler;
import com.cleanroommc.modularui.network.packets.OpenGuiPacket;
import com.cleanroommc.modularui.screen.*;
import com.cleanroommc.modularui.value.sync.PanelSyncManager;
import com.cleanroommc.modularui.widget.WidgetTree;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.client.event.GuiOpenEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.event.entity.player.PlayerContainerEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
public class GuiManager {
protected static final Object2ObjectMap<String, UIFactory<?>> FACTORIES = new Object2ObjectOpenHashMap<>(16);
private static IMuiScreen lastMui;
private static final List<EntityPlayer> openedContainers = new ArrayList<>(4);
public static void registerFactory(UIFactory<?> factory) {
Objects.requireNonNull(factory);
String name = Objects.requireNonNull(factory.getFactoryName());
if (name.length() > 32) {
throw new IllegalArgumentException("The factory name length must not exceed 32!");
}
if (FACTORIES.containsKey(name)) {
throw new IllegalArgumentException("Factory with name '" + name + "' is already registered!");
}
FACTORIES.put(name, factory);
}
public static @NotNull UIFactory<?> getFactory(String name) {
UIFactory<?> factory = FACTORIES.get(name);
if (factory == null) throw new NoSuchElementException();
return factory;
}
public static boolean hasFactory(String name) {
return FACTORIES.containsKey(name);
}
public static <T extends GuiData> void open(@NotNull UIFactory<T> factory, @NotNull T guiData, EntityPlayerMP player) {
if (player instanceof FakePlayer || openedContainers.contains(player)) return;
openedContainers.add(player);
// create panel, collect sync handlers and create container
guiData.setJeiSettings(JeiSettings.DUMMY);
PanelSyncManager syncManager = new PanelSyncManager();
ModularPanel panel = factory.createPanel(guiData, syncManager);
WidgetTree.collectSyncValues(syncManager, panel);
ModularContainer container = new ModularContainer(player, syncManager, panel.getName());
// sync to client
player.getNextWindowId();
player.closeContainer();
int windowId = player.currentWindowId;
PacketBuffer buffer = new PacketBuffer(Unpooled.buffer());
factory.writeGuiData(guiData, buffer);
NetworkHandler.sendToPlayer(new OpenGuiPacket<>(windowId, factory, buffer), player);
// open container // this mimics forge behaviour
player.openContainer = container;
player.openContainer.windowId = windowId;
player.openContainer.addListener(player);
// finally invoke event
MinecraftForge.EVENT_BUS.post(new PlayerContainerEvent.Open(player, container));
}
@SideOnly(Side.CLIENT)
public static <T extends GuiData> void open(int windowId, @NotNull UIFactory<T> factory, @NotNull PacketBuffer data, @NotNull EntityPlayerSP player) {
T guiData = factory.readGuiData(player, data);
JeiSettingsImpl jeiSettings = new JeiSettingsImpl();
guiData.setJeiSettings(jeiSettings);
PanelSyncManager syncManager = new PanelSyncManager();
ModularPanel panel = factory.createPanel(guiData, syncManager);
WidgetTree.collectSyncValues(syncManager, panel);
ModularScreen screen = factory.createScreen(guiData, panel);
screen.getContext().setJeiSettings(jeiSettings);
ModularContainer container = new ModularContainer(player, syncManager, panel.getName());
IMuiScreen wrapper = factory.createScreenWrapper(container, screen);
if (!(wrapper.getGuiScreen() instanceof GuiContainer guiContainer)) {
throw new IllegalStateException("The wrapping screen must be a GuiContainer for synced GUIs!");
}
if (guiContainer.inventorySlots != container) throw new IllegalStateException("Custom Containers are not yet allowed!");
guiContainer.inventorySlots.windowId = windowId;
MCHelper.displayScreen(wrapper.getGuiScreen());
player.openContainer = guiContainer.inventorySlots;
}
@SideOnly(Side.CLIENT)
static void openScreen(ModularScreen screen, JeiSettingsImpl jeiSettings, ContainerCustomizer containerCustomizer) {
screen.getContext().setJeiSettings(jeiSettings);
GuiScreen guiScreen;
if (containerCustomizer == null) {
guiScreen = new GuiScreenWrapper(screen);
} else {
guiScreen = new GuiContainerWrapper(new ModularContainer(containerCustomizer), screen);
}
MCHelper.displayScreen(guiScreen);
}
@SubscribeEvent
public static void onTick(TickEvent.ServerTickEvent event) {
if (event.phase == TickEvent.Phase.END) {
openedContainers.clear();
}
}
@SideOnly(Side.CLIENT)
@SubscribeEvent
public static void onGuiOpen(GuiOpenEvent event) {
if (lastMui != null && event.getGui() == null) {
if (lastMui.getScreen().getPanelManager().isOpen()) {
lastMui.getScreen().getPanelManager().closeAll();
}
lastMui.getScreen().getPanelManager().dispose();
lastMui = null;
} else if (event.getGui() instanceof IMuiScreen screenWrapper) {
if (lastMui == null) {
lastMui = screenWrapper;
} else if (lastMui == event.getGui()) {
lastMui.getScreen().getPanelManager().reopen();
} else {
if (lastMui.getScreen().getPanelManager().isOpen()) {
lastMui.getScreen().getPanelManager().closeAll();
}
lastMui.getScreen().getPanelManager().dispose();
lastMui = screenWrapper;
}
}
}
}