/*
* 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 .
*/
package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.boss.EntityDragon;
import net.minecraft.entity.boss.EntityWither;
import net.minecraft.entity.item.EntityArmorStand;
import net.minecraft.entity.monster.EntityBlaze;
import net.minecraft.entity.monster.EntityCaveSpider;
import net.minecraft.entity.monster.EntityCreeper;
import net.minecraft.entity.monster.EntityEnderman;
import net.minecraft.entity.monster.EntityEndermite;
import net.minecraft.entity.monster.EntityGhast;
import net.minecraft.entity.monster.EntityGiantZombie;
import net.minecraft.entity.monster.EntityGuardian;
import net.minecraft.entity.monster.EntityIronGolem;
import net.minecraft.entity.monster.EntityMagmaCube;
import net.minecraft.entity.monster.EntityPigZombie;
import net.minecraft.entity.monster.EntitySilverfish;
import net.minecraft.entity.monster.EntitySkeleton;
import net.minecraft.entity.monster.EntitySlime;
import net.minecraft.entity.monster.EntitySnowman;
import net.minecraft.entity.monster.EntitySpider;
import net.minecraft.entity.monster.EntityWitch;
import net.minecraft.entity.monster.EntityZombie;
import net.minecraft.entity.passive.EntityBat;
import net.minecraft.entity.passive.EntityChicken;
import net.minecraft.entity.passive.EntityCow;
import net.minecraft.entity.passive.EntityHorse;
import net.minecraft.entity.passive.EntityMooshroom;
import net.minecraft.entity.passive.EntityOcelot;
import net.minecraft.entity.passive.EntityPig;
import net.minecraft.entity.passive.EntityRabbit;
import net.minecraft.entity.passive.EntitySheep;
import net.minecraft.entity.passive.EntitySquid;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.passive.EntityWolf;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.input.Keyboard;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
public class EntityViewer extends GuiScreen {
public static Map> validEntities =
new HashMap>() {{
put("Zombie", () -> new EntityZombie(null));
put("Chicken", () -> new EntityChicken(null));
put("Slime", () -> new EntitySlime(null));
put("Wolf", () -> new EntityWolf(null));
put("Skeleton", () -> new EntitySkeleton(null));
put("Creeper", () -> new EntityCreeper(null));
put("Ocelot", () -> new EntityOcelot(null));
put("Blaze", () -> new EntityBlaze(null));
put("Rabbit", () -> new EntityRabbit(null));
put("Sheep", () -> new EntitySheep(null));
put("Horse", () -> new EntityHorse(null));
put("Eisengolem", () -> new EntityIronGolem(null));
put("Silverfish", () -> new EntitySilverfish(null));
put("Witch", () -> new EntityWitch(null));
put("Endermite", () -> new EntityEndermite(null));
put("Snowman", () -> new EntitySnowman(null));
put("Villager", () -> new EntityVillager(null));
put("Guardian", () -> new EntityGuardian(null));
put("ArmorStand", () -> new EntityArmorStand(null));
put("Squid", () -> new EntitySquid(null));
put("Bat", () -> new EntityBat(null));
put("Spider", () -> new EntitySpider(null));
put("CaveSpider", () -> new EntityCaveSpider(null));
put("Pigman", () -> new EntityPigZombie(null));
put("Ghast", () -> new EntityGhast(null));
put("MagmaCube", () -> new EntityMagmaCube(null));
put("Wither", () -> new EntityWither(null));
put("Enderman", () -> new EntityEnderman(null));
put("Mooshroom", () -> new EntityMooshroom(null));
put("WitherSkeleton", () -> {
EntitySkeleton skeleton = new EntitySkeleton(null);
skeleton.setSkeletonType(1);
return skeleton;
});
put("Cow", () -> new EntityCow(null));
put("Dragon", () -> new EntityDragon(null));
put("Player", () -> new GUIClientPlayer());
put("Pig", () -> new EntityPig(null));
put("Giant", () -> new EntityGiantZombie(null));
}};
public static Map validModifiers = new HashMap() {{
put("playerdata", new SkinModifier());
put("equipment", new EquipmentModifier());
put("riding", new RidingModifier());
put("charged", new ChargedModifier());
put("witherdata", new WitherModifier());
put("invisible", new InvisibleModifier());
put("age", new AgeModifier());
put("horse", new HorseModifier());
put("name", new NameModifier());
}};
public int guiLeft = 0;
public int guiTop = 0;
public int xSize = 176;
public int ySize = 166;
private final String label;
private final EntityLivingBase entity;
private static final ResourceLocation BACKGROUND = new ResourceLocation(
"notenoughupdates",
"textures/gui/entity_viewer.png"
);
public EntityViewer(String label, EntityLivingBase entity) {
this.label = label;
this.entity = entity;
}
public static EntityLivingBase constructEntity(ResourceLocation resourceLocation) {
Gson gson = NotEnoughUpdates.INSTANCE.manager.gson;
try (
Reader is = new InputStreamReader(
Minecraft.getMinecraft().getResourceManager().getResource(resourceLocation).getInputStream(),
StandardCharsets.UTF_8
)
) {
return constructEntity(gson.fromJson(is, JsonObject.class));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static EntityLivingBase constructEntity(JsonObject info) {
List modifiers = info.has("modifiers") ?
StreamSupport.stream(info.get("modifiers").getAsJsonArray().spliterator(), false)
.map(JsonElement::getAsJsonObject).collect(Collectors.toList())
: Collections.emptyList();
return EntityViewer.constructEntity(info.get("entity").getAsString(), modifiers);
}
public static EntityLivingBase constructEntity(String string, String[] modifiers) {
Gson gson = NotEnoughUpdates.INSTANCE.manager.gson;
return constructEntity(
string,
Arrays.stream(modifiers).map(it -> gson.fromJson(it, JsonObject.class)).collect(Collectors.toList())
);
}
public static EntityLivingBase constructEntity(String string, List modifiers) {
Supplier extends EntityLivingBase> aClass = validEntities.get(string);
if (aClass == null) {
System.err.println("Could not find entity of type: " + string);
return null;
}
try {
EntityLivingBase entity = aClass.get();
for (JsonObject modifier : modifiers) {
String type = modifier.get("type").getAsString();
EntityViewerModifier entityViewerModifier = validModifiers.get(type);
entity = entityViewerModifier.applyModifier(entity, modifier);
if (entity == null) break;
}
return entity;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
drawDefaultBackground();
this.guiLeft = (width - this.xSize) / 2;
this.guiTop = (height - this.ySize) / 2;
Minecraft.getMinecraft().getTextureManager().bindTexture(BACKGROUND);
drawTexturedModalRect(guiLeft, guiTop, 0, 0, this.xSize, this.ySize);
Utils.drawStringScaledMaxWidth(label, guiLeft + 10, guiTop + 10, false, 100, 0xFF00FF);
renderEntity(entity, guiLeft + 90, guiTop + 75, mouseX, mouseY);
}
public static void renderEntity(EntityLivingBase entity, int posX, int posY, int mouseX, int mouseY) {
GlStateManager.color(1F, 1F, 1F, 1F);
int scale = 30;
float bottomOffset = 0F;
EntityLivingBase stack = entity;
while (true) {
if (stack instanceof EntityDragon) {
if (Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
scale = 35;
bottomOffset = 0F;
}
else {
scale = 10;
bottomOffset = 2F;
}
} else if (stack instanceof EntityWither) {
scale = 20;
} else if (stack instanceof EntityGhast) {
scale = 8;
bottomOffset = 4F;
} else if (stack instanceof EntityGiantZombie) {
scale = 8;
bottomOffset = -2F;
}
stack.ticksExisted = Minecraft.getMinecraft().thePlayer.ticksExisted;
drawEntityOnScreen(
posX,
(int) (posY - bottomOffset * scale),
scale,
posX - mouseX,
(int) (posY - stack.getEyeHeight() * scale - mouseY),
stack
);
bottomOffset += stack.getMountedYOffset();
if (!(stack.riddenByEntity instanceof EntityLivingBase)) {
break;
}
stack = (EntityLivingBase) stack.riddenByEntity;
}
}
// Need this to flip the ender dragon and make it follow mouse correctly
public static void drawEntityOnScreen(int posX, int posY, int scale, float mouseX, float mouseY, EntityLivingBase ent) {
GlStateManager.enableColorMaterial();
GlStateManager.pushMatrix();
GlStateManager.translate((float)posX, (float)posY, 50.0F);
GlStateManager.scale((float)(-scale), (float)scale, (float)scale);
GlStateManager.rotate(180.0F, 0.0F, 0.0F, 1.0F);
float f = ent.renderYawOffset;
float g = ent.rotationYaw;
float h = ent.rotationPitch;
float i = ent.prevRotationYawHead;
float j = ent.rotationYawHead;
GlStateManager.rotate(135.0F, 0.0F, 1.0F, 0.0F);
RenderHelper.enableStandardItemLighting();
GlStateManager.rotate((ent instanceof EntityDragon) ? 45.0F : -135.0F, 0.0F, 1.0F, 0.0F);
GlStateManager.rotate((ent instanceof EntityDragon) ? ((float)Math.atan(mouseY / 40.0F)) * 20.0F : -((float)Math.atan(mouseY / 40.0F)) * 20.0F, 1.0F, 0.0F, 0.0F);
ent.renderYawOffset = (float)Math.atan(mouseX / 40.0F) * 20.0F;
ent.rotationYaw = (float)Math.atan(mouseX / 40.0F) * 40.0F;
ent.rotationPitch = -((float)Math.atan(mouseY / 40.0F)) * 20.0F;
ent.rotationYawHead = ent.rotationYaw;
ent.prevRotationYawHead = ent.rotationYaw;
GlStateManager.translate(0.0F, 0.0F, 0.0F);
RenderManager renderManager = Minecraft.getMinecraft().getRenderManager();
renderManager.setPlayerViewY(180.0F);
renderManager.setRenderShadow(false);
renderManager.renderEntityWithPosYaw(ent, 0.0D, 0.0D, 0.0D, 0.0F, 1.0F);
renderManager.setRenderShadow(true);
ent.renderYawOffset = f;
ent.rotationYaw = g;
ent.rotationPitch = h;
ent.prevRotationYawHead = i;
ent.rotationYawHead = j;
GlStateManager.popMatrix();
RenderHelper.disableStandardItemLighting();
GlStateManager.disableRescaleNormal();
GlStateManager.setActiveTexture(OpenGlHelper.lightmapTexUnit);
GlStateManager.disableTexture2D();
GlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit);
}
}