Reputation: 21
Currently trying to create a potion effect that once it runs out of time, applies other potion effects to the player. Seemed simple enough yet I found a few errors and bugs trying to accomplish this,
Directly trying to add the effect
@Override
public void performEffect(EntityLivingBase entity, int amplifier){
if (entity instanceof EntityPlayer)
{
EntityPlayer player = (EntityPlayer)entity;
if(player != null){
if(player.getActivePotionEffect(PotionRegistry.effectBuzz) != null){
int duraction = player.getActivePotionEffect(PotionRegistry.effectBuzz).getDuration();
if(duration <= 2){
player.addPotionEffect(new PotionEffect(MobEffects.WEAKNESS, 1200));
}
}
}
}
}
Needless to say this produces this error
[16:10:04] [Server thread/ERROR]: Encountered an unexpected exception net.minecraft.util.ReportedException: Ticking player at net.minecraft.network.NetworkSystem.networkTick(NetworkSystem.java:212) ~[NetworkSystem.class:?] at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:807) ~[MinecraftServer.class:?] at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:688) ~[MinecraftServer.class:?] at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:156) ~[IntegratedServer.class:?] at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:537) [MinecraftServer.class:?] at java.lang.Thread.run(Unknown Source) [?:1.8.0_161] Caused by: java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextNode(Unknown Source) ~[?:1.8.0_161] at java.util.HashMap$KeyIterator.next(Unknown Source) ~[?:1.8.0_161] at net.minecraft.entity.EntityLivingBase.updatePotionEffects(EntityLivingBase.java:650) ~[EntityLivingBase.class:?] at net.minecraft.entity.EntityLivingBase.onEntityUpdate(EntityLivingBase.java:383) ~[EntityLivingBase.class:?] at net.minecraft.entity.Entity.onUpdate(Entity.java:436) ~[Entity.class:?] at net.minecraft.entity.EntityLivingBase.onUpdate(EntityLivingBase.java:2144) ~[EntityLivingBase.class:?] at net.minecraft.entity.player.EntityPlayer.onUpdate(EntityPlayer.java:260) ~[EntityPlayer.class:?] at net.minecraft.entity.player.EntityPlayerMP.onUpdateEntity(EntityPlayerMP.java:345) ~[EntityPlayerMP.class:?] at net.minecraft.network.NetHandlerPlayServer.update(NetHandlerPlayServer.java:174) ~[NetHandlerPlayServer.class:?] at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher$1.update(NetworkDispatcher.java:216) ~[NetworkDispatcher$1.class:?] at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:309) ~[NetworkManager.class:?] at net.minecraft.network.NetworkSystem.networkTick(NetworkSystem.java:197) ~[NetworkSystem.class:?] ... 5 more
Where as if I run this in a tick event
In CommonProxy
MinecraftForge.EVENT_BUS.register(new EventManager());
And then For the EventManager itself
public class EventManager {
public static PotionEffect potion = new PotionEffect(MobEffects.WEAKNESS, 1200);
public static PotionEffect potion2 = new PotionEffect(MobEffects.HUNGER, 600);
public static PotionEffect potion3 = new PotionEffect(MobEffects.UNLUCK, 1200);
@SubscribeEvent
public void onTick(WorldTickEvent event){
EntityPlayer player = Minecraft.getMinecraft().thePlayer;
World world = Minecraft.getMinecraft().theWorld;
if(player != null){
boolean hasEffect = player.isPotionActive(PotionRegistry.effectBuzz);
int applyIt = 0;
if(hasEffect){
applyIt = 1;
} else if(!player.isPotionActive(potion.getPotion()) && applyIt == 1){
applyIt = 2;
} else {
applyIt = 0;
}
if(player != null && applyIt == 2){
player.addPotionEffect(potion);
}
}
}
}
This works, yet the effects are infinite.
Upvotes: 1
Views: 3326
Reputation: 28742
You're performing your action whilst the potion effects are being looped. This is akin to modifying an array whilst iterating it. Don't do that.
Also, don't perform actions like potion effects client side. The ONLY thing to do client side is graphics and user input/output.
Things like potions must be handled on the server, otherwise the server will overwrite your actions on the next update packet.
Just set a flag in your ExtendPlayer entity, and then onTick or player update event check for that flag existance and then add the potions.
@Override
public void performEffect(EntityLivingBase entity, int amplifier){
if (entity instanceof EntityPlayer)
{
EntityPlayer player = (EntityPlayer)entity;
if(player != null){
if(player.getActivePotionEffect(PotionRegistry.effectBuzz) != null){
int duraction = player.getActivePotionEffect(PotionRegistry.effectBuzz).getDuration();
if(duration <= 2){
ExtendedPlayer ePlayer = ExtendedPlayer.get(player);
ePlayer.enableBuzz();
}
}
}
}
}
Something akin to your Extended player
public class ExtendedPlayer implements IExtendedEntityProperties {
... Extended player setup here
protected boolean startBuzz = false;
public void enableBuzz()
{
this.startBuzz = true;
}
public static final ExtendedPlayer get(EntityPlayer player) {
return (ExtendedPlayer) player.getExtendedProperties("MuddymansExtendedPlayer");
}
public EntityPlayer getPlayer() {
return this.player;
}
/**
* Updates anything that needs to be updated each tick
* NOT called automatically, so you must call it yourself from LivingUpdateEvent or a TickHandler
*/
public void onUpdate() {
if(!player.worldObj.isRemote) {
if(this.enableBuzz) {
Player player = this.getPlayer()
player.addPotionEffect(new PotionEffect(MobEffects.WEAKNESS, 1200));
player.addPotionEffect(new PotionEffect(MobEffects.HUNGER, 600));
player.addPotionEffect(new PotionEffect(MobEffects.UNLUCK, 1200));
this.startBuzz = false;
}
}
}
}
Call the exteded player update event from an event handler
@SubscribeEvent
public void livingTick(final LivingUpdateEvent event) {
if (event.entity != null && event.entity instanceof EntityPlayer) {
if(!event.entity.isDead) {
ExtendedPlayer.get((EntityPlayer)event.entity).onUpdate();
}
}
Upvotes: 2