Jump to content

Eastonium

Members
  • Posts

    151
  • Joined

  • Last visited

Posts posted by Eastonium

  1. I'm trying to create a generic tank that can hold any fluid, and has that fluid rendered on the block, as well as in the GUI.

    My current step in getting all of that to work is finding out how to properly send fluid updates to the client. I know packets have to be used for this is some way, but I've seen multiple ways of doing it.

    Here are the ways I've seen:

    Using the getDataPacket() and onDataPacket() functions (in your tile entity), but I haven't seen how/where those are supposed to be triggered.

    Using a custom packet using your mod's own packet handler. (I don't yet know how to use packets like this, and haven't seen a clean example of it.)

     

    So, how is the best way to do this?

     

  2. I've tried everything you suggested, but still no luck. Nothing has changed.

    My updated code will be on my initial post.

     

    EDIT: I have also found that if you make another mob ride this entity, kill the entity (not the mob) and relog, the mob disappears. This happens in creative mode as well.

    Is it possible it is trying to kill everything that is riding my entity?

     

    EDIT AGAIN:

    I found the source of the problem. It wasn't my entity (although it did have some other issues as jabelar pointed out).

    The issue is that I was cancelling the event when you tried to dismount this entity. However, I was not checking if me entity was dead when you tried to dismount. This, when trying to kill my entity, it would try to dismount everything, get stopped, and mess up everything.

  3. I'm currently trying to make an entity that you can hit while riding. However, when you give this entity enough damage to kill it, it is dying server-side but not client side. 

    Another peculiarity is that this issue does not occur if you're in creative mode, and if you switch to creative mode while riding the entity when should be dead, it will die and you'll dismount.

    I've done some debugging and have found that the damage update from the final blow to the entity is not getting sent to the client, but any damage updates before that are.

    This is confirmed to happen with both attacking player damage and damage from lava.

    I'll keep looking into this issue, but if someone knows what might be causing this, or how other rideable entities accomplish this, please let me know!

     

    EDIT: Current Entity Code

    public class EntityFreezeIce extends Entity {
        private static final DataParameter<Float> HEALTH = EntityDataManager.<Float>createKey(EntityFreezeIce.class, DataSerializers.FLOAT);
    
    	public EntityFreezeIce(World worldIn) {
    		super(worldIn);
    		this.preventEntitySpawning = true;
    		this.setSize(0.7F, 1.5F);
    	}
    	
    	public EntityFreezeIce(World worldIn, Entity entityIn) {
    		this(worldIn);
    		this.setPosition(entityIn.posX, entityIn.posY, entityIn.posZ);
    		this.setRotation(entityIn.rotationYaw, 0.0F);
    		this.motionX = entityIn.motionX;
    		this.motionY = entityIn.motionY;
    		this.motionZ = entityIn.motionZ;
    		this.setDamage(7.0F);
    		entityIn.startRiding(this, true);
    	}
    
    	@Override
    	protected void entityInit() {
            this.dataManager.register(HEALTH, Float.valueOf(0.0F));		
    	}
    	
        public void setDamage(float damage) {
            this.dataManager.set(HEALTH, Float.valueOf(damage));
        }
        
        public float getDamage() {
            return ((Float)this.dataManager.get(HEALTH)).floatValue();
        }
    	
    	@Nullable
    	@Override
        public AxisAlignedBB getCollisionBox(Entity entityIn) {
            return entityIn.canBePushed() ? entityIn.getEntityBoundingBox() : null;
        }
    
        @Nullable
        @Override
        public AxisAlignedBB getCollisionBoundingBox() {
            return this.getEntityBoundingBox();
        }
    
        @Override
        public boolean canBePushed() {
            return false;
        }
        
        @Override
        public boolean canBeCollidedWith() {
            return !this.isDead;
        }
        
        @Override
    	public boolean canRiderInteract() {
            return !this.isDead;
        }
    
        @Override
        public double getMountedYOffset() {
            return 0.0D;
        }
        
        @Override
        public boolean attackEntityFrom(DamageSource source, float amount) {
            NuiCraft.logger.log(Level.INFO, world.isRemote + " " + this.isDead + " " + this.getDamage());
            if (!this.world.isRemote && !this.isDead) {
                if (this.isEntityInvulnerable(source)) {
                    return false;
                } else {
                    this.setBeenAttacked();
                    this.setDamage(this.getDamage() - amount);
                    boolean fromCreativePlayer = source.getTrueSource() instanceof EntityPlayer && 
                    		((EntityPlayer)source.getTrueSource()).capabilities.isCreativeMode;
                    if (/*fromCreativePlayer || */this.getDamage() <= 0.0F) {
                    	this.setDead();
                    }
                    NuiCraft.logger.log(Level.INFO, world.isRemote + " " + this.isDead + " " + this.getDamage());
                    return true;
                }
            } else {
                return true;
            }
        }
        
        @Override
    	protected void readEntityFromNBT(NBTTagCompound compound) {
    		this.setDamage(compound.getFloat("health"));
    	}
    
    	@Override
    	protected void writeEntityToNBT(NBTTagCompound compound) {
    		compound.setFloat("health", this.getDamage());		
    	}
    }

     

    SOLUTION:

    I was cancelling the dismount event for this entity, but did not include a check to see if this entity was dead. Solved by only cancelling the dismount event if my entity was still alive.

     

  4. First, I believe "recipes" is correct, as that is what I am using currently. Either that or both "recipe" and "recipes" works?

    I just tested what you have here, and can confirm that my test recipe (basically identical) also did not load, and did not error either. You're not crazy!

    I have a similar recipe that uses a shaped ore recipe that works though, so try changing the recipe type to "forge:ore_shaped".

    If it works, I'm guessing you might have another problem: the recipe book will try to place the items in like "xxx", "x--", "---". If it does, there are a couple problems with forge that need to be fixed.

     

  5. Finally, someone replied!

     

    When are you getting the infinite loop? (hopper-pull, shift-click...)

    Also, I made my modifications to the mergeItemStack() function when I came across problems while shift-clicking, and I tested it and it worked fine for me. How is shift-clicking not working for you?

     

    I'm determined to get this added to forge (hopefully) now that I know others wish this were a thing.

     

  6. How are we supposed to help you without seeing your code and assets?

     

    I was more or less hoping he had the same problem I have and that if not I could compare my code to his if he got his working.

    Which more or less (I say that a lot) worked, my problem was also in my blockstates file, on the same line even.

     

    I had misspelled the name of my liquid after "fluid":

     

    Thanks for your reply

  7. I recently added a slot to a container I had, and overrided the getSlotStackLimit() function.

    However, when I shift-clicked items from my inventory, the value I set in getSlotStackLimit() was completely ignored.

     

    I ended up having to override the mergeItemStack() function in my container class to account for the slot stack limit.

    I think this would be a good thing to change for all instances however, and given forge already changes the mergeItemStack() function to make sure that the item (to put in) is valid for the slot, I don't see why this shouldn't be added.

     

    Here's the new version of the function that I came up with:

    //Changed to be sensitive to Slot stack limits
    @Override
    protected boolean mergeItemStack(ItemStack stack, int startIndex, int endIndex, boolean reverseDirection){
        boolean flag = false;
        int i = startIndex;
        if (reverseDirection) i = endIndex - 1;
        
        if (stack.isStackable()){
            while (stack.stackSize > 0 && (!reverseDirection && i < endIndex || reverseDirection && i >= startIndex)){
                Slot slot = (Slot)this.inventorySlots.get(i);
                ItemStack itemstack = slot.getStack();
                int maxLimit = Math.min(stack.getMaxStackSize(), slot.getSlotStackLimit());
                
                if (itemstack != null && areItemStacksEqual(stack, itemstack)){
                    int j = itemstack.stackSize + stack.stackSize;
                    if (j <= maxLimit){
                        stack.stackSize = 0;
                        itemstack.stackSize = j;
                        slot.onSlotChanged();
                        flag = true;
                        
                    }else if (itemstack.stackSize < maxLimit){
                        stack.stackSize -= maxLimit - itemstack.stackSize;
                        itemstack.stackSize = maxLimit;
                        slot.onSlotChanged();
                        flag = true;
                    }
                }
                if (reverseDirection){ 
                	--i;
                }else ++i;
            }
        }
        if (stack.stackSize > 0){
            if (reverseDirection){
                i = endIndex - 1;
            }else i = startIndex;
    
            while (!reverseDirection && i < endIndex || reverseDirection && i >= startIndex){
                Slot slot1 = (Slot)this.inventorySlots.get(i);
                ItemStack itemstack1 = slot1.getStack();
    
                if (itemstack1 == null && slot1.isItemValid(stack)){ // Forge: Make sure to respect isItemValid in the slot.
                	if(stack.stackSize <= slot1.getSlotStackLimit()){
                	    slot1.putStack(stack.copy());
                        slot1.onSlotChanged();
                        stack.stackSize = 0;
                        flag = true;
                        break;
                	}else{
                	    itemstack1 = stack.copy();
                	    stack.stackSize -= slot1.getSlotStackLimit();
                        itemstack1.stackSize = slot1.getSlotStackLimit();
                        slot1.putStack(itemstack1);
                        slot1.onSlotChanged();
                        flag = true;
                	}                    
                }
                if (reverseDirection){
                    --i;
                }else ++i;
            }
        }
        return flag;
    }

    I'm not currently using 4 spaces or the other formatting stuff, but I can change that if need be.

  8. I've been updating my mod from 1.8.8 to 1.10.2 the last couple days (boy, is it easy compared to most updates), but I've come across multiple instances where I'm either using or overriding deprecated functions.

    For example:

    using GameRegistry.registerBlock(...)

    using GameRegistry.registerItem(...)

    overriding Item.getItem(...)

    overriding Block.isFullCube(...)

    **https://github.com/Eastonium/Nuicraft**

     

     

    I know that I should update the GameRegsitry.registerBlock/Item(...) ones, but should I worry about the ones i'm overriding?

     

    Also, despite the deprecated functions, my mod works 100% as far as I have tested.

     

    Thank you in advance for your help

     

  9. I'm working on making some armor similar to leather in that it can be colored with dyes.
    So far, I have the Item side of things working, and the sprite gets colored properly.
    How would I go about getting the armor to be colored as well? I don't know where to start even after looking at the vanilla code.
    Also, would this change if I'm using a custom model for the armor?
    Item Class:
    public class ItemMask extends ItemArmor {
    public static final int DEFAULT_COLOR = 11324652;
    
    public ItemMask(){
    	super(ArmorMaterial.LEATHER, 0, 0);
    	//this.hasSubtypes = true;
    	this.setMaxDamage(0);
    	this.setCreativeTab(Bionicle.bioMaskTab);
    }
    
    @Override
    public String getArmorTexture(ItemStack stack, Entity entity, int slot, String layer){
    	return Bionicle.MODID + ":textures/models/masks/" + this.getUnlocalizedName().substring(13) + "_5.png";
    }
    
    /*@SideOnly(Side.CLIENT)
    @Override
    public ModelBiped getArmorModel(EntityLivingBase entityLiving, ItemStack itemStack, int armorSlot, ModelBiped _default){
    	ModelBiped armorModel = null;
    	if(itemStack != null){
    		if(itemStack.getItem() instanceof ItemMataMask){
    			if(this == Bionicle.maskMataAkaku){
    				armorModel = Bionicle.proxy.getArmorModel(0);//Akaku Model
    			}else armorModel = Bionicle.proxy.getArmorModel(-1);//Generic Model
    		}
    	}
    	if(armorModel != null){
    		armorModel.bipedHead.showModel = false;
    		armorModel.bipedHeadwear.showModel = armorSlot == 0;
    		armorModel.bipedBody.showModel  = false;
    		armorModel.bipedRightArm.showModel  = false;
    		armorModel.bipedLeftArm.showModel  = false;
    		armorModel.bipedRightLeg.showModel  = false;
    		armorModel.bipedLeftLeg.showModel  = false;
    
    		armorModel.isSneak = entityLiving.isSneaking();
    		armorModel.isRiding = entityLiving.isRiding();
    		armorModel.isChild = entityLiving.isChild();
    		armorModel.heldItemRight = entityLiving.getEquipmentInSlot(0) != null ? 1 :0;
    		if(entityLiving instanceof EntityPlayer){
    			armorModel.aimedBow =((EntityPlayer)entityLiving).getItemInUseDuration() > 2;
    		}
    		return armorModel;
    	}
    	return null;
    }*/
    
    @Override
    public boolean hasColor(ItemStack stack){
    	return !stack.hasTagCompound() ? false : (!stack.getTagCompound().hasKey("display", 10) ? false : stack.getTagCompound().getCompoundTag("display").hasKey("color", 3));
    }
    
    @Override
    public int getColor(ItemStack stack){
    	NBTTagCompound nbttagcompound = stack.getTagCompound();
    	if (nbttagcompound != null){
    		NBTTagCompound nbttagcompound1 = nbttagcompound.getCompoundTag("display");
    		if (nbttagcompound1 != null && nbttagcompound1.hasKey("color", 3)){
    			return nbttagcompound1.getInteger("color");
    		}
    	}
    	return DEFAULT_COLOR;
    }
    
    public void removeColor(ItemStack stack){
    	NBTTagCompound nbttagcompound = stack.getTagCompound();
    	if (nbttagcompound != null){
    		NBTTagCompound nbttagcompound1 = nbttagcompound.getCompoundTag("display");
    		if (nbttagcompound1.hasKey("color")){
    			nbttagcompound1.removeTag("color");
    		}
    	}
    }
    
    public void setColor(ItemStack stack, int color){
    	NBTTagCompound nbttagcompound = stack.getTagCompound();
    	if (nbttagcompound == null){
    		nbttagcompound = new NBTTagCompound();
    		stack.setTagCompound(nbttagcompound);
    	}
    	NBTTagCompound nbttagcompound1 = nbttagcompound.getCompoundTag("display");
    	if (!nbttagcompound.hasKey("display", 10)){
    		nbttagcompound.setTag("display", nbttagcompound1);
    	}
    	nbttagcompound1.setInteger("color", color);
    }
    }
    

     

    Any *useful* help would be appreciated!

     

     

    EDIT: Finally Figured it out!

    After finding some very useful information from Draco18s on other threads, I found my problem. (Thanks indirectly)

    I initially tried creating a texture that was completely transparent with "_overlay" in the name like leather armor has, but that didn't work.

    HERES THE KEY TO GET THIS TO WORK EVERYBODY:

    In your getArmorTexture() function if you always return the texture you're wanting to have colored, then it will also use that for the overlay texture, which doesn't get colored.

    The way to avoid that is to add a null check on the String argument for the function. When rendering normally it passes in null, but for overlay it passes the string "overlay".

    So don't do this:

    @Override
    public String getArmorTexture(ItemStack stack, Entity entity, int slot, String layer){
    	return "MODID:some/path/to/your/colorized/texture.png";
    }

    DO THIS:

    @Override
    public String getArmorTexture(ItemStack stack, Entity entity, int slot, String layer){
    	if(layer == null){
    		return "MODID:some/path/to/your/colorized/texture.png";
    	}else return "MODID:some/path/to/a/blank/texture.png";
    }

     

    I hope people find this and use it!!

  10. I have a tank implemented on my tile entity, but the client isn't getting updated when I remove fluid from the tank bit by bit, but it does work when I fill the tank completely from being empty.

     

    Here's my update function from my TileEntity/TileInventory class.

    @Override
    public void update(){
    	boolean hasLava = this.hasLava();
    	int lavaAmount = this.tank.getFluidAmount();
    	boolean needsUpdate = false;
    
                   //When I print out "lavaAmount" here, I get either 0/1000 (empty/full) when run by the client, but the actual amount when run by the server
    
    	/*if(this.burnTimeRemaining > 0){
    		--this.burnTimeRemaining;
    	}*/
    	if(!this.worldObj.isRemote){
    		if(!hasLava && this.forgeItemstacks[FIRST_FUEL_SLOT] != null && this.forgeItemstacks[FIRST_FUEL_SLOT].getItem() == Items.lava_bucket){//TODO Change to include all items that hold fluids
    			this.fill(null, new FluidStack(FluidRegistry.LAVA, FluidContainerRegistry.BUCKET_VOLUME), true);
    			this.forgeItemstacks[FIRST_FUEL_SLOT] = this.forgeItemstacks[FIRST_FUEL_SLOT].getItem().getContainerItem(forgeItemstacks[FIRST_FUEL_SLOT]);
    		}
    		if(/*this.secondsOfFuelRemaining() > 0*/ hasLava && this.canSmelt()){
    			this.tank.drain(5, true);
    			++this.cookTime;
    			if(this.cookTime == COOK_TIME_FOR_COMPLETION){
    				this.cookTime = 0;
    				this.smeltItem();
    				needsUpdate = true;
    			}
    		}
    		if (lavaAmount != this.tank.getFluidAmount()){
    			needsUpdate = true;
    			//TODO BlockMaskForge.updateFurnaceBlockState(this.isBurning(), this.worldObj, this.pos.getX(), this.pos.getY(), this.pos.getX());
    		}
    	}
    
    	if (needsUpdate){
    		this.markDirty();
    	}
    }

     

    Is there something I'm missing here?

    I'm sure you'll probably need more information to help me solve this, just let me know what you need.

     

    EDIT: Solved it myself. Turns out when I was updating the IInventory setFeild() function, I was always adding fluid rather than adding/removing depending on what it should be.

     

    So I changed this:

    @Override
    public void setField(int id, int value){
    	if(id == COOK_FIELD_ID){
    		cookTime = (short)value;
    	}else if(id == FUEL_AMOUNT_FIELD_ID){
    		this.fill(null, new FluidStack(FluidRegistry.LAVA, value), true);
    	}else{
    		System.err.println("Invalid field ID in TileInventorySmelting.setField:" + id);
    	}
    }

     

    To this:

    @Override
    public void setField(int id, int value){
    	if(id == COOK_FIELD_ID){
    		cookTime = (short)value;
    	}else if(id == FUEL_AMOUNT_FIELD_ID){
    		FluidStack flStack = new FluidStack(FluidRegistry.LAVA, Math.abs(this.tank.getFluidAmount() - value));
    		if(value > this.tank.getFluidAmount()){
    			this.fill(null, flStack, true);
    		}else if(value < this.tank.getFluidAmount()){
    			this.drain(null, flStack, true);
    		}
    	}else{
    		System.err.println("Invalid field ID in TileInventorySmelting.setField:" + id);
    	}
    }

  11. Alright, got that set up.

    I'm having another issue with it though. I'm getting the pink/black checkered block for the specific damaged item, but not for any other damages.

     

    Here's what I have:

    public ModelResourceLocation getModelLocation(ItemStack stack) {
    	if(stack.getItem() == Bionicle.heatstoneLighter){
    		if(stack.getItemDamage() == 128){
    			return new ModelResourceLocation(Bionicle.heatstoneLighter.getRegistryName() + "_spent", "inventory");
    		}else return new ModelResourceLocation(Bionicle.heatstoneLighter.getRegistryName(), "inventory");
    	}else return null;
    }

    I have the _spent version of the model in the same folder right next to the regular one (and spelled correctly), but like I said, its not showing up.

    And I've confirmed that it is getting to that point where it returns the _spent version of the ModelResourceLocation.

    Its not throwing any errors in the console either.

×
×
  • Create New...

Important Information

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