
Science!
Members-
Posts
30 -
Joined
-
Last visited
Converted
-
Gender
Undisclosed
-
Personal Text
Author of GenTech! Theoretically.
Science!'s Achievements

Tree Puncher (2/8)
4
Reputation
-
[1.7.10] [Solved] How do I get nbt data from a TileEntity?
Science! replied to a topic in Modder Support
I'm a little confused as to what exactly you're asking. readFromNBT is called when the tile entity is loaded from memory on the nbt compound tag that represents the tile entity. So while it doesn't access the data in and of itself, it is what is used to turn that memory into the relevant information for the tile entity. As far as 'retrieving NBT data from memory' A. I don't know if you can directly (not at my desktop so I can't really look through the code to check) but B., more importantly, I don't know why you'd want or need to. The data of a tile entity isn't stored automatically- whatever you want to store, you have to do so yourself in the writeToNBT function. So any data that is stored in the tile entity's nbt you should already have direct access to from the tile entity, because otherwise you wouldn't be able to store it in the nbt in the first place. So if you wanted to store, for example, the unlocalized name of the liquid and #mb in your tile entity, it would look something like this: @Override public void writeToNBT(NBTTagCompound tag) { super.writeToNBT(tag); tag.setString("liquidName", liquidName); tag.setInteger("millibuckets", millibuckets); //or whatever your field names might be } and you'd retrieve the information by modifying the readFromNBT function, which would be called when the tile entity is loaded form memory @Override public void readFromNBT(NBTTagCompound tag) { super.readFromNBT(tag); liquidName = tag.getString("liquidName"); millibuckets = tag.getInteger("millibuckets"); //or whatever your field names might be } Other than your readFromNBT and writeFromNBT you can basically ignore the nbt. If you wanted to access the number of millibuckets for example, you'd just use the millibuckets field. Hopefully that answers your question as, as I said, I'm not 100% sure about what you meant by it. -
[SOLVED] [1.7.10] Sticking Tile Entities Where They Don't Belong
Science! replied to Science!'s topic in Modder Support
Alright, so apparently what was happening is when the chunks were reloaded, it called that same function in Chunk I had to rewrite earlier. I was able to fix things by handling ChunkDataEvent.Load and loading it using my rewritten version. It still isn't showing in OPIS, which is hopefully not indicative of some larger problem and is just an idiosyncrasy of however OPIS tracks tile entities. Actually, as I write this, I'm thinking maybe its just because the particular tile entity I was testing with has canUpdate return false, and maybe OPIS doesn't track those. Anyway, it seems to be solved. -
You could do Blocks.grass.setTickRandomly(false). Ofc, then it won't turn into dirt either, although if you're doing that by some other function as it appears that might not matter. Note that you might have to do this every time MC launches- I honestly don't remember if it sticks or not.
-
I have two spots in my mod where its useful to me to add in Tile Entities after the fact. I can do both in different ways if I really need to, but this is the ideal way of doing things in either case. At first, I tried using world.setTileEntity(x,y,z,TileEntity), but that didn't actually do anything. So I stuck a way of creating and checking for tile entities into a PlayerInteractEvent handler and proceeded to start trying stuff. After digging into things a little bit, I determined that in the chunk function it checks if the block at that location is actually supposed to have a tile entity, and if it doesn't then the tile entity won't be added. So I rewrote it without that check. Now, according to my check, which is calling world.getTileEntity, it gets set, but OPIS doesn't see it and it disappears if I reload the world. I'm pretty sure my function does all the same stuff as the original, only without the check, so I'm not really sure what the problem is. Anyone know, or know a better way of adding Tile Entities after the fact where they might not belong? Btw, for one of the usecases I'm dealing with vanilla blocks and blocks from other mods, so I can't modify the block code. Relevant code: PlayerEventHandler to create and check for Tile Entities (Location is basically just a container for coordinates): @SubscribeEvent public void interactHandler(PlayerInteractEvent event) { if (event.entityPlayer.getHeldItem() == null) return; if (event.action != PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) return; ItemStack stack = event.entityPlayer.getHeldItem(); try { if (stack.getItem() == Items.baked_potato) { TileEntity te = TileDataOnly.class.newInstance(); LogHelper.info("Tile entity is invalid? " + te.isInvalid()); WorldHelper.setTileAnywhere(te, new Location(event.x, event.y, event.z, event.world)); } } catch (IllegalAccessException e) { LogHelper.info(e); } catch (InstantiationException e) { LogHelper.info(e); } LogHelper.info(event.world.getBlock(event.x, event.y, event.z) + ": " + event.world.getBlockMetadata(event.x, event.y, event.z)); LogHelper.info(event.world.getTileEntity(event.x, event.y, event.z)); } setTileAnywhere, my replacement for world.setTileEntity (This is in groovy, but besides the lack of semicolons its basically java): static def setTileAnywhere(TileEntity te, Location l) { if(te == null || te.isInvalid()) return //calls the normal setTileEntity to do... something, I'm not really sure what //but it accesses private fields in world and should fail before it gets to what //the rest of it does so this is just easier l.setTile(te) //adds the tileEntity into the world //this until the end is basically copied and pasted from Chunk chunk = l.world().getChunkFromBlockCoords(l.x(), l.z()) if (chunk != null) { //this is basically copied and pasted from func_150812_a in Chunk, except without the check //for if the block should have a tile entity ChunkPosition chunkposition = new ChunkPosition(l.x() & 15, l.y(), l.z() & 15) te.setWorldObj(l.world()) te.xCoord = l.x() te.yCoord = l.y() te.zCoord = l.z() if (chunk.chunkTileEntityMap.containsKey(chunkposition)) { ((TileEntity)chunk.chunkTileEntityMap.get(chunkposition)).invalidate() } te.validate(); chunk.chunkTileEntityMap.put(chunkposition, te) } //notifies the world of the changes l.world().func_147453_f(l.x(), l.y(), l.z(), l.getBlock()) }
-
[Solved] [1.7.10] onBlockActivated parameters
Science! replied to Science!'s topic in Modder Support
OK, thanks. -
[Solved] [1.7.10] onBlockActivated parameters
Science! replied to Science!'s topic in Modder Support
Are those still in world coordinates? Or are they in some coordinate system local to the block? -
[Solved] [1.7.10] onBlockActivated parameters
Science! replied to Science!'s topic in Modder Support
Ah. Good thing you replied just then, as I had just marked this as solved -
This is onBlockActivated, in the Block class public boolean onBlockActivated(World p_149727_1_, int p_149727_2_, int p_149727_3_, int p_149727_4_, EntityPlayer p_149727_5_, int p_149727_6_, float p_149727_7_, float p_149727_8_, float p_149727_9_) { return false; } The first five parameters I can guess are the world the block is in, the x, y, and z coords of the block, and the player doing the activation. From this I found the 6th one is the metadata of the block. What are the floats? Player coordinates?
-
Hm... well if that's the case and the performance is about the same, its probably worth it to use the tile entity since that way I'm sort of working 'within the system'.
-
This is basically an optimization issue. The mod I'm currently working on modifies plants via event handlers and such. The general process is to intercept something like a HarvestDropsEvent, see if its coming from a location with a 'modified plant' object, and if it is, have that object act accordingly- for example, I might double the ItemStack array returned. The way I've been doing the lookup is with a Hashmap<Location, Integer>, where the Location object just stores an x,y,z, and dimID, and the Integer is the id of the 'modified plant object' that is in that spot. As I did this, it occurred to me that I could just as easily have a tile entity at that location which only stores the integer id. So basically, my question is 'Should I replace the hashmap with tile entities?' I'm inclined to think of tile entities as lag machines from my experience as a player, but frankly I don't know enough about how they're handled to really know how efficient they are or aren't. Some pros/cons of tile entities I've thought of: Pros: No autoboxing between Integer and int Would probably interact properly with things like frames and teleporters Would unload with chunks (Probably implementable with the Hashmap, but probably also a bit of a pain) Cons: Would interfere with plants that might have tile entities (not an issue with vanilla plants, but possibly with some mod crops) My biggest concern though is performance, since people will potentially have whole fields of these, or even a natura redwood's worth.
-
Ah, right. My bad. It's been a little while since I've set any metadata.
-
I believe the issue now is in your block code, where you do world.setBlockMetadataWithNotify(x, y, z, 0, l); The last parameter of the setBlockMetadataWithNotify method is a flag that tells minecraft what to notify about the change to metadata. As a general rule, you usually want it to be 2 (so it notifies the client), and here, where you're dealing with a client-side thing like the direction a model is rendered in, you DEFINITELY want to. Instead, you're setting it to l, which could be 0,1,2, or 3. So what's probably happening is the metadata is set correctly server side, but never passed to the client. So when the renderer class, which only runs on the client side iirc, tries to get the block metadata, it gets the block metadata for the client version of the world, which hasn't changed. Also, because you only ever set the metadata to the value of l in the first place, you can just replace the whole if (l == x) {} set of if statements with world.setBlockMetadataWithNotify(x,y,z,l,2); System.out.println(l); //System.out.println is more than robust enough to deal with integers on its own, without you converting them to strings first. It's much cleaner.
-
[1.7.10] Changing the Light Value of a Particular Block
Science! replied to Science!'s topic in Modder Support
Alright, thank you. I think I'll probably end up either messing with World.computeLightValue() via asm or just decide that glowing plants, while neat, are kind of a superfluous visual thing which I can probably scrap. -
Hm. Well, at this point I'm basically just comparing your code to mine, because I'm not exactly an expert on openGL myself. With that in mind, I call GL11.glPushMatrix() before I do either of the rotations, rather than after both of them, which you do. Also, I don't think this would really affect anything, but I don't think your i1 variable in your block class does anything. The metadata for the block before you set it is presumably 0, and 0&4=0. Any number | 0 should be the original number. So I'm pretty sure it doesn't do anything but take up some infinitesimal amount of extra processing power. Again, though, because it doesn't actually do anything, it doesn't do anything BAD either. It just exists, when it probably doesn't have to.
-
x, y, and z are doubles. world.getBlockMetadata expects integer parameters. You can solve this just by casting x, y and z to integers. If you don't know how, look at how you cast them to floats in the GL11.glTranslatef() method and, again, I really suggest looking at a java tutorial or two.