aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de/hysky/skyblocker/utils/container/ContainerSolverManager.java
blob: cf98941ccada1fb9dfb4d5317fa1e223080dd292 (plain)
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 de.hysky.skyblocker.utils.container;

import com.mojang.blaze3d.systems.RenderSystem;
import de.hysky.skyblocker.mixins.accessors.HandledScreenAccessor;
import de.hysky.skyblocker.skyblock.accessories.newyearcakes.NewYearCakeBagHelper;
import de.hysky.skyblocker.skyblock.accessories.newyearcakes.NewYearCakesHelper;
import de.hysky.skyblocker.skyblock.bazaar.ReorderHelper;
import de.hysky.skyblocker.skyblock.chocolatefactory.ChocolateFactorySolver;
import de.hysky.skyblocker.skyblock.dungeon.CroesusHelper;
import de.hysky.skyblocker.skyblock.dungeon.CroesusProfit;
import de.hysky.skyblocker.skyblock.dungeon.terminal.ColorTerminal;
import de.hysky.skyblocker.skyblock.dungeon.terminal.LightsOnTerminal;
import de.hysky.skyblocker.skyblock.dungeon.terminal.OrderTerminal;
import de.hysky.skyblocker.skyblock.dungeon.terminal.StartsWithTerminal;
import de.hysky.skyblocker.skyblock.dwarven.CommissionHighlight;
import de.hysky.skyblocker.skyblock.experiment.ChronomatronSolver;
import de.hysky.skyblocker.skyblock.experiment.SuperpairsSolver;
import de.hysky.skyblocker.skyblock.experiment.UltrasequencerSolver;
import de.hysky.skyblocker.utils.Utils;
import de.hysky.skyblocker.utils.render.gui.ColorHighlight;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectRBTreeMap;
import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.slot.Slot;
import org.jetbrains.annotations.NotNull;

import java.util.List;

/**
 * Manager class for {@link SimpleContainerSolver}s like terminal solvers and experiment solvers. To add a new gui solver, extend {@link SimpleContainerSolver} and register it in {@link #ContainerSolverManager()}.
 */
public class ContainerSolverManager {
	private final ContainerSolver[] solvers;
	private ContainerSolver currentSolver = null;
	private List<ColorHighlight> highlights;
	/**
	 * Useful for keeping track of a solver's state in a Screen instance, such as if Hypixel closes & reopens a screen after every click (as they do with terminals).
	 */
	private int screenId = 0;

	public ContainerSolverManager() {
		solvers = new ContainerSolver[]{
				new ColorTerminal(),
				new OrderTerminal(),
				new StartsWithTerminal(),
				new LightsOnTerminal(),
				new CroesusHelper(),
				new CroesusProfit(),
				new ChronomatronSolver(),
				new CommissionHighlight(),
				new SuperpairsSolver(),
				UltrasequencerSolver.INSTANCE,
				new NewYearCakeBagHelper(),
				NewYearCakesHelper.INSTANCE,
				ChocolateFactorySolver.INSTANCE,
				new ReorderHelper()
		};
	}

	public ContainerSolver getCurrentSolver() {
		return currentSolver;
	}

	public void init() {
		ScreenEvents.BEFORE_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
			if (Utils.isOnSkyblock() && screen instanceof GenericContainerScreen genericContainerScreen) {
				ScreenEvents.afterRender(screen).register((screen1, context, mouseX, mouseY, delta) -> {
					MatrixStack matrices = context.getMatrices();
					matrices.push();
					matrices.translate(((HandledScreenAccessor) genericContainerScreen).getX(), ((HandledScreenAccessor) genericContainerScreen).getY(), 300);
					onDraw(context, genericContainerScreen.getScreenHandler().slots.subList(0, genericContainerScreen.getScreenHandler().getRows() * 9));
					matrices.pop();
				});
				ScreenEvents.remove(screen).register(screen1 -> clearScreen());
				onSetScreen(genericContainerScreen);
			} else {
				clearScreen();
			}
		});
	}

	public void onSetScreen(@NotNull GenericContainerScreen screen) {
		String screenName = screen.getTitle().getString();
		for (ContainerSolver solver : solvers) {
			if (solver.isEnabled()) {
				if (solver instanceof SimpleContainerSolver containerSolver && containerSolver.test(screenName)) {
					++screenId;
					currentSolver = containerSolver;
					currentSolver.start(screen);
					markDirty();

					return;
				} else if (solver.test(screen)) {
					++screenId;
					currentSolver = solver;
					currentSolver.start(screen);
					markDirty();

					return;
				}
			}
		}
		clearScreen();
	}

	public void clearScreen() {
		if (currentSolver != null) {
			currentSolver.reset();
			currentSolver = null;
		}
	}

	public void markDirty() {
		highlights = null;
	}

	/**
	 * @return Whether the click should be disallowed.
	 */
	public boolean onSlotClick(int slot, ItemStack stack) {
		if (currentSolver != null) {
			return currentSolver.onClickSlot(slot, stack, screenId);
		}

		return false;
	}

	public void onDraw(DrawContext context, List<Slot> slots) {
		if (currentSolver == null)
			return;
		if (highlights == null)
			highlights = currentSolver.getColors(slotMap(slots));
		RenderSystem.enableDepthTest();
		RenderSystem.colorMask(true, true, true, false);
		for (ColorHighlight highlight : highlights) {
			Slot slot = slots.get(highlight.slot());
			int color = highlight.color();
			context.fill(slot.x, slot.y, slot.x + 16, slot.y + 16, color);
		}
		RenderSystem.colorMask(true, true, true, true);
	}

	private Int2ObjectMap<ItemStack> slotMap(List<Slot> slots) {
		Int2ObjectMap<ItemStack> slotMap = new Int2ObjectRBTreeMap<>();
		for (int i = 0; i < slots.size(); i++) {
			slotMap.put(i, slots.get(i).getStack());
		}
		return slotMap;
	}
}