From b684310be8a401e64070a324de1402f61348b7bb Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Mon, 17 Sep 2018 13:27:13 +0900 Subject: [PATCH] Move battle attacks to main thread, minor fixes Battle attacks moved to main thread for stability (fixes possible concurrent modification exception). --- .../client/ClientProxy.java | 14 +++ .../TurnBasedMinecraft/common/Battle.java | 108 +++++++++++------- .../common/CommonProxy.java | 10 ++ .../networking/PacketBattleMessage.java | 72 ++++-------- 4 files changed, 113 insertions(+), 91 deletions(-) diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/client/ClientProxy.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/client/ClientProxy.java index f3186af..2cb89fb 100644 --- a/src/main/java/com/seodisparate/TurnBasedMinecraft/client/ClientProxy.java +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/client/ClientProxy.java @@ -7,6 +7,8 @@ import com.seodisparate.TurnBasedMinecraft.common.Config; import com.seodisparate.TurnBasedMinecraft.common.TurnBasedMinecraftMod; import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.util.text.TextComponentString; public class ClientProxy extends CommonProxy { @@ -141,4 +143,16 @@ public class ClientProxy extends CommonProxy { this.config = config; } + + @Override + public void displayString(String message) + { + Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(message)); + } + + @Override + public Entity getEntityByID(int id) + { + return Minecraft.getMinecraft().world.getEntityByID(id); + } } diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Battle.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Battle.java index 2c98919..5ae47bc 100644 --- a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Battle.java +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Battle.java @@ -26,6 +26,7 @@ import net.minecraft.item.ItemPotion; import net.minecraft.item.ItemSplashPotion; import net.minecraft.item.ItemStack; import net.minecraft.util.DamageSource; +import net.minecraftforge.fml.common.FMLCommonHandler; public class Battle { @@ -652,26 +653,27 @@ public class Battle // have player look at attack target final Entity nextEntity = next.entity; final Entity targetEntity = target.entity; + final EntityInfo targetEntityInfo = target.entityInfo; next.entity.getServer().addScheduledTask(() -> { ((EntityPlayerMP)nextEntity).connection.setPlayerLocation(nextEntity.posX, nextEntity.posY, nextEntity.posZ, Utility.yawDirection(nextEntity.posX, nextEntity.posZ, targetEntity.posX, targetEntity.posZ), Utility.pitchDirection(nextEntity.posX, nextEntity.posY, nextEntity.posZ, targetEntity.posX, targetEntity.posY, targetEntity.posZ)); - }); - TurnBasedMinecraftMod.attackingEntity = next.entity; - TurnBasedMinecraftMod.attackingDamage = 0; - ((EntityPlayer)next.entity).attackTargetEntityWithCurrentItem(target.entity); - TurnBasedMinecraftMod.attackingEntity = null; - sendMessageToAllPlayers(PacketBattleMessage.MessageType.ATTACK, next.entity.getEntityId(), target.entity.getEntityId(), TurnBasedMinecraftMod.attackingDamage); - if(!(target.entity instanceof EntityPlayer) && target.entityInfo.defenseDamage > 0) - { - if((int)(Math.random() * 100) < target.entityInfo.defenseDamageProbability) + TurnBasedMinecraftMod.attackingEntity = nextEntity; + TurnBasedMinecraftMod.attackingDamage = 0; + ((EntityPlayer)nextEntity).attackTargetEntityWithCurrentItem(targetEntity); + TurnBasedMinecraftMod.attackingEntity = null; + sendMessageToAllPlayers(PacketBattleMessage.MessageType.ATTACK, nextEntity.getEntityId(), targetEntity.getEntityId(), TurnBasedMinecraftMod.attackingDamage); + if(!(targetEntity instanceof EntityPlayer) && targetEntityInfo.defenseDamage > 0) { - // defense damage - DamageSource defenseDamageSource = DamageSource.causeMobDamage((EntityLivingBase)target.entity); - TurnBasedMinecraftMod.attackingEntity = target.entity; - next.entity.attackEntityFrom(defenseDamageSource, target.entityInfo.defenseDamage); - TurnBasedMinecraftMod.attackingEntity = null; - sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENSE_DAMAGE, target.entity.getEntityId(), next.entity.getEntityId(), target.entityInfo.defenseDamage); + if((int)(Math.random() * 100) < targetEntityInfo.defenseDamageProbability) + { + // defense damage + DamageSource defenseDamageSource = DamageSource.causeMobDamage((EntityLivingBase)targetEntity); + TurnBasedMinecraftMod.attackingEntity = targetEntity; + nextEntity.attackEntityFrom(defenseDamageSource, targetEntityInfo.defenseDamage); + TurnBasedMinecraftMod.attackingEntity = null; + sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENSE_DAMAGE, targetEntity.getEntityId(), nextEntity.getEntityId(), targetEntityInfo.defenseDamage); + } } - } + }); } else { @@ -741,32 +743,39 @@ public class Battle damageAmount += (int)(Math.random() * (next.entityInfo.attackVariance * 2 + 1)) - next.entityInfo.attackVariance; } // attack - TurnBasedMinecraftMod.attackingEntity = next.entity; - target.entity.attackEntityFrom(damageSource, damageAmount); - TurnBasedMinecraftMod.attackingEntity = null; - sendMessageToAllPlayers(PacketBattleMessage.MessageType.ATTACK, next.entity.getEntityId(), target.entity.getEntityId(), damageAmount); - if(!(target.entity instanceof EntityPlayer) && target.entityInfo.defenseDamage > 0) - { - if((int)(Math.random() * 100) < target.entityInfo.defenseDamageProbability) + final Entity nextEntity = next.entity; + final EntityInfo nextEntityInfo = next.entityInfo; + final Entity targetEntity = target.entity; + final EntityInfo targetEntityInfo = target.entityInfo; + final int finalDamageAmount = damageAmount; + next.entity.getServer().addScheduledTask(() -> { + TurnBasedMinecraftMod.attackingEntity = nextEntity; + targetEntity.attackEntityFrom(damageSource, finalDamageAmount); + TurnBasedMinecraftMod.attackingEntity = null; + sendMessageToAllPlayers(PacketBattleMessage.MessageType.ATTACK, nextEntity.getEntityId(), targetEntity.getEntityId(), finalDamageAmount); + if(!(targetEntity instanceof EntityPlayer) && targetEntityInfo.defenseDamage > 0) { - // defense damage - DamageSource defenseDamageSource = DamageSource.causeMobDamage((EntityLivingBase)target.entity); - TurnBasedMinecraftMod.attackingEntity = target.entity; - next.entity.attackEntityFrom(defenseDamageSource, target.entityInfo.defenseDamage); - TurnBasedMinecraftMod.attackingEntity = null; - sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENSE_DAMAGE, target.entity.getEntityId(), next.entity.getEntityId(), target.entityInfo.defenseDamage); + if((int)(Math.random() * 100) < targetEntityInfo.defenseDamageProbability) + { + // defense damage + DamageSource defenseDamageSource = DamageSource.causeMobDamage((EntityLivingBase)targetEntity); + TurnBasedMinecraftMod.attackingEntity = targetEntity; + nextEntity.attackEntityFrom(defenseDamageSource, targetEntityInfo.defenseDamage); + TurnBasedMinecraftMod.attackingEntity = null; + sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENSE_DAMAGE, targetEntity.getEntityId(), nextEntity.getEntityId(), targetEntityInfo.defenseDamage); + } } - } - // attack effect - if(next.entityInfo.attackEffect != EntityInfo.Effect.UNKNOWN && next.entityInfo.attackEffectProbability > 0) - { - int effectChance = (int)(Math.random() * 100); - if(effectChance < next.entityInfo.attackEffectProbability) + // attack effect + if(nextEntityInfo.attackEffect != EntityInfo.Effect.UNKNOWN && nextEntityInfo.attackEffectProbability > 0) { - next.entityInfo.attackEffect.applyEffectToEntity((EntityLivingBase)target.entity); - sendMessageToAllPlayers(PacketBattleMessage.MessageType.WAS_AFFECTED, next.entity.getEntityId(), target.entity.getEntityId(), 0, next.entityInfo.attackEffect.getAffectedString()); + int effectChance = (int)(Math.random() * 100); + if(effectChance < nextEntityInfo.attackEffectProbability) + { + nextEntityInfo.attackEffect.applyEffectToEntity((EntityLivingBase)targetEntity); + sendMessageToAllPlayers(PacketBattleMessage.MessageType.WAS_AFFECTED, nextEntity.getEntityId(), targetEntity.getEntityId(), 0, nextEntityInfo.attackEffect.getAffectedString()); + } } - } + }); } else { @@ -892,13 +901,20 @@ public class Battle if(targetItem instanceof ItemFood) { sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getEntityId(), 0, PacketBattleMessage.UsedItemAction.USED_FOOD.getValue(), targetItemStack.getDisplayName()); - ((ItemFood)targetItem).onItemUseFinish(targetItemStack, next.entity.world, (EntityLivingBase)next.entity); + final Entity nextEntity = next.entity; + next.entity.getServer().addScheduledTask(() -> { + ((ItemFood)targetItem).onItemUseFinish(targetItemStack, nextEntity.world, (EntityLivingBase)nextEntity); + }); } else if(targetItem instanceof ItemPotion && !(targetItem instanceof ItemSplashPotion) && !(targetItem instanceof ItemLingeringPotion)) { sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getEntityId(), 0, PacketBattleMessage.UsedItemAction.USED_POTION.getValue(), targetItemStack.getDisplayName()); - ((ItemPotion)targetItem).onItemUseFinish(targetItemStack, next.entity.world, (EntityLivingBase)next.entity); - ((EntityPlayer)next.entity).inventory.setInventorySlotContents(next.itemToUse, new ItemStack(Items.GLASS_BOTTLE)); + final Entity nextEntity = next.entity; + final int nextItemToUse = next.itemToUse; + next.entity.getServer().addScheduledTask(() -> { + ((ItemPotion)targetItem).onItemUseFinish(targetItemStack, nextEntity.world, (EntityLivingBase)nextEntity); + ((EntityPlayer)nextEntity).inventory.setInventorySlotContents(nextItemToUse, new ItemStack(Items.GLASS_BOTTLE)); + }); } else { @@ -911,7 +927,11 @@ public class Battle sendMessageToAllPlayers(PacketBattleMessage.MessageType.SWITCHED_ITEM, next.entity.getEntityId(), 0, 0); break; } - ((EntityPlayer)next.entity).inventory.currentItem = next.itemToUse; + final Entity nextEntity = next.entity; + final int nextItemToUse = next.itemToUse; + next.entity.getServer().addScheduledTask(() -> { + ((EntityPlayer)nextEntity).inventory.currentItem = nextItemToUse; + }); sendMessageToAllPlayers(PacketBattleMessage.MessageType.SWITCHED_ITEM, next.entity.getEntityId(), 0, 1); break; } @@ -929,7 +949,9 @@ public class Battle undecidedCount.set(players.size()); healthCheck(); isCreativeCheck(); - sendMessageToAllPlayers(PacketBattleMessage.MessageType.TURN_END, 0, 0, 0); + FMLCommonHandler.instance().getMinecraftServerInstance().addScheduledTask(() -> { + sendMessageToAllPlayers(PacketBattleMessage.MessageType.TURN_END, 0, 0, 0); + }); break; } // case ACTION default: diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/CommonProxy.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/CommonProxy.java index 224da94..2bf1b54 100644 --- a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/CommonProxy.java +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/CommonProxy.java @@ -2,6 +2,9 @@ package com.seodisparate.TurnBasedMinecraft.common; import org.apache.logging.log4j.Logger; +import net.minecraft.entity.Entity; +import net.minecraftforge.fml.common.FMLCommonHandler; + public class CommonProxy { public void setBattleGuiTime(int timeRemaining) {} @@ -29,4 +32,11 @@ public class CommonProxy public void typeEnteredBattle(String type) {} public void setConfig(Config config) {} + + public void displayString(String message) {} + + public Entity getEntityByID(int id) + { + return FMLCommonHandler.instance().getMinecraftServerInstance().getEntityWorld().getEntityByID(id); + } } diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketBattleMessage.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketBattleMessage.java index 8330031..2de9f30 100644 --- a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketBattleMessage.java +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketBattleMessage.java @@ -7,11 +7,9 @@ import com.seodisparate.TurnBasedMinecraft.common.Battle; import com.seodisparate.TurnBasedMinecraft.common.TurnBasedMinecraftMod; import io.netty.buffer.ByteBuf; -import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.scoreboard.ScorePlayerTeam; -import net.minecraft.util.text.TextComponentString; import net.minecraftforge.fml.common.network.ByteBufUtils; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; @@ -150,7 +148,7 @@ public class PacketBattleMessage implements IMessage @Override public IMessage onMessage(PacketBattleMessage message, MessageContext ctx) { - Entity fromEntity = Minecraft.getMinecraft().world.getEntityByID(message.entityIDFrom); + Entity fromEntity = TurnBasedMinecraftMod.commonProxy.getEntityByID(message.entityIDFrom); String from = "Unknown"; if(fromEntity != null) { @@ -186,7 +184,7 @@ public class PacketBattleMessage implements IMessage } } } - Entity toEntity = Minecraft.getMinecraft().world.getEntityByID(message.entityIDTo); + Entity toEntity = TurnBasedMinecraftMod.commonProxy.getEntityByID(message.entityIDTo); String to = "Unknown"; if(toEntity != null) { @@ -226,8 +224,7 @@ public class PacketBattleMessage implements IMessage switch(message.messageType) { case ENTERED: - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - from + " entered battle!")); + TurnBasedMinecraftMod.commonProxy.displayString(from + " entered battle!"); if(TurnBasedMinecraftMod.currentBattle == null || TurnBasedMinecraftMod.currentBattle.getId() != message.amount) { TurnBasedMinecraftMod.currentBattle = new Battle(message.amount, null, null, false); @@ -245,110 +242,89 @@ public class PacketBattleMessage implements IMessage case FLEE: if(message.amount != 0) { - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - from + " fled battle!")); + TurnBasedMinecraftMod.commonProxy.displayString(from + " fled battle!"); } else { - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - from + " tried to flee battle but failed!")); + TurnBasedMinecraftMod.commonProxy.displayString(from + " tried to flee battle but failed!"); } break; case DIED: - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - from + " died in battle!")); + TurnBasedMinecraftMod.commonProxy.displayString(from + " died in battle!"); break; case ENDED: - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - "Battle has ended!")); + TurnBasedMinecraftMod.commonProxy.displayString("Battle has ended!"); TurnBasedMinecraftMod.commonProxy.battleEnded(); TurnBasedMinecraftMod.commonProxy.stopMusic(); break; case ATTACK: - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - from + " attacked " + to + " and dealt " + message.amount + " damage!")); + TurnBasedMinecraftMod.commonProxy.displayString(from + " attacked " + to + " and dealt " + message.amount + " damage!"); break; case DEFEND: - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - from + " blocked " + to + "'s attack!")); + TurnBasedMinecraftMod.commonProxy.displayString(from + " blocked " + to + "'s attack!"); break; case DEFENSE_DAMAGE: - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - from + " retaliated from " + to + "'s attack and dealt " + message.amount + " damage!")); + TurnBasedMinecraftMod.commonProxy.displayString(from + " retaliated from " + to + "'s attack and dealt " + message.amount + " damage!"); break; case MISS: - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - from + " attacked " + to + " but missed!")); + TurnBasedMinecraftMod.commonProxy.displayString(from + " attacked " + to + " but missed!"); break; case DEFENDING: - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - from + " is defending!")); + TurnBasedMinecraftMod.commonProxy.displayString(from + " is defending!"); break; case DID_NOTHING: - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - from + " did nothing!")); + TurnBasedMinecraftMod.commonProxy.displayString(from + " did nothing!"); break; case USED_ITEM: switch(UsedItemAction.valueOf(message.amount)) { case USED_NOTHING: - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - from + " tried to use nothing!")); + TurnBasedMinecraftMod.commonProxy.displayString(from + " tried to use nothing!"); break; case USED_INVALID: if(message.custom.length() > 0) { - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - from + " tried to consume " + message.custom + " and failed!")); + TurnBasedMinecraftMod.commonProxy.displayString(from + " tried to consume " + message.custom + " and failed!"); } else { - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - from + " tried to consume an invalid item and failed!")); + TurnBasedMinecraftMod.commonProxy.displayString(from + " tried to consume an invalid item and failed!"); } break; case USED_FOOD: - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - from + " ate a " + message.custom + "!")); + TurnBasedMinecraftMod.commonProxy.displayString(from + " ate a " + message.custom + "!"); break; case USED_POTION: - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - from + " drank a " + message.custom + "!")); + TurnBasedMinecraftMod.commonProxy.displayString(from + " drank a " + message.custom + "!"); break; } break; case TURN_BEGIN: - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - "The turn begins!")); + TurnBasedMinecraftMod.commonProxy.displayString("The turn begins!"); TurnBasedMinecraftMod.commonProxy.battleGuiTurnBegin(); break; case TURN_END: if(TurnBasedMinecraftMod.currentBattle != null) { - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - "The turn ended!")); + TurnBasedMinecraftMod.commonProxy.displayString("The turn ended!"); } TurnBasedMinecraftMod.commonProxy.battleGuiTurnEnd(); break; case SWITCHED_ITEM: if(message.amount != 0) { - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - from + " switched to a different item!")); + TurnBasedMinecraftMod.commonProxy.displayString(from + " switched to a different item!"); } else { - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - from + " switched to a different item but failed because it was invalid!")); + TurnBasedMinecraftMod.commonProxy.displayString(from + " switched to a different item but failed because it was invalid!"); } break; case WAS_AFFECTED: - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - to + " was " + message.custom + " by " + from + "!")); + TurnBasedMinecraftMod.commonProxy.displayString(to + " was " + message.custom + " by " + from + "!"); break; case BECAME_CREATIVE: - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( - from + " entered creative mode and left battle!")); + TurnBasedMinecraftMod.commonProxy.displayString(from + " entered creative mode and left battle!"); break; } return null;