Mordenkainen / Technomancy

Magic and Science, what can go wrong
15 stars 8 forks source link

Time for some code armor #160

Closed Armigus closed 8 years ago

Armigus commented 8 years ago

This part of your EventRegister file needs protection:

@SubscribeEvent(priority = EventPriority.LOW) public void entityDeath(LivingDeathEvent event){ if(event.entityLiving instanceof EntityVillager && event.entityLiving.getEntityData().hasKey("treasure")){ if(!event.entityLiving.getEntityData().hasKey("seal") || !event.entityLiving.getEntityData().getBoolean("seal")){ TMItems.treasures.onTreasureDestroyed(event.entityLiving.worldObj, event.entityLiving.posX, event.entityLiving.posY, event.entityLiving.posZ, event.entityLiving, TMItems.treasures.getTreasureId(event.entityLiving.getEntityData().getString("treasure"))); } } if(event.source instanceof EntityDamageSource){ EntityDamageSource dmger = (EntityDamageSource)event.source; if(dmger.damageType=="player"){ if(((EntityPlayer)dmger.getEntity()).inventory.hasItem(TMItems.exGem)){ tryToFillGem((EntityPlayer) dmger.getEntity(), ExistenceConversion.getGem(event.entityLiving)); }else{ PlayerData.addExistencePower(dmger.getEntity().worldObj.rand, (EntityPlayer) dmger.getEntity()); } } } }

Note that certain blocks can kill mobs as if they were a player. The Dynamism Tablet from Thaumic Tinkerer and the Mob Grinder from Draconic Evolution work this way. The damage type is not enough to prove that the source is a player.

You might have to get the entity itself and test its class like so...

EntityDamageSource dmger = (EntityDamageSource)event.source; Entity source = dmger.getEntity(); if (source.getClass() == EntityPlayer.class) { EntityPlayer user = (EntityPlayer)source; if (user.inventory.hasItem(TMItems.exGem)) { tryToFillGem(user,ExistenceConversion.getGem(event.entityLiving)); }else{ PlayerData.addExistencePower(source.worldObj.rand, user); }
};

Another area you need to harden is the addExistencePower function in PlayerData:

public static void addExistencePower(World w, String userName) { NBTTagCompound data = getData(w.getPlayerEntityByName(userName)); int randVal = data.getInteger("existencelevel") * 100 - data.getInteger("rexistencelevel"); if(w.rand.nextInt(randVal)==0){ data.setInteger("existencelevel", data.getInteger("existencelevel") + 1); data.setInteger("rexistencelevel", 0); }else{ data.setInteger("rexistencelevel", data.getInteger("rexistencelevel") + 1); } }

Add this after setting randVal:

if (randVal<=0) return;

Please fix this now... I have the mob grinders and they crash every time they kill. The error is question is:

java.lang.IllegalArgumentException: bound must be positive at java.util.Random.nextInt(Random.java:388) at theflogat.technomancy.common.player.PlayerData.addExistencePower(PlayerData.java:182) at theflogat.technomancy.lib.handlers.EventRegister.entityDeath(EventRegister.java:172)

theflogat commented 8 years ago

Thank you for having identified the issue. As for your solution it's not a problem of the source not being a player but the player being a fake player thus not having the value I'm searching for.