aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/WitherCloakChanger.java
blob: 704606bf0be3261166dc9c38f8f5607ec191de7c (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
/*
 * Copyright (C) 2022 NotEnoughUpdates contributors
 *
 * This file is part of NotEnoughUpdates.
 *
 * NotEnoughUpdates is free software: you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation, either
 * version 3 of the License, or (at your option) any later version.
 *
 * NotEnoughUpdates is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
 */

package io.github.moulberry.notenoughupdates.miscfeatures;

import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe;
import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Vec3;
import net.minecraftforge.client.event.ClientChatReceivedEvent;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;

@NEUAutoSubscribe
public class WitherCloakChanger {
	public static boolean isCloakActive = false;
	/**
	 * When was the last charged Creeper that is a member of the group rendered?
	 * Used to determine if the cloak was deactivated by Hypixel without sending a message
	 *
	 * @see io.github.moulberry.notenoughupdates.mixins.MixinEntityChargedCreeper#cancelChargedCreeperLayer(net.minecraft.entity.monster.EntityCreeper , float, float, float, float, float, float, float, org.spongepowered.asm.mixin.injection.callback.CallbackInfo)
	 */
	public static long lastCreeperRender = 0;
	public static long lastDeactivate = System.currentTimeMillis();

	@SubscribeEvent(priority = EventPriority.HIGHEST)
	public void onChatMessage(ClientChatReceivedEvent event) {
		if (!NotEnoughUpdates.INSTANCE.isOnSkyblock()) return;
		if (event.message.getUnformattedText().startsWith("Creeper Veil ")) {
			if (isCloakActive && !event.message.getUnformattedText().equals("Creeper Veil Activated!")) {
				isCloakActive = false;
				lastDeactivate = System.currentTimeMillis();
			} else {
				isCloakActive = true;
			}
		} else if (event.message.getUnformattedText().startsWith("Not enough mana! Creeper Veil De-activated!")) {
			isCloakActive = false;
			lastDeactivate = System.currentTimeMillis();
		}
	}

	@SubscribeEvent
	public void onWorldChange(WorldEvent.Unload event) {
		isCloakActive = false;
	}

	private static final ResourceLocation witherCloakShield = new ResourceLocation(
		"notenoughupdates:wither_cloak_shield.png");

	@SubscribeEvent
	public void onRenderLast(RenderWorldLastEvent event) {
		if (isCloakActive) {
			//last creeper rendered over 2 seconds ago -> Creeper Veil de activated without a message. Happens for example when picking up the item in the inventory
			if (System.currentTimeMillis() - lastCreeperRender >= 2000) {
				isCloakActive = false;
				lastDeactivate = System.currentTimeMillis();
				lastCreeperRender = 0;
				return;
			}
		}

		if (!NotEnoughUpdates.INSTANCE.isOnSkyblock() || !isCloakActive ||
			!NotEnoughUpdates.INSTANCE.config.itemOverlays.customWitherCloakToggle) return;
		Minecraft mc = Minecraft.getMinecraft();

		//CONSTANTS (Other contribs, mess with these as you wish, but you should know I chose these for a reason)
		final double shieldWidth = 0.8d; //How wide they are
		final double shieldHeight = 2.0d; //How tall they are
		final double accuracy =
			4.0d; //Will be accurate to 1/accuracy of a degree (so updates every 0.25 degrees with an accuracy of 4)

		for (int i = 0; i < NotEnoughUpdates.INSTANCE.config.itemOverlays.customWitherCloakCount; i++) {
			double angle = (int) (
				((System.currentTimeMillis() / 30 * NotEnoughUpdates.INSTANCE.config.itemOverlays.customWitherCloakSpeed *
					-0.5 * accuracy)) % (360 * accuracy)) / accuracy;
			angle += (360d / NotEnoughUpdates.INSTANCE.config.itemOverlays.customWitherCloakCount) * i;
			angle %= 360;
			double posX = mc.thePlayer.posX - (shieldWidth / 2);
			double posY = mc.thePlayer.posY;
			double posZ = mc.thePlayer.posZ + NotEnoughUpdates.INSTANCE.config.itemOverlays.customWitherCloakDistance;

			Vec3 topLeft = rotateAboutOrigin(
				mc.thePlayer.posX,
				mc.thePlayer.posZ,
				angle,
				new Vec3(posX, posY + shieldHeight, posZ)
			);
			Vec3 topRight = rotateAboutOrigin(
				mc.thePlayer.posX,
				mc.thePlayer.posZ,
				angle,
				new Vec3(posX + shieldWidth, posY + shieldHeight, posZ)
			);
			Vec3 bottomRight = rotateAboutOrigin(
				mc.thePlayer.posX,
				mc.thePlayer.posZ,
				angle,
				new Vec3(posX + shieldWidth, posY, posZ)
			);
			Vec3 bottomLeft = rotateAboutOrigin(mc.thePlayer.posX, mc.thePlayer.posZ, angle, new Vec3(posX, posY, posZ));
			RenderUtils.drawFilledQuadWithTexture(
				topLeft,
				topRight,
				bottomRight,
				bottomLeft, /*NotEnoughUpdates.INSTANCE.config.misc.customWitherCloakTransparency*/
				1.0f,
				witherCloakShield
			);
		}
		GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
		GlStateManager.tryBlendFuncSeparate(
			GL11.GL_SRC_ALPHA,
			GL11.GL_ONE_MINUS_SRC_ALPHA,
			GL11.GL_ONE,
			GL11.GL_ONE_MINUS_SRC_ALPHA
		);
	}

	private static Vec3 rotateAboutOrigin(double originX, double originZ, double angle, Vec3 point) {
		double a = angle * Math.PI / 180;
		double newX = originX + (Math.cos(a) * (point.xCoord - originX) + Math.sin(a) * (point.zCoord - originZ));
		double newZ = originZ + (-Math.sin(a) * (point.xCoord - originX) + Math.cos(a) * (point.zCoord - originZ));
		return new Vec3(newX, point.yCoord, newZ);
	}
}