Jump to content

Science!

Members
  • Posts

    30
  • Joined

  • Last visited

Posts posted by Science!

  1. 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.

  2. 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.

  3. 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.

  4. 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())
        }
    

     

  5. 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?

  6. 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.

  7. 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.

  8. 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.

  9. 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.

  10. Hmm.... I might just end up not being able to do this, unfortunately, at least not without a bit of asm. My hands are kind of tied in terms of giving the blocks themselves special logic, as I'd like to be able to change the light value of blocks from mods, for example. Even more unfortunately, these blocks are plants, meaning I'd have to not only copy how they look but their logic as well. That lighting link is interesting though, and shows me where to look if I do end up going the asm route. There's one thing I find curious though- if the lighting should revert whenever its recalculated, why does the light value persist, albeit sporadically, even between doing things like placing blocks around it and reopening the world? Also, as far as forcing a re-render, isn't that what I was doing with

    event.world.markBlockRangeForRenderUpdate(event.x, event.y, event.z, 15, 15, 15);

    ?

     

  11. World world = tileEntity.getWorldObj(). Or World potato = tileEntity.getWorldObj(), it doesn't really matter, as long as you then put potato.getBlockMetadata(). Its just a variable assignment :/ . You'll also need to actually set dir equal to world.getBlockMetadata(). world.getBlockMetadata() is just a method that returns a value (an integer in this case, which is equal to the block's metadata). It doesn't actually change dir on its own- you need to right dir = world.getBlockMetadata(x,y,z); . It seems you are a little unfamiliar with Java, so I suggest looking at at least a few general purpose Java tutorials before going much further with your mod. You can find a million free ones on the internet.

  12. Title explains it pretty well. If possible, I'd like to make a particular block glow. Unfortunately, due to compatibility issues, I can't really just make a copy with a different light value. I initially tried setLightValue(), but it changed all blocks of the same type. (Sidenote- could someone confirm or deny for me that there is only one instance of each type of block? It definitely seems like when you change even non-static values like lightValue it affects all of them). So next I looked into world.setLightValue() method and I came up with the following (stuck in a PlayerInteractEvent Handler for the sake of quick testing):

    @SubscribeEvent
    public void plantHandler(PlayerInteractEvent event) {
    	//You can ignore everything from here until the next comment. It's for testing other stuff
    	if (event.entityPlayer.getHeldItem() == null) return;
    	if (event.action != PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) return;
    	if(event.entityPlayer.getHeldItem().getItem() == Items.arrow){
    		SeedHandler.testChamberBuilder(new int[]{event.x, event.y, event.z, event.world.provider.dimensionId});
    	}
    	//Start of relevant code
    	if(event.entityPlayer.getHeldItem().getItem() == Items.glowstone_dust){
    		//Set the light value
    		event.world.setLightValue(EnumSkyBlock.Block, event.x, event.y, event.z, 15);
    		//Mark the nearby blocks for a render update
    		event.world.markBlockRangeForRenderUpdate(event.x, event.y, event.z, 15, 15, 15);
    		LogHelper.info("Get block light value: " + event.world.getBlockLightValue(event.x, event.y, event.z));
    		LogHelper.info("Get light brightness: " + event.world.getLightBrightness(event.x, event.y, event.z));
    	}
    	//Everything after here is prettymuch irrelevant to the issue at hand
    	if(event.entityPlayer.getHeldItem().getItem() == Items.bowl){
    		event.world.getBlock(event.x, event.y, event.z).setTickRandomly(false);
    	}
    	if(event.entityPlayer.getHeldItem().getItem() == Items.saddle){
    		event.world.getBlock(event.x, event.y, event.z).setTickRandomly(true);
    	}
    	ItemStack stack = event.entityPlayer.getHeldItem();
    	if (stack.getTagCompound() == null || !stack.getTagCompound().hasKey("genTechId")) return;
    	PlantData data = PlantData.get(event.world);
    	GenTechPlant plant = data.getPlant(stack.getTagCompound().getInteger("genTechId"));
    	if (plant.canPlant(event.x, event.y, event.z, event.world, ForgeDirection.getOrientation(event.face)))
    		data.addBlock(new int[]{event.x, event.y, event.z, event.world.provider.dimensionId}, plant);
    
    }
    

    Unfortunately, this has some odd behavior. When I first use it, it seems to do nothing. Upon exiting and reopening the world, the block is actually lit up. However, if I place something on top of the block, the light goes out, and won't reappear until I exit and reopen the world again. Oh, and the block light value and light brightness return the correct values, both before and after exiting and reopening.

  13. Getting the metadata while in the render class is precisely what world.getBlockMetadata() is for. Your block class was fine, except for the odd choice of switch statement. GET block metadata is, as one might expect, for GETTING the metadata. So first you SET it form the Block class, like you originally did, with the SETBlockMetadataWithNotify method. Then, in  your renderer class, you GET it with the world.GETBlockMetadata method. In your renderer class, you don't already have a world variable, so that's what tileEntity.getWorldObj() is for. So this way, by setting the metadad when you place it in the block class then getting it in the renderer class, you pass your directional information from your block to your renderer.

  14. Use

    world.getBlockMetadata(x,y,z)

    to get the metadata. You can get the world with

    tileEntity.getWorldObj()

      Also, while this doesn't have to do with your block not being the proper direction,  why do you have a switch statement to figure out what to print for your metadata? You can just do

    System.out.println(metadir)

  15. When you say 'world', do you mean world as in the class World, ie each dimension is its own world, or world as in one server's instance of minecraft, complete with all dimensions? And yeah, I might just go with the names. I just figured if there weren't any downsides to the integer ids they'd save a tiny bit of memory vs the String names.

  16. I did this a little while ago in a since-abandoned mod, so maybe take it with a grain of salt, but looking back at my code, in my Renderer class right before the actual model.render, I rotated it with:

    [embed=425,349]GL11.glRotatef(/*some rotation variable*/, 0.0F, 1.0F, 0.0F);[/embed]

    As far as getting that rotation variable, you'd probably base it off of the metadata like normal. If you have trouble like that, I'm willing to bet that in your earlier post that you mentioned people explain it. The only real difference is rather than picking an image based off of metadata, you pick a rotation angle (in degrees).

  17. I have an object that needs to store a block and an item in nbt. After a little bit of looking, I saw that both the Item and Block classes have a method to get an integer id for an item or block respectively, and to get the item or block back from that integer id. What I want to know is, is there a reason for me not to use these? I know that these days ids are dynamically allocated somehow or other, and what I'm worried about is the same id not always pointing to the same item/block. I'm *guessing* they probably won't change if the mods installed stay the same, but I'm particularly worried about what happens if the mods are updated, or another mod is added.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.