Jump to content

[1.12] Getting and Using world.loadedEntities remotely


Recommended Posts

Posted (edited)

So I basically have a mod that's supposed to draw an esp over every mob in the world (or at least within viewing distance)

 

Main.java

package prickles.insightsq.core;

import java.util.ArrayList;
import java.util.Arrays;

import net.minecraft.client.Minecraft;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.Mod.Instance;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import prickles.insight.hud.HelmetHandler;
import prickles.insight.hud.RenderOverlayHandler;
import prickles.insightsq.core.proxies.CommonProxy;

@Mod(modid = Reference.MODID, name = Reference.NAME, version = Reference.VERSION)
public class Main {
	@Instance
	public static Main instance;
	
	@SidedProxy(clientSide = Reference.CLIENT, serverSide = Reference.COMMON)
	public static CommonProxy proxy;
	
	public static Minecraft mc;
	
	public static ArrayList<String> friendlyUsernames = new ArrayList<String>();
	public static String[] friendlyNamesArr;
	
	@EventHandler
	public static void preInit(FMLPreInitializationEvent e) {
		proxy.preInit(e);
	}
	
	@EventHandler
	public static void init(FMLInitializationEvent e) {				
		proxy.init(e);
		
		initialize();
		
		MinecraftForge.EVENT_BUS.register(HelmetHandler.class);
	}
	
	@EventHandler
	public static void postInit(FMLPostInitializationEvent e) {				
		proxy.postInit(e);
		
		MinecraftForge.EVENT_BUS.register(new RenderOverlayHandler(mc));
	}
	
	public static void initialize() {
		mc = Minecraft.getMinecraft();
		friendlyNamesArr = new String[] { "Pr1ckl3s", "DoubleBrackets", "UnderCoverChicken", "Cutout", "Generaltyler1", "EmeraldUpsilon" };
		friendlyUsernames.addAll(Arrays.asList(friendlyNamesArr));
	}
}

 

HelmetHandler.java

package prickles.insight.hud;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import net.minecraft.client.entity.EntityOtherPlayerMP;
import net.minecraft.entity.Entity;
import net.minecraft.entity.monster.EntityMob;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import prickles.insight.hud.utils.RenderUtils;
import prickles.insightsq.core.Main;

public class HelmetHandler {

	public static boolean equipped;

	public static List<Entity> worldEntities;

	@SubscribeEvent
	public static void helmet(TickEvent.PlayerTickEvent event) {
		EntityPlayer p = event.player;

		if (p.inventory.armorItemInSlot(3).getItem() == Item.getItemById(314)) {
			equipped = true;
		} else {
			equipped = false;
		}

		if (Main.friendlyUsernames.contains(p.getName())) {
			Main.friendlyUsernames.remove(Arrays.binarySearch(Main.friendlyNamesArr, p.getName()));
		}
	}

	@SubscribeEvent
	public static void worldLoader(TickEvent.WorldTickEvent event) {
		worldEntities = event.world.loadedEntityList;
	}

		@SubscribeEvent
	public static void render(RenderWorldLastEvent event) {
		if (equipped) {
			if (worldEntities != null) {
				Iterator<Entity> iter = worldEntities.iterator();
				while (iter.hasNext()) {
					Entity e = iter.next();
					if (e instanceof EntityOtherPlayerMP) {
						if (Main.friendlyUsernames.contains(e.getName())) {
							RenderUtils.drawESP(event, e, 1f, 0, 255, 0);
						} else {
							RenderUtils.drawESP(event, e, 1f, 255, 0, 0);
						}
					}

					if (e instanceof EntityMob) {
						RenderUtils.drawESP(event, e, 1f, 255, 187, 0);
					}

					if (e instanceof EntityAnimal) {
						RenderUtils.drawESP(event, e, 1f, 0, 150, 255);
					}
				}
			}
		}
	}
}

 

RenderUtils.java

package prickles.insight.hud.utils;

import java.awt.Color;

import org.lwjgl.opengl.GL11;

import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.client.event.RenderWorldLastEvent;

public class RenderUtils {

		public static void drawESP(RenderWorldLastEvent evt, Entity e, float lineWidth, int r, int g, int b) {
		double eX = e.lastTickPosX + (e.posX - e.lastTickPosX) * (double) evt.getPartialTicks();
		double eY = e.lastTickPosY + (e.posY - e.lastTickPosY) * (double) evt.getPartialTicks();
		double eZ = e.lastTickPosZ + (e.posZ - e.lastTickPosZ) * (double) evt.getPartialTicks();

		Entity p = Minecraft.getMinecraft().getRenderViewEntity();

		double pX = p.lastTickPosX + (p.posX - p.lastTickPosX) * (double) evt.getPartialTicks();
		double pY = p.lastTickPosY + (p.posY - p.lastTickPosY) * (double) evt.getPartialTicks();
		double pZ = p.lastTickPosZ + (p.posZ - p.lastTickPosZ) * (double) evt.getPartialTicks();

		if (p.getDistanceSqToEntity(e) <= Minecraft.getMinecraft().gameSettings.renderDistanceChunks * 16) {
			Tessellator.getInstance().getBuffer().setTranslation(-pX, -pY, -pZ);
			renderESP(Tessellator.getInstance(), new Vec3d(eX, eY, eZ), new Vec3d(eX + 1, eY + 1, eZ + 1), r, g, b, lineWidth);
			Tessellator.getInstance().getBuffer().setTranslation(0, 0, 0);
		}
	}
	
	public static void BBP(BufferBuilder bufferBuilder, double x, double y, double z, Color c) {
		bufferBuilder.pos(x, y, z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).endVertex();;
	}
	
	public static void renderESP(Tessellator t, Vec3d posA, Vec3d posB, int r, int g, int b, float lineWidth) {
		GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
		GL11.glDisable(GL11.GL_CULL_FACE);
		GL11.glDisable(GL11.GL_LIGHTING);
		GL11.glDisable(GL11.GL_TEXTURE_2D);

		GL11.glEnable(GL11.GL_BLEND);
		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

		Color c = new Color(r, g, b, 255);
		GL11.glColor3d(r, g, b);
		GL11.glLineWidth(lineWidth);
		GL11.glDepthMask(false);
		Tessellator tessellator = t.getInstance();
		BufferBuilder bufferBuilder = tessellator.getBuffer();
		
		bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR);
		
		double dx = Math.abs(posA.x - posB.x);
		double dy = Math.abs(posA.y - posB.y);
		double dz = Math.abs(posA.z - posB.z);

		BBP(bufferBuilder, posA.x, posA.y, posA.z, c);
		BBP(bufferBuilder, posA.x, posA.y, posA.z + dz, c);

		BBP(bufferBuilder, posA.x, posA.y, posA.z + dz, c);
		BBP(bufferBuilder, posA.x + dx, posA.y, posA.z + dz, c);

		BBP(bufferBuilder, posA.x + dx, posA.y, posA.z + dz, c);
		BBP(bufferBuilder, posA.x + dx, posA.y, posA.z, c);

		BBP(bufferBuilder, posA.x + dx, posA.y, posA.z, c);
		BBP(bufferBuilder, posA.x, posA.y, posA.z, c);

		BBP(bufferBuilder, posA.x, posA.y + dy, posA.z, c);
		BBP(bufferBuilder, posA.x, posA.y + dy, posA.z + dz, c);

		BBP(bufferBuilder, posA.x, posA.y + dy, posA.z+dz, c);
		BBP(bufferBuilder, posA.x+dx, posA.y + dy, posA.z+dz, c);

		BBP(bufferBuilder, posA.x + dx, posA.y + dy, posA.z + dz, c);
		BBP(bufferBuilder, posA.x + dx, posA.y + dy, posA.z, c);

		BBP(bufferBuilder, posA.x + dx, posA.y + dy, posA.z, c);
		BBP(bufferBuilder, posA.x, posA.y + dy, posA.z, c);

		BBP(bufferBuilder, posA.x, posA.y, posA.z, c);
		BBP(bufferBuilder, posA.x, posA.y  +dy, posA.z, c);

		BBP(bufferBuilder, posA.x, posA.y, posA.z + dz, c);
		BBP(bufferBuilder, posA.x, posA.y + dy, posA.z + dz, c);

		BBP(bufferBuilder, posA.x + dx, posA.y, posA.z + dz, c);
		BBP(bufferBuilder, posA.x + dx, posA.y + dy, posA.z + dz, c);

		BBP(bufferBuilder, posA.x + dx, posA.y, posA.z, c);
		BBP(bufferBuilder, posA.x + dx, posA.y + dy, posA.z, c);

		tessellator.draw();      

		GL11.glDepthMask(true);
		GL11.glPopAttrib();
	}

}

This is just the way I'm drawing my boxes if it's necessary (Will be changed to look better)

 

As far as I know, I need the RenderWorldLastEvent as a parameter for my drawESP method to render my boxes

When I tried using Minecraft.getMinecraft().getRenderPartialTicks() instead, I would get this error:

Spoiler

java.lang.NullPointerException: Exception in server tick loop

 

Currently, with the above code, I get the following error:

Spoiler

java.util.ConcurrentModificationException: null
 at java.util.ArrayList$Itr.checkForComodification(Unknown Source) ~[?:1.8.0_151]
 at java.util.ArrayList$Itr.next(Unknown Source) ~[?:1.8.0_151]
 at prickles.insight.hud.HelmetHandler.render(HelmetHandler.java:53) ~[HelmetHandler.class:?]
 at net.minecraftforge.fml.common.eventhandler.ASMEventHandler_8_HelmetHandler_render_RenderWorldLastEvent.invoke(.dynamic) ~[?:?]
 at net.minecraftforge.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:90) ~[ASMEventHandler.class:?]
 at net.minecraftforge.fml.common.eventhandler.EventBus.post(EventBus.java:179) ~[EventBus.class:?]
 at net.minecraftforge.client.ForgeHooksClient.dispatchRenderLast(ForgeHooksClient.java:160) ~[ForgeHooksClient.class:?]
 at net.minecraft.client.renderer.EntityRenderer.renderWorldPass(EntityRenderer.java:1483) ~[EntityRenderer.class:?]
 at net.minecraft.client.renderer.EntityRenderer.renderWorld(EntityRenderer.java:1312) ~[EntityRenderer.class:?]
 at net.minecraft.client.renderer.EntityRenderer.updateCameraAndRender(EntityRenderer.java:1115) ~[EntityRenderer.class:?]
 at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1192) ~[Minecraft.class:?]
 at net.minecraft.client.Minecraft.run(Minecraft.java:436) [Minecraft.class:?]
 at net.minecraft.client.main.Main.main(Main.java:118) [Main.class:?]
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_151]
 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_151]
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_151]
 at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_151]
 at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.12.jar:?]
 at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.12.jar:?]
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_151]
 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_151]
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_151]
 at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_151]
 at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97) [start/:?]
 at GradleStart.main(GradleStart.java:26) [start/:?]

 

Any suggestions?

Edited by Prickles
Posted (edited)

Alright I fixed it (Pretty shameful errors)

Here's what I did

 

New HelmetHandler class:

package prickles.insight.hud;

import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import net.minecraft.client.entity.EntityOtherPlayerMP;
import net.minecraft.entity.Entity;
import net.minecraft.entity.monster.EntityMob;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import prickles.insight.hud.utils.RenderUtils;
import prickles.insightsq.core.Main;

public class HelmetHandler {

	public static boolean equipped;

	public static List<Entity> worldEntities;

	@SubscribeEvent
	public static void helmet(TickEvent.PlayerTickEvent event) {
		EntityPlayer p = event.player;

		if (p.inventory.armorItemInSlot(3).getItem() == Item.getItemById(314)) {
			equipped = true;
		} else {
			equipped = false;
		}

		if (Main.friendlyUsernames.contains(p.getName())) {
			Main.friendlyUsernames.remove(Arrays.binarySearch(Main.friendlyNamesArr, p.getName()));
		}
	}

	@SubscribeEvent
	public static void worldLoader(TickEvent.WorldTickEvent event) {
		worldEntities = event.world.loadedEntityList;
	}

	@SubscribeEvent
	public static void render(RenderWorldLastEvent event) {
		if (equipped) {
			if (worldEntities != null) {
				for (int i = 0; i < worldEntities.size(); i++) {
					Entity e = worldEntities.get(i);
					if (e instanceof EntityOtherPlayerMP) {
						if (Main.friendlyUsernames.contains(e.getName())) {
							RenderUtils.drawESP(event, e, 1f, 0, 255, 0);
						} else {
							RenderUtils.drawESP(event, e, 1f, 255, 0, 0);
						}
					}

					if (e instanceof EntityMob) {
						RenderUtils.drawESP(event, e, 1f, 255, 187, 0);
					}

					if (e instanceof EntityAnimal) {
						RenderUtils.drawESP(event, e, 1f, 0, 150, 255);
					}
				}
			}
		}
	}
}

 

 

Edited by Prickles
Posted

I don't think you need to handle the world tick event at all. You're just using that to reference the world entity list but you can just access that directly when you need it. I would get rid of the static worldEntities list field and forget the world tick handler.

 

You also probably don't need the player tick event either. The render event happens often enough (even more than the tick) so whether the player is wearing the helmet can be checked at the time of rendering, and the render event will only happen for the one player. So moving the player tick code to the render event will also help avoid the issues that diesieben07 is mentioning.

 

If you put everything into the render event then you shouldn't has as much issue with "reaching across the sides" or issue with syncrhonization between the time the other events fire for other players.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted (edited)

Okay, so would this be any better?:

@SubscribeEvent @SideOnly(Side.CLIENT)
	public static void helmet(RenderWorldLastEvent event) {
		Minecraft mc = Minecraft.getMinecraft();
		EntityPlayer p = (EntityPlayer) mc.player;
		List<Entity> entities = mc.world.loadedEntityList;
		
		if (Main.friendlyUsernames.contains(p.getName())) {
			Main.friendlyUsernames.remove(Arrays.binarySearch(Main.friendlyNamesArr, p.getName()));
		}

		if (p.inventory.armorItemInSlot(3).getItem() == Item.getItemById(314)) {
			equipped = true;
		} else {
			equipped = false;
		}

		if (equipped) {
			for (Entity e : entities) {
				if(!(e instanceof EntityLiving)) {
					continue;
				}
				
				if (e instanceof EntityOtherPlayerMP) {
					if (Main.friendlyUsernames.contains(e.getName())) {
						RenderUtils.drawESP(event, e, 2f, 0, 255, 0);
					} else {
						RenderUtils.drawESP(event, e, 2f, 255, 0, 0);
					}
				}

				if (e instanceof EntityMob) {
					RenderUtils.drawESP(event, e, 2f, 255, 187, 0);
				}

				if (e instanceof EntityAnimal) {
					RenderUtils.drawESP(event, e, 2f, 0, 150, 255);
				}
			}
		}
	}

 

Or would I need to use a packet system (IMessage example in the docs) and constantly get the server world and player to use instead of mc.player and mc.world?

Edited by Prickles
Posted

This is more of a private mod, so I just made a list of the usernames of my friends and I, and that whole thing with Arrays.binarySearch is to remove the player's username from that list so he doesn't draw a box on himself. I guess I should use UUIDs tho lol.

Any player not on that list gets a red esp and any player on it gets a green one. And I am using Arrays.asList

I totally forgot about needing to sort that list and remembered a simple substitute search method I made haha

Here's some new code:

Spoiler

Bottom of Main.java:


public static void initialize() {
		friendlyUUIDArr = new String[] {"57037bd92cdd4b588d91e2d683fa468f", "5f9ef67d87be4b16a711dab015f33bd0", "802e7296b7c746748dad0c9067d6a457", "32ddd1968dda4c799742c2ffa5efdfe0", "c71047eb7daa4a0db6bb899143d7b92c", "6ec6981095984f388fe26c9bd44866d3" };
		friendlyUUID.addAll(Arrays.asList(friendlyUUIDArr));
	}
	
	public static int search(String str, ArrayList<String> list) {
		for(int i = 0; i < list.size(); i++) {
			if(str.equals(list.get(i))) {
				return i;
			}
		}
		return 0;
	}

I know, the manual String[] input is messy but I'm lazy so it's staying lol

 

HelmetHandler#helmet:


@SubscribeEvent
	public static void helmet(RenderWorldLastEvent event) {
		Minecraft mc = Minecraft.getMinecraft();
		EntityPlayer p = (EntityPlayer) mc.player;
		List<Entity> entities = mc.world.loadedEntityList;
		
		if (Main.friendlyUUID.contains(p.getUniqueID().toString())) {
			Main.friendlyUUID.remove(Main.search(p.getUniqueID().toString(), Main.friendlyUUID));
		}

		if (p.inventory.armorItemInSlot(3).getItem() == Item.getItemById(314)) {
			equipped = true;
		} else {
			equipped = false;
		}

		if (equipped && esp) {
			for (Entity e : entities) {
				if(!(e instanceof EntityLiving)) {
					continue;
				}
				
				if (e instanceof EntityOtherPlayerMP) {
					if (Main.friendlyUUID.contains(e.getUniqueID().toString())) {
						RenderUtils.drawESP(event, e, 2f, 0, 255, 0);
					} else {
						RenderUtils.drawESP(event, e, 2f, 255, 0, 0);
					}
				}

				if (e instanceof EntityMob) {
					RenderUtils.drawESP(event, e, 2f, 255, 187, 0);
				}

				if (e instanceof EntityAnimal || e instanceof EntityAmbientCreature) {
					RenderUtils.drawESP(event, e, 2f, 0, 150, 255);
				}
			}
		}
	}

Esp is just a new boolean I added for toggling through chat commands

Equipped is just defined by whether or not the player is wearing a gold helmet

I need to access it because I have a class called RenderOverlayHandler that has a RenderGameOverlayEvent method that renders an overlay if the player is wearing said helmet:

Spoiler

package prickles.insight.hud;

import org.lwjgl.opengl.GL11;

import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import prickles.insightsq.core.Reference;

public class RenderOverlayHandler extends Gui {

	private final ResourceLocation hud = new ResourceLocation(Reference.MODID, "textures/gui/hud.png");

	public Minecraft mc;

	public int w;
	public int h;
	
	public static boolean ro = true;

	public RenderOverlayHandler(Minecraft mc) {
		this.mc = mc;
	}

	@SubscribeEvent
	public void renderOverlay(RenderGameOverlayEvent.Post event) {
		if (event.getType() == ElementType.HOTBAR && ro) {
			if (HelmetHandler.equipped) {

				GL11.glPushAttrib(GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_ENABLE_BIT);
				GL11.glEnable(GL11.GL_BLEND);
				GL11.glDepthMask(false);

				w = mc.displayWidth;
				h = mc.displayHeight;

				ScaledResolution sr = new ScaledResolution(mc);
				mc.renderEngine.bindTexture(hud);
				drawScaledCustomSizeModalRect(0, 0, 0, 0, w, h, sr.getScaledWidth(), sr.getScaledHeight(), w, h);

				GL11.glDisable(GL11.GL_BLEND);
				GL11.glDepthMask(true);
				GL11.glPopAttrib();
			}
		}
	}
}

 

I guess I could just combine the two classes but I don't think it would really make a difference

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.