Jump to content

coolAlias

Members
  • Posts

    2805
  • Joined

  • Last visited

Posts posted by coolAlias

  1. How about PlayerWakeUpEvent - pretty self-explanatory, but currently I use LivingUpdateEvent to check if the player is fully asleep instead.

     

    InventorySlotClick event would be useful for intercepting inventory interactions, for example if you have a spell that creates magic armor that you don't want the player to be able to remove or that destroys itself if clicked.

  2. You could also try out my Structure Generation Tool - it has methods that allow you to easily manipulate things like TileEntity inventories, set painting art, add items to item frames, etc.

     

    Additionally, you'll be able to generate your structure easily at any rotation or offset.

     

    http://www.minecraftforum.net/topic/1963371-structure-generation-and-rotation-tool/

     

    It's open source, so you can see for yourself how the methods work and copy it if you want.

  3. Might I suggest opening a custom Gui with your Item Backpack rather than editing the base inventory gui? For an example of this, check out my tutorial on creating an Item that stores an Inventory: http://www.minecraftforum.net/topic/1949352-creating-an-item-that-stores-an-inventory/

     

    If you want an extra inventory slot to store the item, like I see you are doing, you could store it in IExtendedEntityProperties and assign a special key to open your custom player inventory to allow access to your custom slot. If you need help with IExtendedEntityProperties, I also have a tutorial on that:

    http://www.minecraftforum.net/topic/1952901-eventhandler-and-iextendedentityproperties/#entry24051513

     

    I've done this exact thing helping out some guys making a Naruto mod - they needed custom inventory slots for Sharingan Eyes, and I did it like I outlined above.

  4. DamageSource has a method getSourceOfDamage() that returns the Entity causing the damage.

     

    Use it like this in your LivingAttackEvent:

    if (event.entity instanceof EntityPlayer)
    {
    // Now you've got the player that is being attacked by something
    EntityPlayer player = (EntityPlayer) event.entity;
    
    if (event.source.getSourceOfDamage() != null && event.source.getSourceOfDamage() instanceof EntityZombie)
    {
    EntityZombie zombie = (EntityZombie) event.source.getSourceOfDamage();
    
    // now you've got the zombie that's attacking the player, do what you'd like to it
    }
    }
    

  5. You also have to set a max use duration for your item, or it cannot be used. If you don't override this method, the default value from Item is 0.

    @Override
        public int getMaxItemUseDuration(ItemStack par1ItemStack)
        {
            return 72000; // however long your item can be used, in ticks
        }
    

     

    It worked! Thanks! And I didn't know you moved here from MCForums :P

    Great! Yeah, I just signed up with some problems of my own ;)

  6. You also have to set a max use duration for your item, or it cannot be used. If you don't override this method, the default value from Item is 0.

    @Override
        public int getMaxItemUseDuration(ItemStack par1ItemStack)
        {
            return 72000; // however long your item can be used, in ticks
        }
    

  7. Try using this in your EntityJoinWorldEvent instead:

    if (event.entity instanceof EntityPlayer) {
      event.entity.getEntityData().setInteger("gold", 1000);
      // test to see if it worked:
      System.out.println("Player's gold: " + event.entity.getEntityData().getInteger("gold"));
    }
    

    'getEntityData()' returns the NBT Tag Compound associated with the entity, be it player or whatever. Then you can set the gold directly like that if you want.

     

    You don't need to create all those other variables in your code, such as 'theNBT'. Just use the ones provided by the parameters.

     

    The OP is using that event. I think the problem is that those objects have not been set yet when he / she is trying to access them.

     

    It's similar to how you can't access worldObj in the constructor of a TileEntity because it does not get set until after the constructor.

    All of those fields should already be initialized in EntityJoinWorldEvent. I use it all the time to set IExtendedEntityProperty data specifically because these same objects are available for use, whereas, as you've pointed out, are NOT available in a constructor or using the EntityConstructingEvent.

     

    @OP: I'd suggest taking a look at my tutorial on using IExtendedEntityProperties - there you will find a better way to add gold as well as get it to persist across player death and such. http://www.minecraftforum.net/topic/1952901-eventhandler-and-iextendedentityproperties/#entry24051513

  8. Try using this in your EntityJoinWorldEvent instead:

    if (event.entity instanceof EntityPlayer) {
      event.entity.getEntityData().setInteger("gold", 1000);
      // test to see if it worked:
      System.out.println("Player's gold: " + event.entity.getEntityData().getInteger("gold"));
    }
    

    'getEntityData()' returns the NBT Tag Compound associated with the entity, be it player or whatever. Then you can set the gold directly like that if you want.

     

    You don't need to create all those other variables in your code, such as 'theNBT'. Just use the ones provided by the parameters.

  9. I've recently been trying to update my Structure Generation Toolhttps://github.com/coolAlias/StructureGenerationTool to be compatible with multi-player; as such, I've changed to a KeyHandler and storing the Item variables in NBT.

     

    Each key press changes a variable in the item's NBT, but this is only client side. I know I can send packets, but I was hoping not to spam packets because the data is only needed when the item is used. I've been trying to send a packet from client to server onItemUse, which works, but it's too late to the party and the Item activates with the data from the previous time instead of the current data.

     

    I played around with synchronized variable and wait/notify, but it results in thread lock since the server side is waiting for the information but it can't get it until the onItemUse method is called client side, which obviously doesn't happen while the thread is waiting.

     

    Here's my item code with my failed attempts:

     

    public class ItemStructureSpawner extends BaseModItem
    {
    /** Enumerates valid values for increment / decrement offset methods */
    public static enum Offset { OFFSET_X, OFFSET_Y, OFFSET_Z }
    
    /** List of all structures that can be generated with this item */
    private static final List<Structure> structures = new LinkedList();
    
    private static final StructureGeneratorBase gen = new WorldGenStructure();
    
    /** String identifiers for NBT storage and retrieval */
    private static final String[] data = {"Structure", "Rotations", "OffsetX", "OffsetY", "OffsetZ", "InvertY"};
    
    /** Indices for data variables */
    private static final int STRUCTURE_INDEX = 0, ROTATIONS = 1, OFFSET_X = 2, OFFSET_Y = 3, OFFSET_Z = 4, INVERT_Y = 5;
    
    public ItemStructureSpawner(int par1)
    {
    	super(par1);
    	setMaxDamage(0);
    	setMaxStackSize(1);
    	setCreativeTab(CreativeTabs.tabMisc);
    	// constructor should only be called once anyways
    	init();
    	LogHelper.log(Level.INFO, "ItemStructureSpawner initialized structures.");
    }
    
    /**
         * Called when item is crafted/smelted. Not called from Creative Tabs.
         */
    @Override
        public void onCreated(ItemStack itemstack, World world, EntityPlayer player)
        {
    	initNBTCompound(itemstack);
        }
    
    /**
     * Increments the appropriate Offset and returns the new value for convenience.
     */
    public int incrementOffset(ItemStack itemstack, Offset type)
    {
    	if (itemstack.stackTagCompound == null)
    		initNBTCompound(itemstack);
    
    	int offset;
    
    	switch(type) {
    	case OFFSET_X:
    		offset = itemstack.stackTagCompound.getInteger(data[OFFSET_X]) + 1;
    		itemstack.stackTagCompound.setInteger(data[OFFSET_X], offset);
    		return offset;
    	case OFFSET_Y:
    		offset = itemstack.stackTagCompound.getInteger(data[OFFSET_Y]) + 1;
    		itemstack.stackTagCompound.setInteger(data[OFFSET_Y], offset);
    		return offset;
    	case OFFSET_Z:
    		offset = itemstack.stackTagCompound.getInteger(data[OFFSET_Z]) + 1;
    		itemstack.stackTagCompound.setInteger(data[OFFSET_Z], offset);
    		return offset;
    	default: return 0;
    	}
    }
    
    /**
     * Decrements the appropriate Offset and returns the new value for convenience.
     */
    public int decrementOffset(ItemStack itemstack, Offset type)
    {
    	if (itemstack.stackTagCompound == null)
    		initNBTCompound(itemstack);
    
    	int offset;
    
    	switch(type) {
    	case OFFSET_X:
    		offset = itemstack.stackTagCompound.getInteger(data[OFFSET_X]) - 1;
    		itemstack.stackTagCompound.setInteger(data[OFFSET_X], offset);
    		return offset;
    	case OFFSET_Y:
    		offset = itemstack.stackTagCompound.getInteger(data[OFFSET_Y]) - 1;
    		itemstack.stackTagCompound.setInteger(data[OFFSET_Y], offset);
    		return offset;
    	case OFFSET_Z:
    		offset = itemstack.stackTagCompound.getInteger(data[OFFSET_Z]) - 1;
    		itemstack.stackTagCompound.setInteger(data[OFFSET_Z], offset);
    		return offset;
    	default: return 0;
    	}
    }
    
    /**
     * Returns true if y offset is inverted (i.e. y will decrement)
     */
    public boolean isInverted(ItemStack itemstack) {
    	if (itemstack.stackTagCompound == null)
    		initNBTCompound(itemstack);
    	return itemstack.stackTagCompound.getBoolean(data[iNVERT_Y]);
    }
    
    /**
     * Inverts Y axis for offset adjustments; returns new value for convenience.
     */
    public boolean invertY(ItemStack itemstack) {
    	if (itemstack.stackTagCompound == null)
    		initNBTCompound(itemstack);
    	boolean invert = !itemstack.stackTagCompound.getBoolean(data[iNVERT_Y]);
    	itemstack.stackTagCompound.setBoolean(data[iNVERT_Y], invert);
    	return invert;
    }
    
    /**
     * Resets all manual offsets to 0.
     */
    public void resetOffset(ItemStack itemstack) {
    	if (itemstack.stackTagCompound == null)
    		initNBTCompound(itemstack);
    	itemstack.stackTagCompound.setInteger(data[OFFSET_X], 0);
    	itemstack.stackTagCompound.setInteger(data[OFFSET_Y], 0);
    	itemstack.stackTagCompound.setInteger(data[OFFSET_Z], 0);
    }
    
    /**
     * Rotates structure's facing by 90 degrees clockwise; returns number of rotations for convenience.
     */
    public int rotate(ItemStack itemstack) {
    	if (itemstack.stackTagCompound == null)
    		initNBTCompound(itemstack);
    	int rotations = (itemstack.stackTagCompound.getInteger(data[ROTATIONS]) + 1) % 4;
    	itemstack.stackTagCompound.setInteger(data[ROTATIONS], rotations);
    	return rotations;
    }
    
    /**
     * Increments the structure index and returns the new value for convenience.
     */
    public int nextStructure(ItemStack itemstack) {
    	if (itemstack.stackTagCompound == null)
    		initNBTCompound(itemstack);
    	int index = itemstack.stackTagCompound.getInteger(data[sTRUCTURE_INDEX]) + 1;
    	if (index == structures.size()) index = 0;
    	itemstack.stackTagCompound.setInteger(data[sTRUCTURE_INDEX], index);
    	return index;
    }
    
    /**
     * Decrements the structure index and returns the new value for convenience.
     */
    public int prevStructure(ItemStack itemstack) {
    	if (itemstack.stackTagCompound == null)
    		initNBTCompound(itemstack);
    	int index = itemstack.stackTagCompound.getInteger(data[sTRUCTURE_INDEX]) - 1;
    	if (index < 0) index = this.structures.size() - 1;
    	itemstack.stackTagCompound.setInteger(data[sTRUCTURE_INDEX], index);
    	return index;
    }
    
    /**
     * Returns the name of the structure at provided index, or "" if index out of bounds
     */
    public String getStructureName(int index) {
    	return (index < structures.size() ? structures.get(index).name : "");
    }
    
    /**
     * Returns index of currently selected structure
     */
    public int getCurrentStructureIndex(ItemStack itemstack) {
    	if (itemstack.stackTagCompound == null)
    		initNBTCompound(itemstack);
    	return itemstack.stackTagCompound.getInteger(data[sTRUCTURE_INDEX]);
    }
    
    /**
     * Toggles between generate and remove structure setting. Returns new value for convenience.
     */
    public boolean toggleRemove() {
    	return gen.toggleRemoveStructure();
    }
    
    @Override
    public int getMaxItemUseDuration(ItemStack par1ItemStack)
        {
            return 1;
        }
    
    @Override
    public boolean onItemUse(ItemStack itemstack, EntityPlayer player, World world, int x, int y, int z, int par7, float par8, float par9, float par10)
        {
    	// Need to update server with correct information
    	if (world.isRemote) {
    		if (itemstack.stackTagCompound == null)
    			initNBTCompound(itemstack);
    		PacketDispatcher.sendPacketToServer(SGTPacketNBTItem.getPacket(itemstack));
    	}
    	// NOTE: It isn't absolutely necessary to check if the world is not remote here,
    	// but I recommend it as the client will be notified automatically anyway.
    	if (!world.isRemote && structures.size() > 0)
    	{
    		//new SyncThread(itemstack);
    		/*
    		while (itemstack.stackTagCompound == null)
    		{
    			try {
    				System.out.println("Waiting...");
    				wait();
    			} catch (InterruptedException e) {
    				System.out.println("Interrupted.");
    				//e.printStackTrace();
    				//return false;
    			}
    			System.out.println("Finished waiting.");
    		}
    		*/
    		/*
    		if (itemstack.stackTagCompound == null) {
    			LogHelper.log(Level.SEVERE, "Item Structure Spawner's NBT Tag is null.");
    			//initNBTCompound(itemstack);
    			try {
    				wait();
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    				return false;
    			}
    		}
    		*/
    		NBTTagCompound tag = itemstack.stackTagCompound;
    		// LogHelper.log(Level.INFO, "Preparing to generate structure");
    		gen.setPlayerFacing(player);
    		//gen.addBlockArray(StructureArrays.blockArrayNPCBlackSmith);
    		Structure structure = structures.get(tag.getInteger(data[sTRUCTURE_INDEX]));
    		// LogHelper.log(Level.INFO, "Structure size: " + structure.blockArrayList().size());
    		gen.setBlockArrayList(structure.blockArrayList());
    		gen.setStructureFacing(structure.getFacing() + tag.getInteger(data[ROTATIONS]));
    		// LogHelper.log(Level.INFO, "Default offsets: " + structure.getOffsetX() + "/" + structure.getOffsetZ());
    		//structure.setDefaultOffset(this.offsetX, this.offsetY, this.offsetZ);
    		gen.setDefaultOffset(structure.getOffsetX() + tag.getInteger(data[OFFSET_X]), structure.getOffsetY() + tag.getInteger(data[OFFSET_Y]), structure.getOffsetZ() + tag.getInteger(data[OFFSET_Z]));
    		// adjust for structure generating centered on player's position (including height)
    		//gen.setDefaultOffset(structure.getOffsetX() + this.offsetX, structure.getOffsetY() + this.offsetY, structure.getOffsetZ() + this.offsetZ); // adjust down one for the buffer layer
    		gen.generate(world, world.rand, x, y, z);
    
    		// reset for next time
    		itemstack.stackTagCompound = null;
    	}
    
            return true;
        }
    
    private final void initNBTCompound(ItemStack itemstack)
    {
    	if (itemstack.stackTagCompound == null)
    		itemstack.stackTagCompound = new NBTTagCompound();
    
    	for (int i = 0; i < INVERT_Y; ++i) {
        		itemstack.stackTagCompound.setInteger(data[i], 0);
        	}
        	
        	itemstack.stackTagCompound.setBoolean(data[iNVERT_Y], false);
        	
        	LogHelper.log(Level.INFO, "NBT Tag initialized for ItemStructureSpawner");
    }
    
    private final void init()
    {
    	Structure structure = new Structure("Hut");
    	structure.addBlockArray(StructureArrays.blockArrayNPCHut);
    	structure.setFacing(StructureGeneratorBase.EAST);
    	// has a buffer layer on the bottom in case no ground; spawn at y-1 for ground level
    	structure.setStructureOffset(0, -1, 0);
    	structures.add(structure);
    
    	structure = new Structure("Blacksmith");
    	structure.addBlockArray(StructureArrays.blockArrayNPCBlackSmith);
    	structure.setFacing(StructureGeneratorBase.NORTH);
    	structures.add(structure);
    
    	structure = new Structure("Viking Shop");
    	structure.addBlockArray(StructureArrays.blockArrayShop);
    	structure.setFacing(StructureGeneratorBase.WEST);
    	structures.add(structure);
    
    	structure = new Structure("Redstone Dungeon");
    	structure.addBlockArray(StructureArrays.blockArrayRedstone);
    	//structure.setFacing(StructureGeneratorBase.EAST);
    	structures.add(structure);
    
    	structure = new Structure("Offset Test");
    	structure.addBlockArray(StructureArrays.blockArraySpawnTest);
    	structure.setFacing(StructureGeneratorBase.NORTH);
    	structures.add(structure);
    }
    }
    // mangled attempt at multi-threading...
    class SyncThread implements Runnable
    {
    Thread t;
    
    private final ItemStack itemstack;
    
    public SyncThread(ItemStack itemstack) {
    	t = new Thread();
    	this.itemstack = itemstack;
    	t.start();
    }
    
    @Override
    public void run()
    {
    	//synchronized (itemstack)
    	{
    		while (itemstack.stackTagCompound == null)
    		{
    			try {
    				wait();
    			} catch (InterruptedException e) {
    
    			}
    		}
    	}
    }
    }
    

     

    And my PacketHandler with custom packet class:

     

    public class SGTPacketHandler implements IPacketHandler
    {
    /** Packet IDs */
    public static final byte PACKET_NBT_ITEM = 1;
    
    @Override
    public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player)
    {
    	System.out.println("[sERVER] Received client packet.");
    	DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(packet.data));
    	byte packetType;
    
    	try {
    		packetType = inputStream.readByte();
    	} catch (IOException e) {
    		e.printStackTrace();
    		return;
    	}
    
    	switch(packetType) {
    	case PACKET_NBT_ITEM: handlePacketNBTItem(packet, (EntityPlayer) player, inputStream); break;
    	default: LogHelper.log(Level.SEVERE, "Unhandled packet exception for packet id " + packetType);
    	}
    }
    
    private void handlePacketNBTItem(Packet250CustomPayload packet, EntityPlayer player, DataInputStream inputStream)
    {
    	short size;
    
    	try {
    		size = inputStream.readShort();
    		if (size > 0) {
    			byte[] abyte = new byte[size];
    			inputStream.readFully(abyte);
    			player.getHeldItem().stackTagCompound = CompressedStreamTools.decompress(abyte);
    		}
    	} catch (IOException e) {
    		e.printStackTrace();
    		return;
    	}
    
    	//notifyAll();
    }
    }
    
    // The custom packet class:
    public class SGTPacketNBTItem
    {
    public static Packet250CustomPayload getPacket(ItemStack itemstack)
    {
    	NBTTagCompound compound = itemstack.stackTagCompound;
    	ByteArrayOutputStream bos = new ByteArrayOutputStream();
    	DataOutputStream outputStream = new DataOutputStream(bos);
    
    	try {
    		outputStream.writeByte(SGTPacketHandler.PACKET_NBT_ITEM);
    		if (compound == null) {
    			outputStream.writeShort(-1);
            } else {
                byte[] abyte = CompressedStreamTools.compress(compound);
                outputStream.writeShort((short) abyte.length);
                outputStream.write(abyte);
            }
    	} catch (Exception ex) {
    		ex.printStackTrace();
    	}
    	Packet250CustomPayload packet = new Packet250CustomPayload();
    	packet.channel = ModInfo.CHANNEL;
    	packet.data = bos.toByteArray();
    	packet.length = bos.size();
    
    	return packet;
    }
    }
    

     

     

×
×
  • Create New...

Important Information

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