- Fix: Bug in index calculations of Anvil composite byte/nibble arrays, causing incorrect block updates.
- Block updates for Minecraft 1.4.
- Minor changes to RegionFile to make it easier to extend (e.g. for Cubic Chunks).
I believe the latest Substrate code in source control does have a TileEntityControl object that exposes that. You'd get the TileEntity object for that block and cast it.
In general, whenever you need to modify a property that is not exposed by a specific object (in this case a specific TileEntity), you can still access that object's NbtTree and set the raw data. A bit like using NBTExplorer or NBTedit, but with code.
I might have missed it, but is there an easy way to access the raw TagNodeCompound reference for a given TileEntity? I'm writing a program that has to deal with blocks introduced by mods, and I'd like to design for forward compatibility, which means I need to be able to get the Tile entity's data regardless of whether it is a recognized TileEntity type or not.
If not, I have a pair of functions that add said functionality I'd be happy to contribute.
Seems the answer is yes and no. TileEntity has a "Source" property that returns a raw compound, but for some reason I decided to make it protected. It should really be public.
There is a minor caveat however. When you save the TileEntity (via a BuildTree call), a new tree will be built from all the values defined by the schema of the particular TileEntity type, and then the "Source" compound will be merged into that tree. Any values already in the tree will take precedence. If you want to handle all types in a consistently general-purpose way, you'll need to add or change something. In retrospect, I did not architect that very well.
Actually, I only need read access. I'm working on a top-down map exporter, and one of the key points in it is mod support. For that, I need to be able to access some of the NBT structures, e.g. for things like Railcraft or Buildcraft where they store the block type in the TileEntity instead of the Metadata nybble.
And yes, I noticed that Source was protected. I, ah, may have dented my desk when I first saw that
You've probably already gone ahead and made changes, but I've just pushed an update to master exposing a Source property in a handful of INbtObject base classes.
Yeah, I'll be pulling. I think there's one other change I need made (I'll double check), but if so I'll fork and make it, then send you a pull request with the changes.
The whole point of asking about this was specifically because I dont' want to get stuck on a custom-modified version of Substrate
Submitted a pull request with the other changes required, which allows the user to specify whether to return a TileEntity object as a fallback if there is no registered TileEntity-derived class.
It's implemented as an overload with a boolean parameter, so the change should not be breaking for any existing projects using Substrate.
The Meaning of Life, the Universe, and Everything.
Join Date:
7/3/2011
Posts:
54
Member Details
Hello. I just found this tool, and it looks amazing! I was hoping for a bit of advice on a project that I have started, and wanted your opinion on whether you think that this tool is a good choice for the job.
I am writing a program that takes GIS elevation data and transforms it into a Minecraft map. Once this is finished, I want to add hydrography, roads, ground cover, etc.. all from the standard file formats that are freely available on most U.S. state's websites and the USGS.
My first thought was to just write the code to create the map files myself, but while searching for background data, I found this tool. Any opinions/advice would be greatly appreciated.
This should be fine for you. It should be as easy as using the BlockManager to set blocks and data values, and the SDK will take care of managing all the chunks, regions, lighting calculation, etc. You should download it directly from source though, the built assembly is a little out of date right now.
Version 1.3.7 is available. It's mainly an accumulation of fixes over the last few months, and a few small additions to the API.
- Fix: Wrong tag name for additional block IDs ("AddBlocks" instead of "Add")
- Fix: Anvil worlds can now handle block IDs >255
- Fix: Empty chunk sections below heightmap were not written
- Fix: NBT Tree discarding root node name on load
- Fix: Various Entity and TileEntity issues
- Raw NBT tree exposed on more objects (Entities, TileEntities, Items...)
- Generic TileEntity objects will be created if specific types are unknown
- Region files multithread safe
- MobSpawnerTileEntities have updated data fields
Several of these fixes and improvements were provided by other members of the community, so thank you for the contributions and bug reports!
Did you call save on the level? Have you verified an actual change in the data with either Substrate or NBTExplorer?
As for abilities, I think they're mostly ignored by MC unless the correct gametype is specified. Even then I don't know how or if they are all honored.
Thanks for Substrate... I ran into a need to report out the text and location my signs as a way to keep track of where my stuff is, and I couldn't find anything out there that would do it without including other info. Using Substrate I developed a utility ("Minecraft Sign Plotter") that plots sign locations and lists/prints sign text. I have only tested it on my single-player worlds but it is at a point where I can release it in case anyone else out there uses signs like I do.
Whenever I try to call .Save() on a ChunkManger instance it throws me this
System.ArgumentNullException was unhandled
Message=String reference not set to an instance of a String.
Parameter name: s
Source=mscorlib
ParamName=s
StackTrace:
at System.Text.Encoding.GetBytes(String s)
at Substrate.Nbt.NbtTree.WriteString(TagNodeString val)
at Substrate.Nbt.NbtTree.WriteValue(TagNode val)
at Substrate.Nbt.NbtTree.WriteTag(String name, TagNode val)
at Substrate.Nbt.NbtTree.WriteCompound(TagNodeCompound val)
at Substrate.Nbt.NbtTree.WriteValue(TagNode val)
at Substrate.Nbt.NbtTree.WriteList(TagNodeList val)
at Substrate.Nbt.NbtTree.WriteValue(TagNode val)
at Substrate.Nbt.NbtTree.WriteTag(String name, TagNode val)
at Substrate.Nbt.NbtTree.WriteCompound(TagNodeCompound val)
at Substrate.Nbt.NbtTree.WriteValue(TagNode val)
at Substrate.Nbt.NbtTree.WriteTag(String name, TagNode val)
at Substrate.Nbt.NbtTree.WriteCompound(TagNodeCompound val)
at Substrate.Nbt.NbtTree.WriteValue(TagNode val)
at Substrate.Nbt.NbtTree.WriteTag(String name, TagNode val)
at Substrate.Nbt.NbtTree.WriteTo(Stream s)
at Substrate.AnvilChunk.Save(Stream outStream)
at Substrate.ChunkRef.Save(Stream outStream)
at Substrate.RegionChunkManager.Save()
at SubstrateTest.WorldGenerator.generateWorld(Int32 dim) in D:\gaems\C#\sustratetest\SubstrateTest\SubstrateTest\WorldGenerator.cs:line 85
at SubstrateTest.WorldGenerator.createWorld() in D:\gaems\C#\sustratetest\SubstrateTest\SubstrateTest\WorldGenerator.cs:line 63
at SubstrateTest.Form1.button2_Click(Object sender, EventArgs e) in D:\gaems\C#\sustratetest\SubstrateTest\SubstrateTest\Form1.cs:line 112
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at SubstrateTest.Program.Main() in D:\gaems\C#\sustratetest\SubstrateTest\SubstrateTest\Program.cs:line 19
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
I have the exact same structure as in your FlatMap example. Didn't try to run the flatmap example. Probably calling something wrong way.
It's probably not your problem because it happened after I moved program's classes into different files.
Earlier the program used almost the same and worked even if it was a giant unreadable clump of code.
Looks like a string tag has a null string data value. You should see if your code could be setting a null string, but for my part I should patch up the NBT writer to handle null strings as empty strings instead.
- Fix: Bug in index calculations of Anvil composite byte/nibble arrays, causing incorrect block updates.
- Block updates for Minecraft 1.4.
- Minor changes to RegionFile to make it easier to extend (e.g. for Cubic Chunks).
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
In general, whenever you need to modify a property that is not exposed by a specific object (in this case a specific TileEntity), you can still access that object's NbtTree and set the raw data. A bit like using NBTExplorer or NBTedit, but with code.
Mods I Develop: Garden Stuff -- Storage Drawers -- Hunger Strike
Tools I Develop: NBTExplorer -- Substrate
If not, I have a pair of functions that add said functionality I'd be happy to contribute.
There is a minor caveat however. When you save the TileEntity (via a BuildTree call), a new tree will be built from all the values defined by the schema of the particular TileEntity type, and then the "Source" compound will be merged into that tree. Any values already in the tree will take precedence. If you want to handle all types in a consistently general-purpose way, you'll need to add or change something. In retrospect, I did not architect that very well.
Mods I Develop: Garden Stuff -- Storage Drawers -- Hunger Strike
Tools I Develop: NBTExplorer -- Substrate
And yes, I noticed that Source was protected. I, ah, may have dented my desk when I first saw that
Mods I Develop: Garden Stuff -- Storage Drawers -- Hunger Strike
Tools I Develop: NBTExplorer -- Substrate
The whole point of asking about this was specifically because I dont' want to get stuck on a custom-modified version of Substrate
It's implemented as an overload with a boolean parameter, so the change should not be breaking for any existing projects using Substrate.
I am writing a program that takes GIS elevation data and transforms it into a Minecraft map. Once this is finished, I want to add hydrography, roads, ground cover, etc.. all from the standard file formats that are freely available on most U.S. state's websites and the USGS.
My first thought was to just write the code to create the map files myself, but while searching for background data, I found this tool. Any opinions/advice would be greatly appreciated.
Thanks,
Eric
Mods I Develop: Garden Stuff -- Storage Drawers -- Hunger Strike
Tools I Develop: NBTExplorer -- Substrate
http://www.minecraftforum.net/topic/1582262-tool-seesharp-a-minecraft-map-exporter-for-the-rest-of-us/
- Fix: Wrong tag name for additional block IDs ("AddBlocks" instead of "Add")
- Fix: Anvil worlds can now handle block IDs >255
- Fix: Empty chunk sections below heightmap were not written
- Fix: NBT Tree discarding root node name on load
- Fix: Various Entity and TileEntity issues
- Raw NBT tree exposed on more objects (Entities, TileEntities, Items...)
- Generic TileEntity objects will be created if specific types are unknown
- Region files multithread safe
- MobSpawnerTileEntities have updated data fields
Several of these fixes and improvements were provided by other members of the community, so thank you for the contributions and bug reports!
Mods I Develop: Garden Stuff -- Storage Drawers -- Hunger Strike
Tools I Develop: NBTExplorer -- Substrate
As for abilities, I think they're mostly ignored by MC unless the correct gametype is specified. Even then I don't know how or if they are all honored.
Mods I Develop: Garden Stuff -- Storage Drawers -- Hunger Strike
Tools I Develop: NBTExplorer -- Substrate
Thanks for Substrate... I ran into a need to report out the text and location my signs as a way to keep track of where my stuff is, and I couldn't find anything out there that would do it without including other info. Using Substrate I developed a utility ("Minecraft Sign Plotter") that plots sign locations and lists/prints sign text. I have only tested it on my single-player worlds but it is at a point where I can release it in case anyone else out there uses signs like I do.
http://syntap.com/blog/?p=135
It would have been much harder to so without your work on Substrate, thank you!
Message=String reference not set to an instance of a String.
Parameter name: s
Source=mscorlib
ParamName=s
StackTrace:
at System.Text.Encoding.GetBytes(String s)
at Substrate.Nbt.NbtTree.WriteString(TagNodeString val)
at Substrate.Nbt.NbtTree.WriteValue(TagNode val)
at Substrate.Nbt.NbtTree.WriteTag(String name, TagNode val)
at Substrate.Nbt.NbtTree.WriteCompound(TagNodeCompound val)
at Substrate.Nbt.NbtTree.WriteValue(TagNode val)
at Substrate.Nbt.NbtTree.WriteList(TagNodeList val)
at Substrate.Nbt.NbtTree.WriteValue(TagNode val)
at Substrate.Nbt.NbtTree.WriteTag(String name, TagNode val)
at Substrate.Nbt.NbtTree.WriteCompound(TagNodeCompound val)
at Substrate.Nbt.NbtTree.WriteValue(TagNode val)
at Substrate.Nbt.NbtTree.WriteTag(String name, TagNode val)
at Substrate.Nbt.NbtTree.WriteCompound(TagNodeCompound val)
at Substrate.Nbt.NbtTree.WriteValue(TagNode val)
at Substrate.Nbt.NbtTree.WriteTag(String name, TagNode val)
at Substrate.Nbt.NbtTree.WriteTo(Stream s)
at Substrate.AnvilChunk.Save(Stream outStream)
at Substrate.ChunkRef.Save(Stream outStream)
at Substrate.RegionChunkManager.Save()
at SubstrateTest.WorldGenerator.generateWorld(Int32 dim) in D:\gaems\C#\sustratetest\SubstrateTest\SubstrateTest\WorldGenerator.cs:line 85
at SubstrateTest.WorldGenerator.createWorld() in D:\gaems\C#\sustratetest\SubstrateTest\SubstrateTest\WorldGenerator.cs:line 63
at SubstrateTest.Form1.button2_Click(Object sender, EventArgs e) in D:\gaems\C#\sustratetest\SubstrateTest\SubstrateTest\Form1.cs:line 112
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at SubstrateTest.Program.Main() in D:\gaems\C#\sustratetest\SubstrateTest\SubstrateTest\Program.cs:line 19
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
I have the exact same structure as in your FlatMap example. Didn't try to run the flatmap example. Probably calling something wrong way.
It's probably not your problem because it happened after I moved program's classes into different files.
Earlier the program used almost the same and worked even if it was a giant unreadable clump of code.
Mods I Develop: Garden Stuff -- Storage Drawers -- Hunger Strike
Tools I Develop: NBTExplorer -- Substrate