What area would I see the Rotation value in (Notice each head is a different angle slightly).
I"m asking all this because, while there is a tool that exist to "convert" worlds, it felt clunky, and relied on NEI Dumps in specific formats. (mIDas and mIDas gold I believe).
My friend and I would like to create a modpack world migration toolkit and your API (as a base for loading/saving/editing the world) seems like the best choice.
For loading, saving, and editing world files:
We looked at Craft.Net (Using the Craft.Net.Anvil)
We looked at fNBT
We looked at the source MOJANG posted for the NBT format (The converter from alpha to Region in Java code)
We looked at mIDas
We then found your Substrate and NBT Explorer.
We made the furthest progress in proof of concept with your API.
Substrate was purpose-built for third party world editing. Everything else is either wrapped up in a larger project, or only tackles the lower-level NBT layers. Though due to the way Minecraft has evolved, certain parts of the API have fallen out of date.
The rotation value of heads is stored in the block's data field. You're already printing it in your code snippet. It ranges 0-15, each increment represents 22 degrees to give you 360-degree coverage. blocks.SetData(x, y, z, rotation);
Hmm, so am I seeing only data=1 because of some sort of conversion issue? There are enough heads at different angles I would have expected to see 6 or 7 different values. I only see Data=1 a bunch of times, and a single time it printed Data=5. I tested it with carpet and got 0,1,2,3,4,5,6 etc so that seems to be as expected for different types of carpet.
With respect to the API falling out of date, are there issues we can fork and assist with to get it up to date? Again, your API seems to be the best we've found so far.
Looks like I was actually wrong on the heads: http://minecraft.gamepedia.com/Data_values#Heads
The data values are like torch data values. They determine whether it's affixed to a wall, or on the floor. You saw a 5 because you (accidentally?) stuck one on a wall.
For the API, there's certain parts that I've stopped adding to, like Entities and TileEntities. I used to create classes for each one and bind properties to all the tags. The problem is Mojang adds these pretty frequently, and they also change them from time to time. Manipulating the NBT tree is less convenient, but more adaptable.
If there's a part of the API that you think needs to be improved, you are certainly welcome to submit pull requests. I usually get to them in a timely manner.
@jaquadro (sorry for the delay in responding - see previous email in Mid Feb)
I am having problems in OpenWorld->LoadLevel(). It is getting as far as:
public virtual Level LoadTreeSafe (TagNode tree)
{
if (!ValidateTree(tree)) {
return null;
}
return LoadTree(tree);
}
but then failing to validate the tree (the failure is in the NbtVerifier.Verify() method. Works fine for 1.62 but fails for a newly created world with no changes.
It gets to the following line in VerifyCompound(..)
pass = Verify(tag, value, node) && pass;
iterates through successfully a few times, then pass goes false on the node "AttackTime" as the value is null.
If the chunks are modified, then save them. Modified chunks are always held in memory. Otherwise, it maintains a certain amount of chunks in an LRU cache (something like 256 ... it's configurable). Once the cache is full, unmodified chunks will start being let go.
I save each chunk after it's generated, but a copy of each region file seems to stay in memory.
Here's a copy of my mapgen function, with lots of placeholder variables before I get a proper config system/gui in place. Is there more I need to do? It seems to be keeping every instance of RegionFile, and the amount of memory taken up is more or less the size of the resulting region folder.
(incidentally, this takes about 4 hours to run. Yay light calculations on huge maps)
public void simpleWriteTest()
{
currentWorld = AnvilWorld.Create("C:\\Users\\Japa\\AppData\\Roaming\\.minecraft\\saves\\testing\\");
currentDwarfMap = new DwarfWorldMap();
currentDwarfMap.loadElevationMap("D:\\DwarfFortress\\df_34_11_win\\world_graphic-el-region2-250-15510.bmp");
currentDwarfMap.loadWaterMap("D:\\DwarfFortress\\df_34_11_win\\world_graphic-elw-region2-250-15510.bmp");
currentDwarfMap.loadBiomeMap("D:\\DwarfFortress\\df_34_11_win\\world_graphic-bm-region2-250-15510.bmp");
IChunkManager cm = currentWorld.GetChunkManager();
// We can set different world parameters
currentWorld.Level.LevelName = "Flatlands";
currentWorld.Level.Spawn = new SpawnPoint(20, 255, 20);
currentWorld.Level.GameType = GameType.CREATIVE;
currentWorld.Level.AllowCommands = true;
int cropWidth = 2064;
int cropHeight = 2064;
borderWest = 0;
borderEast = borderWest + cropWidth;
borderNorth = 0;
borderSouth = borderNorth + cropHeight;
//FIXME get rid of this junk
Settings.Default.tilesPerRegionTile = 8;
Settings.Default.mapCenterX = (borderWest + borderEast) / 2;
Settings.Default.mapCenterY = (borderNorth + borderSouth) / 2;
//We have to split up the area we're working on into chunks.
//We use X and Y because minecraft's coordinate system is just retarded.
int chunkStartX = ((borderWest - Settings.Default.mapCenterX) * Settings.Default.tilesPerRegionTile) / 16;
int chunkStartY = ((borderNorth - Settings.Default.mapCenterY) * Settings.Default.tilesPerRegionTile) / 16;
int chunkFinishX = ((borderEast - Settings.Default.mapCenterX) * Settings.Default.tilesPerRegionTile) / 16;
int chunkFinishY = ((borderSouth - Settings.Default.mapCenterY) * Settings.Default.tilesPerRegionTile) / 16;
//int xmin = -20;
//int xmax = 20;
//int zmin = -20;
//int zmaz = 20;
// We'll create chunks at chunk coordinates xmin,zmin to xmax,zmax
Console.WriteLine("Starting conversion now.");
Stopwatch watch = Stopwatch.StartNew();
for (int xi = chunkStartX; xi < chunkFinishX; xi++)
{
for (int zi = chunkStartY; zi < chunkFinishY; zi++)
{
// This line will create a default empty chunk, and create a
// backing region file if necessary (which will immediately be
// written to disk)
ChunkRef chunk = cm.CreateChunk(xi, zi);
// This will make sure all the necessary things like trees and
// ores are generated for us.
chunk.IsTerrainPopulated = false;
// Auto light recalculation is horrifically bad for creating
// chunks from scratch, because we're placing thousands
// of blocks. Turn it off.
chunk.Blocks.AutoLight = false;
double xMin = ((xi * 16.0 / (double)Settings.Default.tilesPerRegionTile) + Settings.Default.mapCenterX);
double xMax = (((xi + 1) * 16.0 / (double)Settings.Default.tilesPerRegionTile) + Settings.Default.mapCenterX);
double yMin = ((zi * 16.0 / (double)Settings.Default.tilesPerRegionTile) + Settings.Default.mapCenterY);
double yMax = (((zi + 1) * 16.0 / (double)Settings.Default.tilesPerRegionTile) + Settings.Default.mapCenterY);
// Make the terrain
HeightMapChunk(chunk, xMin, xMax, yMin, yMax);
// Reset and rebuild the lighting for the entire chunk at once
chunk.Blocks.RebuildHeightMap();
chunk.Blocks.RebuildBlockLight();
chunk.Blocks.RebuildSkyLight();
// Save the chunk to disk so it doesn't hang around in RAM
cm.Save();
}
TimeSpan elapsedTime = watch.Elapsed;
int finished = xi - chunkStartX + 1;
int left = chunkFinishX - xi - 1;
TimeSpan remainingTime = TimeSpan.FromTicks(elapsedTime.Ticks / finished * left);
Console.WriteLine("Built Chunk Row {0} of {1}. {2}:{3}:{4} elapsed, {5}:{6}:{7} remaining.",
finished, chunkFinishX - chunkStartX,
elapsedTime.Hours, elapsedTime.Minutes, elapsedTime.Seconds,
remainingTime.Hours, remainingTime.Minutes, remainingTime.Seconds);
maxHeight = -9999;
minHeight = 9999;
}
// Save all remaining data (including a default level.dat)
// If we didn't save chunks earlier, they would be saved here
currentWorld.Save();
}
I should just nix all the validation. It has no place in modern Minecraft. Most of that was designed back when we 8 mobs, a few tile entities, and a very spartan level file. Things got considerably more complicated in three years.
With all the things I maintain now I haven't done much with Substrate in the last year. There's still a good core, it just has a lot of legacy cruft that should be removed at this point. If anyone's interested in contributing to the project let me know.
Hi jaquadro, im making a better version of NBTEdit named NBT++ and it implements substrate. I need a way to get NBT Values in a file. How can i do this?
Isn't that what NBTExplorer already is? A better version of NBTEdit? All the source is available. It's linked in the OP. You're free to go through it.
Using NBTExplorer I see two issues with player values:
AttackTime isn't present in my saves, so I marked in optional
Health is a float in my saves, but Substrate expects a short
Then there's a larger issue with the player inventory, in that the "id" is a string type in my save but Substrate expects an int. I could work up a map of all the item names to IDs (expected 1, got "minecraft:stone"). (see: http://minecraft-ids.grahamedgecombe.com/)
I don't need inventory for my purposes, so I'm just not processing the player info. Once I get something working I'll see about a pull request.
The AttackTime and Health have already been fixed on master of the Substrate repo on github. I was using the 1.3.8 download of Substrate when I encountered those errors. Still, master expects TAG_SHORT for the item 'id', which now appears to be a string. Easy workaround: empty your inventory before saving and it bypasses that validation errors.
The higher-level APIs in Substrate have unfortunately fallen out of date and into disrepair. Creating high-level classes to expose NBT data as direct properties was ultimately a misguided effort that assumed Minecraft would only keep adding to what already existed. Instead, NBT data has changed pretty radically across versions. A lot of work and complexity would need to go into those abstractions to fulfill their mission of providing a version-agnostic interface to data.
The lower-level APIs for managing NBT, chunks, and worlds is still useful and current.
For standard minecraft, all IDs >255 are items.
Mods I Develop: Garden Stuff -- Storage Drawers -- Hunger Strike
Tools I Develop: NBTExplorer -- Substrate
What area would I see the Rotation value in (Notice each head is a different angle slightly).
I"m asking all this because, while there is a tool that exist to "convert" worlds, it felt clunky, and relied on NEI Dumps in specific formats. (mIDas and mIDas gold I believe).
My friend and I would like to create a modpack world migration toolkit and your API (as a base for loading/saving/editing the world) seems like the best choice.
For loading, saving, and editing world files:
We made the furthest progress in proof of concept with your API.
The rotation value of heads is stored in the block's data field. You're already printing it in your code snippet. It ranges 0-15, each increment represents 22 degrees to give you 360-degree coverage. blocks.SetData(x, y, z, rotation);
Mods I Develop: Garden Stuff -- Storage Drawers -- Hunger Strike
Tools I Develop: NBTExplorer -- Substrate
With respect to the API falling out of date, are there issues we can fork and assist with to get it up to date? Again, your API seems to be the best we've found so far.
The data values are like torch data values. They determine whether it's affixed to a wall, or on the floor. You saw a 5 because you (accidentally?) stuck one on a wall.
http://minecraft.gamepedia.com/Chunk_format#Tile_Entity_Format
The skull TileEntity has a "Rot" flag. The values range from 0-15, and they are identical to the sign data values in their meaning.
For the API, there's certain parts that I've stopped adding to, like Entities and TileEntities. I used to create classes for each one and bind properties to all the tags. The problem is Mojang adds these pretty frequently, and they also change them from time to time. Manipulating the NBT tree is less convenient, but more adaptable.
If there's a part of the API that you think needs to be improved, you are certainly welcome to submit pull requests. I usually get to them in a timely manner.
Mods I Develop: Garden Stuff -- Storage Drawers -- Hunger Strike
Tools I Develop: NBTExplorer -- Substrate
I am having problems in OpenWorld->LoadLevel(). It is getting as far as:
public virtual Level LoadTreeSafe (TagNode tree)
{
if (!ValidateTree(tree)) {
return null;
}
return LoadTree(tree);
}
but then failing to validate the tree (the failure is in the NbtVerifier.Verify() method. Works fine for 1.62 but fails for a newly created world with no changes.
It gets to the following line in VerifyCompound(..)
pass = Verify(tag, value, node) && pass;
iterates through successfully a few times, then pass goes false on the node "AttackTime" as the value is null.
I'm making a large scale map generator, but right now it keeps all region files in memory, and ends up into the multi gigabytes.
Yes, I am making huge maps.
Mods I Develop: Garden Stuff -- Storage Drawers -- Hunger Strike
Tools I Develop: NBTExplorer -- Substrate
Here's a copy of my mapgen function, with lots of placeholder variables before I get a proper config system/gui in place. Is there more I need to do? It seems to be keeping every instance of RegionFile, and the amount of memory taken up is more or less the size of the resulting region folder.
(incidentally, this takes about 4 hours to run. Yay light calculations on huge maps)
I should just nix all the validation. It has no place in modern Minecraft. Most of that was designed back when we 8 mobs, a few tile entities, and a very spartan level file. Things got considerably more complicated in three years.
Mods I Develop: Garden Stuff -- Storage Drawers -- Hunger Strike
Tools I Develop: NBTExplorer -- Substrate
Mods I Develop: Garden Stuff -- Storage Drawers -- Hunger Strike
Tools I Develop: NBTExplorer -- Substrate
Also, you can add my project to the list of things that use substrate.
http://www.bay12forums.com/smf/index.php?topic=138366.0
Isn't that what NBTExplorer already is? A better version of NBTEdit? All the source is available. It's linked in the OP. You're free to go through it.
Mods I Develop: Garden Stuff -- Storage Drawers -- Hunger Strike
Tools I Develop: NBTExplorer -- Substrate
It's probably a 1.8 thing and the class needs updating.
Mods I Develop: Garden Stuff -- Storage Drawers -- Hunger Strike
Tools I Develop: NBTExplorer -- Substrate
Properties that were once part of Minecraft but no longer are.
Mods I Develop: Garden Stuff -- Storage Drawers -- Hunger Strike
Tools I Develop: NBTExplorer -- Substrate
I am trying to load a world but I can't get past the spot where you open it. It always gives me the error "Failed to load 'level.dat'"
The code I am using.
I'm also getting that error. I set up debugging (see: http://unityvs.com/documentation/dll-debugging/) and found a few issues with the maps coming out of MC 1.10.
Using NBTExplorer I see two issues with player values:
Then there's a larger issue with the player inventory, in that the "id" is a string type in my save but Substrate expects an int. I could work up a map of all the item names to IDs (expected 1, got "minecraft:stone"). (see: http://minecraft-ids.grahamedgecombe.com/)
I don't need inventory for my purposes, so I'm just not processing the player info. Once I get something working I'll see about a pull request.
The AttackTime and Health have already been fixed on master of the Substrate repo on github. I was using the 1.3.8 download of Substrate when I encountered those errors. Still, master expects TAG_SHORT for the item 'id', which now appears to be a string. Easy workaround: empty your inventory before saving and it bypasses that validation errors.
I'm working on a lookup table (string to int) based on the info here: http://www.minecraftinfo.com/idlist.htm
If anyone has a more up-to-date list I'd appreciate the link!
The higher-level APIs in Substrate have unfortunately fallen out of date and into disrepair. Creating high-level classes to expose NBT data as direct properties was ultimately a misguided effort that assumed Minecraft would only keep adding to what already existed. Instead, NBT data has changed pretty radically across versions. A lot of work and complexity would need to go into those abstractions to fulfill their mission of providing a version-agnostic interface to data.
The lower-level APIs for managing NBT, chunks, and worlds is still useful and current.
Mods I Develop: Garden Stuff -- Storage Drawers -- Hunger Strike
Tools I Develop: NBTExplorer -- Substrate