Jump to content

Ticking Block Entity Null Pointer


meee39
 Share

Recommended Posts

In my mod I have a TE and on world reload the update method causes a Null Pointer Exception. Here is the error message:

[12:21:24] [Server thread/INFO] [FML]: The state engine was in incorrect state SERVER_STOPPING and forced into state SERVER_STOPPED. Errors may have been discarded.
[12:21:25] [Client thread/INFO] [STDOUT]: [net.minecraft.init.Bootstrap:printToSYSOUT:600]: ---- Minecraft Crash Report ----
// Quite honestly, I wouldn't worry myself about that.

Time: 6/11/17 12:21 PM
Description: Ticking block entity

java.lang.NullPointerException: Ticking block entity
	at com.leo.mobsuppressors.tileentity.TileEntityEnderSuppressor.update(TileEntityEnderSuppressor.java:43)
	at net.minecraft.world.World.updateEntities(World.java:1950)
	at net.minecraft.world.WorldServer.updateEntities(WorldServer.java:648)
	at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:795)
	at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:699)
	at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:156)
	at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:548)
	at java.lang.Thread.run(Thread.java:748)


A detailed walkthrough of the error, its code path and all known details is as follows:
---------------------------------------------------------------------------------------

-- Head --
Thread: Client thread
Stacktrace:
	at com.leo.mobsuppressors.tileentity.TileEntityEnderSuppressor.update(TileEntityEnderSuppressor.java:43)

-- Block entity being ticked --
Details:
	Name: minecraft:endersuppressor_tileentity // com.leo.mobsuppressors.tileentity.TileEntityEnderSuppressor
	Block type: ID #235 (tile.endersuppressor // com.leo.mobsuppressors.blocks.BlockEnderSuppressor)
	Block data value: 1 / 0x1 / 0b0001
	Block location: World: (113,63,65), Chunk: (at 1,3,1 in 7,4; contains blocks 112,0,64 to 127,255,79), Region: (0,0; contains chunks 0,0 to 31,31, blocks 0,0,0 to 511,255,511)
	Actual block type: ID #235 (tile.endersuppressor // com.leo.mobsuppressors.blocks.BlockEnderSuppressor)
	Actual block data value: 1 / 0x1 / 0b0001
Stacktrace:
	at net.minecraft.world.World.updateEntities(World.java:1950)
	at net.minecraft.world.WorldServer.updateEntities(WorldServer.java:648)

-- Affected level --
Details:
	Level name: New World
	All players: 0 total; []
	Chunk stats: ServerChunkCache: 625 Drop: 0
	Level seed: -2733871743652672072
	Level generator: ID 00 - default, ver 1. Features enabled: true
	Level generator options: 
	Level spawn location: World: (8,64,8), Chunk: (at 8,4,8 in 0,0; contains blocks 0,0,0 to 15,255,15), Region: (0,0; contains chunks 0,0 to 31,31, blocks 0,0,0 to 511,255,511)
	Level time: 1625 game time, 1625 day time
	Level dimension: 0
	Level storage version: 0x04ABD - Anvil
	Level weather: Rain time: 82026 (now: false), thunder time: 128357 (now: false)
	Level game mode: Game mode: creative (ID 1). Hardcore: false. Cheats: true
Stacktrace:
	at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:795)
	at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:699)
	at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:156)
	at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:548)
	at java.lang.Thread.run(Thread.java:748)

-- System Details --
Details:
	Minecraft Version: 1.11.2
	Operating System: Mac OS X (x86_64) version 10.12
	Java Version: 1.8.0_131, Oracle Corporation
	Java VM Version: Java HotSpot(TM) 64-Bit Server VM (mixed mode), Oracle Corporation
	Memory: 611255608 bytes (582 MB) / 1038876672 bytes (990 MB) up to 1038876672 bytes (990 MB)
	JVM Flags: 3 total; -Xincgc -Xmx1024M -Xms1024M
	IntCache: cache: 0, tcache: 0, allocated: 12, tallocated: 94
	FML: MCP 9.38 Powered by Forge 13.20.0.2294 7 mods loaded, 7 mods active
	States: 'U' = Unloaded 'L' = Loaded 'C' = Constructed 'H' = Pre-initialized 'I' = Initialized 'J' = Post-initialized 'A' = Available 'D' = Disabled 'E' = Errored
	UCHIJAAAA	minecraft{1.11.2} [Minecraft] (minecraft.jar) 
	UCHIJAAAA	mcp{9.19} [Minecraft Coder Pack] (minecraft.jar) 
	UCHIJAAAA	FML{8.0.99.99} [Forge Mod Loader] (forgeSrc-1.11.2-13.20.0.2294.jar) 
	UCHIJAAAA	forge{13.20.0.2294} [Minecraft Forge] (forgeSrc-1.11.2-13.20.0.2294.jar) 
	UCHIJAAAA	mobsuppressors{0.1 - alpha} [Mob Suppressors] (bin) 
	UCHIJAAAA	jei{4.3.5.275} [Just Enough Items] (jei_1.11.2-4.3.5.275.jar) 
	UCHIJAAAA	jeresources{0.6.2.104} [Just Enough Resources] (JustEnoughResources-1.11.2-0.6.2.104.jar) 
	Loaded coremods (and transformers): 
	Profiler Position: N/A (disabled)
	Player Count: 0 / 8; []
	Type: Integrated Server (map_client.txt)
	Is Modded: Definitely; Client brand changed to 'fml,forge'
[12:21:25] [Client thread/INFO] [STDOUT]: [net.minecraft.init.Bootstrap:printToSYSOUT:600]: #@!@# Game crashed! Crash report saved to: #@!@# ./crash-reports/crash-2017-06-11_12.21.24-server.txt
[12:21:25] [Client Shutdown Thread/INFO]: Stopping server
[12:21:25] [Client Shutdown Thread/INFO]: Saving players
[12:21:25] [Client Shutdown Thread/INFO]: Saving worlds

From the error message I guess that the only relevant class is TileEntityEnderSuppressor so that is the only one I will include (unless you need more).

public class TileEntityEnderSuppressor extends TileEntity implements ITickable, IMobSuppressorTE {
	private World world = Minecraft.getMinecraft().world;
	public BlockEnderSuppressor block;
	public boolean isPublic;
	public static final int maxTicks = 300;
	public int powerTicksLeft = 0;
	
	public ItemStackHandler itemStackHandler = new ItemStackHandler(1) {
		@Override
		protected void onContentsChanged(int slot) {
			TileEntityEnderSuppressor.this.markDirty();
		}
	};
	
	public TileEntityEnderSuppressor() {}
	
	public TileEntityEnderSuppressor(BlockEnderSuppressor block) {
		this.block = block;
		this.isPublic = true;
	}
	
	@Override
	public void update() {
		if (world.getBlockState(getPos()).getBlock() instanceof BlockEnderSuppressor != true) {
			return;
		}
		
		if (world != null) {
			Random RNG = new Random();
			world.spawnParticle(EnumParticleTypes.PORTAL, RNG.nextFloat() + pos.getX(), RNG.nextFloat() + pos.getY(), RNG.nextFloat() + pos.getZ(), 0.1, 0.1, 0.1, 0);
		}
		
		if (powerTicksLeft > 0) {
			powerTicksLeft--;
			world.setBlockState(this.getPos(), world.getBlockState(getPos()).withProperty(block.is_powered, false));
		} else {
			if (itemStackHandler.getStackInSlot(0).isEmpty()) {
				world.setBlockState(this.getPos(), world.getBlockState(getPos()).withProperty(block.is_powered, true));
			} else {
				if (itemStackHandler.getStackInSlot(0).getItem() instanceof ItemEnderPearl) {
					itemStackHandler.getStackInSlot(0).shrink(1);
					setFullPowerTicks();
				}
			}
		}
	}
	
	@Override
	public NBTTagCompound writeToNBT(NBTTagCompound compound) {
		super.writeToNBT(compound);
		
		compound.setTag("items", itemStackHandler.serializeNBT());
		
		compound.setBoolean("isPublic", isPublic);
		compound.setInteger("powerTicksLeft", powerTicksLeft);
		
		return compound;
	}
	
	@Override
	public void readFromNBT(NBTTagCompound compound) {
		super.readFromNBT(compound);
		
		if (compound.hasKey("items")) {
			itemStackHandler.deserializeNBT((NBTTagCompound)compound.getTag("items"));
		}
		
		isPublic = compound.getBoolean("isPublic");
		powerTicksLeft = compound.getInteger("powerTicksLeft");
	}

	@Override
	public boolean isPublic() {
		return isPublic;
	}

	@Override
	public void setFullPowerTicks() {
		this.powerTicksLeft = maxTicks;
	}

	@Override
	public int getPowerTicksLeft() {
		return powerTicksLeft;
	}
	
	@Override
    public boolean hasCapability(Capability<?> capability, EnumFacing facing) {
        if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
            return true;
        }
        return super.hasCapability(capability, facing);
    }

    @Override
    public <T> T getCapability(Capability<T> capability, EnumFacing facing) {
        if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
            return (T) itemStackHandler;
        }
        return super.getCapability(capability, facing);
    }
	
	public boolean canInteractWith(EntityPlayer playerIn) {
        return !isInvalid() && playerIn.getDistanceSq(pos.add(0.5D, 0.5D, 0.5D)) <= 64D;
    }
}

So what happens is if I place the block or mine it or open the GUI nothing happens and its fine. If I exit a world with this block in it, everything is fine. The problem comes when I reload the world; it crashes.

Link to comment
Share on other sites

Quote

at com.leo.mobsuppressors.tileentity.TileEntityEnderSuppressor.update(TileEntityEnderSuppressor.java:43)

Which line is line 43? (I'm assuming what you pasted doesn't start at the beginning of the file, since I don't see any imports)

 

edit:Also, this isn't a ForgeGradle issue, in the future you should post things like this right in Modder Support :)

Edited by Ugdhar
added note
Link to comment
Share on other sites

Derp.

 

I thought it wouldn't matter to post it after the imports...

 

package com.leo.mobsuppressors.tileentity;

import java.util.Random;

import com.leo.mobsuppressors.blocks.BlockEnderSuppressor;

import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemEnderPearl;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.ITickable;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.ItemStackHandler;

public class TileEntityEnderSuppressor extends TileEntity implements ITickable, IMobSuppressorTE {
	private World world = Minecraft.getMinecraft().world;
	public BlockEnderSuppressor block;
	public boolean isPublic;
	public static final int maxTicks = 300;
	public int powerTicksLeft = 0;
	
	public ItemStackHandler itemStackHandler = new ItemStackHandler(1) {
		@Override
		protected void onContentsChanged(int slot) {
			TileEntityEnderSuppressor.this.markDirty();
		}
	};
	
	public TileEntityEnderSuppressor() {}
	
	public TileEntityEnderSuppressor(BlockEnderSuppressor block) {
		this.block = block;
		this.isPublic = true;
	}
	
	@Override
	public void update() {
		if (world.getBlockState(getPos()).getBlock() instanceof BlockEnderSuppressor != true) {
			return;
		}
		
		if (world != null) {
			Random RNG = new Random();
			world.spawnParticle(EnumParticleTypes.PORTAL, RNG.nextFloat() + pos.getX(), RNG.nextFloat() + pos.getY(), RNG.nextFloat() + pos.getZ(), 0.1, 0.1, 0.1, 0);
		}
		
		if (powerTicksLeft > 0) {
			powerTicksLeft--;
			world.setBlockState(this.getPos(), world.getBlockState(getPos()).withProperty(block.is_powered, false));
		} else {
			if (itemStackHandler.getStackInSlot(0).isEmpty()) {
				world.setBlockState(this.getPos(), world.getBlockState(getPos()).withProperty(block.is_powered, true));
			} else {
				if (itemStackHandler.getStackInSlot(0).getItem() instanceof ItemEnderPearl) {
					itemStackHandler.getStackInSlot(0).shrink(1);
					setFullPowerTicks();
				}
			}
		}
	}
	
	@Override
	public NBTTagCompound writeToNBT(NBTTagCompound compound) {
		super.writeToNBT(compound);
		
		compound.setTag("items", itemStackHandler.serializeNBT());
		
		compound.setBoolean("isPublic", isPublic);
		compound.setInteger("powerTicksLeft", powerTicksLeft);
		
		return compound;
	}
	
	@Override
	public void readFromNBT(NBTTagCompound compound) {
		super.readFromNBT(compound);
		
		if (compound.hasKey("items")) {
			itemStackHandler.deserializeNBT((NBTTagCompound)compound.getTag("items"));
		}
		
		isPublic = compound.getBoolean("isPublic");
		powerTicksLeft = compound.getInteger("powerTicksLeft");
	}

	@Override
	public boolean isPublic() {
		return isPublic;
	}

	@Override
	public void setFullPowerTicks() {
		this.powerTicksLeft = maxTicks;
	}

	@Override
	public int getPowerTicksLeft() {
		return powerTicksLeft;
	}
	
	@Override
    public boolean hasCapability(Capability<?> capability, EnumFacing facing) {
        if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
            return true;
        }
        return super.hasCapability(capability, facing);
    }

    @Override
    public <T> T getCapability(Capability<T> capability, EnumFacing facing) {
        if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
            return (T) itemStackHandler;
        }
        return super.getCapability(capability, facing);
    }
	
	public boolean canInteractWith(EntityPlayer playerIn) {
        return !isInvalid() && playerIn.getDistanceSq(pos.add(0.5D, 0.5D, 0.5D)) <= 64D;
    }
}

 

Link to comment
Share on other sites

Wrong subforum.

21 minutes ago, meee39 said:

world.getBlockState(getPos()).getBlock() instanceof BlockEnderSuppressor != true

That is a very interesting way of inversing conditions. Are you aware that you can put your condition in parentheses and put a ! before them?

21 minutes ago, meee39 said:

private World world = Minecraft.getMinecraft().world

This field makes no sense whatsover. TileEntities already have a world field in them(it, conviniently, is also called world). Not only is this redundant it will also crash the server as Minecraft is a client-side only class. You do not need this field.

21 minutes ago, meee39 said:

if (world != null)

If the tileentity gets ticked(update method is called) it's world can't be null unless explicidly nullified which is not the case for vanilla or any mod that I know of. If tile's world is null and it ticks that is a severe issue on the part of the mod that nullified the world and it is their bug. Even discarding all that this check is pointless as you access tile's world object a few lines above meaning that even if it's world would be null it would crash before getting to this check.

21 minutes ago, meee39 said:

Random RNG = new Random(); world.spawnParticle(EnumParticleTypes.PORTAL, RNG.nextFloat() + pos.getX(), RNG.nextFloat() + pos.getY(), RNG.nextFloat() + pos.getZ(), 0.1, 0.1, 0.1, 0);

RNG => world.rand. No need to create new Random object each tick.

21 minutes ago, meee39 said:

public BlockEnderSuppressor block;

Why do you even need this field? You only ever access it to obtain a property instance. Those should be static. And final. You should not need an instance to obtain it.

 

The tiles are updated on both client and server. You might want to adapt your logic to that aswell since you are currently setting blockstates regardless of if it is client or server, which you should not ever do. Blockstates changes should be done on server only.

Edited by V0idWa1k3r
Link to comment
Share on other sites

Thanks! It works now. Although, as with all programming, by doing this I have discovered the problem that all fuel seems to get consumed when you leave the GUI. Also the full power ticks doesn't seem to be getting set now.

Edited by meee39
Link to comment
Share on other sites

That is because you need to sync the values between client and server. Either use custom packets, vanilla methods (SPacketUpdateTileEntity, getUpdateTag and such) or sync your data in the GUI directly if you only need it to be visible in the GUI(see GuiFurnace for an example and give me a minute to try and find a thread with a similar issue so I can link it here)

Edit: here it is

 

Edited by V0idWa1k3r
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share



×
×
  • Create New...

Important Information

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