Levels

Levels

4M Downloads

Using Levels together with Woot crashes MC

Gepett0 opened this issue ยท 24 comments

commented

Hi,

when using Levels 3.0.5 together with woot 0.3.0 on forge 1968 i get the following crash,
while running a mob factory.

Description: Ticking block entity

java.lang.NullPointerException: Ticking block entity
at com.thexfactor117.levels.leveling.AbilitySelection.getRandomizedAbilities(AbilitySelection.java:41)
at com.thexfactor117.levels.leveling.Experience.getNextLevel(Experience.java:66)
at com.thexfactor117.levels.events.EventLivingDeath.onEntityDeath(EventLivingDeath.java:75)
at net.minecraftforge.fml.common.eventhandler.ASMEventHandler_190_EventLivingDeath_onEntityDeath_LivingDeathEvent.invoke(.dynamic)
at net.minecraftforge.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:49)
at net.minecraftforge.fml.common.eventhandler.EventBus.post(EventBus.java:140)
at net.minecraftforge.common.ForgeHooks.onLivingDeath(ForgeHooks.java:486)
at net.minecraft.entity.EntityLivingBase.func_70645_a(EntityLivingBase.java:1024)
at ipsis.woot.manager.SpawnerManager.spawn(SpawnerManager.java:227)
at ipsis.woot.tileentity.TileEntityMobFactory.func_73660_a(TileEntityMobFactory.java:345)
at net.minecraft.world.World.func_72939_s(World.java:1797)
at net.minecraft.world.WorldServer.func_72939_s(WorldServer.java:618)
at net.minecraft.server.MinecraftServer.func_71190_q(MinecraftServer.java:707)
at net.minecraft.server.MinecraftServer.func_71217_p(MinecraftServer.java:611)
at net.minecraft.server.integrated.IntegratedServer.func_71217_p(IntegratedServer.java:148)
at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:469)
at java.lang.Thread.run(Thread.java:745)

commented

Hmm, so with woot, the sword is placed in like a machine, correct?

commented

No, woot actually fake-kills mob. It's a spawner without the spawning. You just get the loot and xp in item form.

commented

It just looks like Woot somehow uses a block to kill the monsters, and a sword is being used somehow for my code to even be called. Plus an instance of the player has to be using the weapon too, which is why this whole error is confusing to me.

Do you happen to know of a sword being involved at all in the process?

commented

No swords involved on my side, neither on crafting any block nor equipped.
Will post crash log to woot, too.

commented

I'm not too sure why my code is getting called then - this issue is with a ticking block returning null which would definitely be a Woot issue. I just don't know why my code is getting called.

Maybe the Woot author will have some insight.

commented

I'm the fool that wrote Woot :)
So I use a FakePlayer that is holding a sword and therefore your onEntityDeath handler will be called when I kill a mob. The chances are I'm not setting up the FakePlayer correctly, so I'll try and track down what I'm doing wrong.

So I've been digging about to try and understand what is going wrong, by adding a handler in my mod for the LivingDeathEvent. It is being called 4 times with a player holding a sword. Extracting from the nbt of the current item I get level 1, with xp 0->10->20>30 and player.worldObj.rand valid.

After the 4th event I get the following output before the exception occurs:
[20:37:34] [Server thread/INFO] [Levels]: UNKNOWN
[20:37:34] [Server thread/INFO] [Levels]: AbilitySelection level: 2
[20:37:34] [Server thread/INFO] [Levels]: Max Level Cap: 6

Looking at the exception point and your code I think it is complaining at:
int abilityLevel = ABILITY_LEVELS[level - 1].next(rand);

However I cannot see why that line is causing an exception.
Is there something about my FakePlayer and sword that is causing your rarity to be UNKNOWN and screwing things up?

commented

That lines be giving me issues before in the past too, and I'm not too sure why - usually throwing an index out of bounds exception. Something is returning null and I'm trying to figure out what is: perhaps the player is returning null? I would say it could be the level but according to your outputs it's returning like it should.

The way I handle my rarities is that they get applied by ticking through an EntityPlayer's inventory, so if that isn't a "thing" with the FakePlayer, then that would be why the rarity is returning UNKNOWN because it never actually got set.

That's what I can see so far, I guess it depends on how your FakePlayer works.

commented

I'm just using the standard Forge provided FakePlayer which is a subclass of EntityPlayerMP.

One thought however. What if the FakePlayer didn't tick such that EntityLivingUpdate isn't called?
Would that not mean that your rarity would be UNKNOWN. Then when ABILITY_LEVELS[level - 1].next(rand) is called, then ABILITY_LEVELS[level - 1] is null and that causes the exception?

I don't know if EntityLivingUpdate is called for FakePlayer or not, I've not had time to look at the source and experiment. I'll add a EntityLivingUpdate hook into my mod and give that a try later today, to verify that it is called and that there is an inventory.

commented

That's the only way I can think of it. FakePlayer must not get ticked, resulting in the exceptions. If you're going to be doing some tests through EntityLivingUpdate, that would probably shed some light onto the issue.

commented

Ran a quick experiment with a LivingUpdateEventHandler, that basically just displays if the entity is an instanceof FakePlayer and logs if it is or not. Added a breakpoint on the FakePlayer being true and the code never stopped. Log output just showed the non-FakePlayer update events.

From a quick look at the Forge FakePlayer code, onUpdate is an empty function. The onUpdate method from EntityLivingBase is the one that raises the onLivingUpdate event, so FakePlayer is overriding that,

FakePlayer->EntityPlayerMP->EntityPlayer->EntityLivingBase

So it looks like with FakePlayer you wont get the EntityLivingUpdate event.

commented

Hmm yeah I can see what it's doing now, which explains why the rarity is returning UNKNOWN. I'm trying to think if I could throw in a check for FakePlayer's and not run the code for that, maybe that could solve this issue. I guess I could throw in Woot and see if I could fix it up.

If you have any ideas let me know.

Edit: I just comitted a possible fix, just me adding a check on the fly and I have no idea if it will work. The download to this build is here. I can try and test it in a little bit if neither of y'all can, but I figured I'd link the build here anyways.

commented

That didn't fix it for me. Going by your change you make the FakePlayer check in the onLivingUpdate event, which wont be called for a FakePlayer. Do you not need it in the LivingDeathEvent to ignore deaths that are caused by a FakePlayer?

commented

Oh I see now, because LivingUpdate isn't called by FakePlayer. I can try and put it on Death and Hurt and see if that will help - I think it should fix it that way. I'll update it and link the new build here.

r3.0.7

commented

I'll give that a go later today, but going from the diff that looks like it will fix the issue, as you are now ignoring all FakePlayer caused entity deaths. I'm really hoping that this is a generic issue with FakePlayers causing deaths with swords and not something specific to Woot/Levels interaction.

commented

I tested and it still failed, but I think I know why.
The change you made was to say

if (event.getSource().getSourceOfDamage() instanceof EntityPlayer && !(event.getEntityLiving() instanceof FakePlayer))

However it is the getSourceOfDamage that needs to be an EntityPlayer but NOT a FakePlayer.
The check that you have added is that the thing that was hurt/damaged is not a FakePlayer.
All your leveling information is applied to getSourceOfDamage

So you would need to update the check in
LivingDeathEvent
LivingHurtEvent

commented

I have no idea how that mistake got passed me. Should be fixed now.

commented

Not a long term test, but switching to the new version and running for a few minutes caused no crashes. So it looks like that fixes the issue. Maybe @Gepett0 could give it a try and make sure it fixes it for him as well. My testing was on FTB Unstable with Woot, Level and Xlib added.

commented

Awesome. I'll go ahead and close this issue. If anyone finds it again just let me know.

commented

That link is giving me the 1.10-r4.0.0.jar.
I can see the 1.9.3-r3.0.8.jar but I cannot download it.

commented

Yeah that's my fault, I'm in the process of migrating to a build server and the link I've been providing links the most recent file. When I get access to my computer I'll put r3.0.8 in the releases section of the repository.

commented

Of course, thanks for all the testing too @Ipsis

Glad it seems to be working properly now @Gepett0

commented

And thanks for working with me to get to the bottom of this :)

commented

Hi,

sorry for my late response.
Just gave it a try in creative building a T3 factory with all the bestgood upgrades possible.
No crashes anymore.

TY for the good work