aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de/hysky/skyblocker/utils/container/ContainerSolverManager.java
blob: 77833a678e0bcf6071dc9a986a60df0ab59aca4c (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
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.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.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 ContainerSolver}s like terminal solvers and experiment solvers. To add a new gui solver, extend {@link ContainerSolver} and register it in {@link #ContainerSolverManager()}.
 */
public class ContainerSolverManager {
	private final AbstractContainerSolver[] solvers;
	private AbstractContainerSolver 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 AbstractContainerSolver[]{
				new ColorTerminal(),
				new OrderTerminal(),
				new StartsWithTerminal(),
				new LightsOnTerminal(),
				new CroesusHelper(),
				new CroesusProfit(),
				new ChronomatronSolver(),
				new SuperpairsSolver(),
				UltrasequencerSolver.INSTANCE,
				new NewYearCakeBagHelper(),
				NewYearCakesHelper.INSTANCE,
				new ChocolateFactorySolver()
		};
	}

	public AbstractContainerSolver 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 (AbstractContainerSolver solver : solvers) {
			if (solver.isEnabled()) {
				if (solver instanceof ContainerSolver 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;
	}
}