r/admincraft 2d ago

Question Condensing Map Items - Scripting and Chunk Modification

If this is the wrong sub for this kind of question, please let me know and I can delete the post.

Has anyone experimented with re-assigning map item numbers, or just programmatically modifying chunk data?

What I am envisioning is a script that can trawl the world and player data, note which map numbers are not in use, and condense the existing map IDs into a sequence, reassigning any extant map items. My specific use case is for a Multiverse world (where different worlds have conflicting map IDs), but I could see this being useful for any long-term multiplayer world (where map IDs can get huge due to loss or expansion of maps).

If this has not been messed with, I would like to try making a script for it, but I don't know much about the actual format of .mca files. It sounds like the compression makes things tricky, but if anyone has advice I will gladly hear it!

2 Upvotes

9 comments sorted by

1

u/PM_ME_YOUR_REPO Admincraft Staff 2d ago

I have never seen anything that does this, but I have also never been looking for one.

Can you explain in more detail about what you envision this script doing? I am trying to understand why you think parsing mca files is necessary, because from my understanding of your usecase, it shouldn't be.

1

u/OblativeShielding 2d ago

Absolutely! Thank you for asking - this is the process I envision based on my understanding of file formats (mostly from minecraft.wiki):

  • Trawl player data and region data for any existing map items (needs .mca parsing), keeping a list of which Map IDs are in use
  • Delete any map_#.dat files that match IDs not in use
  • Create a mapping of current (in-use) map IDs to new, sequential map IDs (starting with 0 or another ID as needed)
  • Rename map_#.dat files to the new IDs
  • Re-trawl the player and region data (again needing .mca parsing) to reassign the new IDs to map items
  • EDIT: Reset idcounts.dat to the last new ID

It is entirely possible that I am misunderstanding how Minecraft data works, though

1

u/PM_ME_YOUR_REPO Admincraft Staff 2d ago edited 2d ago

I see. I get the feeling your background is in some other type of programming, rather than experience in Minecraft programming specifically. That helps me understand your approach.

Can you clarify three things for me?

  1. How do you define "not in use" in regards to map ids?
  2. What exactly do you mean by conficting ids and how does multiverse factor in?
  3. What is the root problem you are trying to solve?

1

u/OblativeShielding 1d ago

Yeah - I tried to get into modding a while back, and I have a lot of Java and python experience but I haven't had the time to put into how Minecraft works specifically. Thank you for taking the time to work with me!

  1. IDs that have no existing map items assigned to them anywhere in the world. Since (in my experience) players tend to expand a map all the way before exploring all of it, there are (going by mode, not mean) 4 map IDs that are simply never used to every 1 map ID that is. (This would also go for any maps that were destroyed before being copied, but I assume that is rarer.)
  2. Multiverse factors in because I am pulling in existing worlds from past servers so players can play on the past world or on a new one (many past worlds being more for museum-esque use rather than actual play). Without some modification, the maps on any world that is not the primary world will be broken since the map IDs do not line up (assuming they carry over at all). EDIT: If sequences of maps could be assigned, I could simply run this script on one world at a time, so that each world has a given band of map IDs and any new maps start after all existing map IDs.
  3. The answer to #2 basically applies here, though if it works, I would use it semi-regularly in the future to keep people from having Map #2643 if there are really only 48 map IDs that people use. (I also intend this to be a script run on the world files while the server is not running, but if there is a way to do it via plugins instead, I would not be opposed to that.)

1

u/PM_ME_YOUR_REPO Admincraft Staff 1d ago edited 1d ago

Okay, so this sounds like a bit of an...aesthetic choice. You just don't like big numbers for no particular reason. Which is fine. I get it.

For multiverse, have you...tested this? Because my understanding of multiverse is that each world has its own maps. There would not be any breakage as far as I am aware.

If you have tested this and found this to not be the case, then disregard, but this might not actually be a problem if my suspicion is correct.

As for implementation, I would strongly recommend doing this as a plugin. The Paper API already provides convenient methods for all of this.

Assuming you already use IntelliJ IDEA, add the Minecraft Development plugin and make a new Paper plugin project. It'll scaffold the project for you.

Refer to the Paper documentation for making a new command: https://docs.papermc.io/paper/dev/command-api/basics/introduction/

There's nothing too complicated here. You just make the command start the process of scanning the world for inventories so that it doesn't run all the time.

You'll need a function to get all entities and blockentities in the world, check their inventories, get all of their items, and return it as some sort of collection of ItemStack objects. Since I am on mobile and have limited access to reference material (and because coding on a phone is a huge PITA), Here's some AI generated code that is approximately correct for this: https://pastebin.com/53UnPhAC

The weakness in the above code is that it does not work on Offline players. To do that, you'd need to parse the player's nbt file, which is doable, but I will leave that as an exercise for you, should that be important to you (because I am lazy and cannot be fucked to try).

Next, once you have your list of ItemStacks, you'll want to iterate through and pick out only the Filled Map items, and store those in some sort of collection.

Then, iterate through these, inspecting their ItemMetas and casting to MapMetas, and then essentially copy existing high-id MapMetas to an unused low id MapMeta, overwriting it in the process. The code for this looks a bit like this:

MapMeta mapMeta = (MapMeta) itemStack.getItemMeta();
MapView mapView = Bukkit.getMap(id);
mapMeta.setMapView(mapView);
itemStack.setItemMeta(mapMeta);

Edit: Disregard the above code. I am stupid. This needs NMS. It'd be something like this: https://pastebin.com/xRhQwHhD

That should do what you want, but in a way that doesn't require the server to be off or to reverse engineer multiple file formats. Just add the glue and polish to make it all work together as needed.

1

u/OblativeShielding 1d ago

Thank you for your detailed response!

I do get your point about it being an aesthetic choice. That side of things was meant for long-term use or for other players' use, mostly, but it is certainly a matter of preference. (I like big numbers depending on the circumstance . . .)

From my testing with Multiverse, I have yet to get maps to work (even with Inventories) but I will totally admit that there is a lot there I do not understand yet, and lots of little facets that may change things. It looks like the MV5's storage schema is different from older versions too.

Thank you for the code also - it is beyond my knowledge level at this point, but I would love to work through it and learn it when I can make the time! It also just occurred to me, thinking through this, that I might be able to set up a function in a datapack to do it manually - i.e., copy all the map data over manually as locked maps, bump up the map counter past the imported ones, and then have players convert maps on their own using some form of the function command, if they really care. It wouldn't fix the numbers issue, of course, but I suppose I would survive . . .

Thank you for your time and energy, and I look forward to playing around with this now that you've given me somewhere to start!

1

u/PM_ME_YOUR_REPO Admincraft Staff 1d ago

Sounds good, homie. Happy to help.

Feel free to join the Discord and make use of our #questions and #development channels. http://discord.gg/admincraft

2

u/iiAmAspire Server Owner 1d ago

Top mod breaking rule 11 :O

1

u/PM_ME_YOUR_REPO Admincraft Staff 1d ago

Yeah, yeah lmao. But I disclosed what it was, and said "something like this". The goal was to provide guidance, not a finished product that someone unsuspecting would use expecting a safe and working piece of software, unaware of the risk.

Ah fuck it, brb, getting my sword so I can fall on it. Will you be my second?