Jump to content

Making a minimap


bkvaluemeal

Recommended Posts

I'm trying to understand how minimap mods actually work. I found the open source MapWriter and have browsed the source code for other popular minimaps, but what I can't seem to figure out is how they actually get the colors for the map. I've tried something like how the map item works (getting the color of the block I'm standing on and drawing a rectangle on screen with that integer), but nothing happened. Could someone explain this to me please?

 

This is what I've got so far, and you can see where I'd like to add the minimap. The zone your in (top left) will change based on a text file stored locally or on the server. When your armor's durability is less than 75%, a manikin type thing will appear in the bottom right.

 

width=800 height=450

ggm12Qc.jpg?1 [/img]

Link to comment
Share on other sites

At first I tried this:

 

IBlockState state = MC.theWorld.getBlockState(MC.thePlayer.getPosition());
int color = state.getBlock().getMapColor(state).colorValue;
drawRect(0, 0, 100, 100, color);

 

That didn't work. So then I found a thread talking about getting the textures from the jar like so:

 

MC.getTextureManager().bindTexture(new ResourceLocation("textures/blocks/grass_side.png"));
drawModalRectWithCustomSizedTexture(0, 0, 0, 0, 64, 64, 64, 64);

 

This does work, and I could get the RGB values like this:

 

static int[] loadTexture(String block)
{
try
{
	final ResourceLocation resourceLocation = new ResourceLocation("textures/blocks/" + block + ".png");
	final IResourceManager resourceManager = Minecraft.getMinecraft().getResourceManager();
	final IResource resource = resourceManager.getResource(resourceLocation);
	final InputStream in = resource.getInputStream();
	final BufferedImage image = ImageIO.read(in);
	return image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth());
}
catch (Exception e)
{

}
return null;
}

 

My thought now is to cache all the block colors found in Minecraft, but what do I do about custom blocks added by a mod? Is it possible to iterate through the textures in their jar?

Link to comment
Share on other sites

Cool, that works too.

 

IBlockState state = MC.theWorld.getBlockState(MC.thePlayer.getPosition());
int color = 0xFF000000 | state.getBlock().getMapColor(state).colorValue;
drawRect(50, 50, 100, 100, color);

 

Although, it's not the level of detail I was looking for. It swaps between black and the actual color for whatever reason. Xaero's map mod doesn't work like this, right?

Link to comment
Share on other sites

Well, no, but what I'm saying is that Xaero's map, for instance, looks nothing like the item you can craft in game. It is much more detailed. I don't think the getMapColor() function has the ability to yield that level of detail. So, how do they do it?

 

I'll play around with the getMapColor() function and see what I get. I'll post that when I'm done.

Link to comment
Share on other sites

GetMapColor() returns a predefined color (one of 16, IIRC although there are some duplicates).  The more advanced maps go "this color is useless" and examine the block's actual texture and make a "best guess" average color for the block.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

Right, my question is how do they get that texture? The default Minecraft blocks are easy enough, but how do you grab the textures of custom blocks?

 

Edit:

Let me clarify, I can use the loadTexture() function I mentioned before only if I know where the resource location is, correct? I will assume I don't know that. Some modder may decide not to follow convention. I can't seem to find a way to pull a texture from an arbitrary block.

Link to comment
Share on other sites

This works, but I get tons of errors. What is the right way to do this? I really don't even want to use the getMapColor() function because it flickers between black and green. I don't know why.

 

public class MiniMapHandler
{
private static final Minecraft MC = Minecraft.getMinecraft();
private static final BufferedImage MAP = new BufferedImage(75, 75, BufferedImage.TYPE_INT_RGB);
private static DynamicTexture TEXTURE = new DynamicTexture(MAP);

@SubscribeEvent
public void onTick(PlayerTickEvent event)
{
	// (Y, X) They're swapped. Don't feel like retyping.
	BlockPos zero_zero = MC.thePlayer.getPosition();
	BlockPos one_zero = MC.thePlayer.getPosition().north();
	BlockPos n_one_zero = MC.thePlayer.getPosition().south();
	BlockPos zero_one = MC.thePlayer.getPosition().east();
	BlockPos zero_n_one = MC.thePlayer.getPosition().west();

	IBlockState state_zero_zero = MC.theWorld.getBlockState(zero_zero);
	IBlockState state_one_zero = MC.theWorld.getBlockState(one_zero);
	IBlockState state_n_one_zero = MC.theWorld.getBlockState(n_one_zero);
	IBlockState state_zero_one = MC.theWorld.getBlockState(zero_one);
	IBlockState state_zero_n_one = MC.theWorld.getBlockState(zero_n_one);

	int color_zero_zero = state_zero_zero.getBlock().getMapColor(state_zero_zero).colorValue;
	int color_one_zero = state_one_zero.getBlock().getMapColor(state_one_zero).colorValue;
	int color_n_one_zero = state_n_one_zero.getBlock().getMapColor(state_n_one_zero).colorValue;
	int color_zero_one = state_zero_one.getBlock().getMapColor(state_zero_one).colorValue;
	int color_zero_n_one = state_zero_n_one.getBlock().getMapColor(state_zero_n_one).colorValue;

	MAP.setRGB(37, 37, color_zero_zero);
	MAP.setRGB(37, 38, color_one_zero);
	MAP.setRGB(37, 36, color_n_one_zero);
	MAP.setRGB(38, 37, color_zero_one);
	MAP.setRGB(36, 37, color_zero_n_one);

	TEXTURE = new DynamicTexture(MAP);
}

public static ResourceLocation getTexture()
{
	return MC.getTextureManager().getDynamicTextureLocation("minimap", TEXTURE);
}
}

 

Inside onRenderGui(RenderGameOverlayEvent event):

MC.getTextureManager().bindTexture(MiniMapHandler.getTexture());
drawModalRectWithCustomSizedTexture(MC.displayWidth / 2 - 78, 13, 0, 0, 75, 75, 75, 75);

Link to comment
Share on other sites

I knew that creating this wasn't going to be easy, but this is a lot of work! With The Division launching soon, I honestly don't think I'll be working on this much longer. I've opted to use getMapColor() (despite what I said) in lieu of starting a huge project. I have created a much better way to draw the map, although is there a way to update the DynamicTexture without making a new one every time? My game starts to lag after a while and updateDynamicTexture() doesn't seem to do the trick.

 

MiniMapHandler:

public class MiniMapHandler
{
   private static final Minecraft MC = Minecraft.getMinecraft();
   public static final BufferedImage MAP = new BufferedImage(75, 75, BufferedImage.TYPE_INT_RGB);

   @SubscribeEvent
   public void onTick(PlayerTickEvent event)
   {
      BlockPos center = MC.thePlayer.getPosition();

      for (int z = center.getZ() - 37; z < center.getZ() + 38; z++)
      {
         for (int x = center.getX() - 37; x < center.getX() + 38; x++)
         {
            IBlockState state = MC.theWorld.getBlockState(new BlockPos(x, center.getY(), z));
            int color = state.getBlock().getMapColor(state).colorValue;

            MAP.setRGB(x - center.getX() + 37, z - center.getZ() + 37, color);
         }
      }
   }
}

 

Inside onRenderGui(RenderGameOverlayEvent event):

TEXTURE = new DynamicTexture(MiniMapHandler.MAP);
MC.getTextureManager().bindTexture(MC.getTextureManager().getDynamicTextureLocation("minimap", TEXTURE));
drawModalRectWithCustomSizedTexture(MC.displayWidth / 2 - 78, 13, 0, 0, 75, 75, 75, 75);

 

The map reminds me of NetHack...

 

8rNdJ8G.jpg

Link to comment
Share on other sites

While using the player's current Y position seems like a logical choice, that map is utterly worthless to me, as a player.  In looking at it and looking at what's in front of the player in that screenshot, I have literally no idea where I am or what direction I'm facing.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

That's true. Haha! Could you suggest a way to get the topmost block or perhaps a better way to draw the map without crashing my client? I'm most concerned about the latter.

 

Edit:

I made the map look better. It checks blocks above and below the player.

 

public class MiniMapHandler
{
private static final Minecraft MC = Minecraft.getMinecraft();
public static final BufferedImage MAP = new BufferedImage(75, 75, BufferedImage.TYPE_INT_RGB);

@SubscribeEvent
public void onTick(PlayerTickEvent event)
{
	BlockPos center = MC.thePlayer.getPosition();
	MAP.flush();

	for (int z = center.getZ() - 37; z < center.getZ() + 38; z++)
	{
		for (int x = center.getX() - 37; x < center.getX() + 38; x++)
		{
			for (int y = center.getY() + 10; y > center.getY() - 10; y--)
			{
				BlockPos pos = new BlockPos(x, y, z);
				IBlockState state = MC.theWorld.getBlockState(pos);

				if (!state.getBlock().isAir(MC.theWorld.init(), pos))
				{
					int color = state.getBlock().getMapColor(state).colorValue;

					MAP.setRGB(x - center.getX() + 37, z - center.getZ() + 37, color);

					break;
				}
			}
		}
	}

	MAP.setRGB(37, 37, 0xFFFFFF);
}
}

 

855QFDc.png

Link to comment
Share on other sites

If it crashes, include the line that it crashes at.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

No, it "crashes" because Java's memory fills up and the server shuts down. I get messages saying the server jumped ahead X number of ticks. I'm not handling the dynamic textures properly. I don't exactly know how other than to create a new one and load it.

Link to comment
Share on other sites

That's because you're creating 118125 BlockPos objects and 118125 IBlockState references every tick, all of which need to be garbage collected.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

Would probably help if...

 

1) Didn't use MAP.flush();

2) Didn't check for changes every tick (seriously, scanning 118125 blocks every tick is dumb)

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

You still don't need MAP.flush()

 

You may as well think of it as MAP.garbageCollect(), the method exists to mark the memory it uses as free, but you're using it to reset the colors.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

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.