]> git.seodisparate.com - TurnBasedMinecraftMod/commitdiff
1.18.4 Fix battle hits, non-instant hits 1.18.4
authorStephen Seo <seo.disparate@gmail.com>
Fri, 10 Jun 2022 07:57:48 +0000 (16:57 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Fri, 10 Jun 2022 07:57:48 +0000 (16:57 +0900)
Fix hits in battles not hitting due to invulnerability frames.

Changed hits to be spaced appart by approx. 15ms.

Changelog.md
README.md
build.gradle
src/main/java/com/burnedkirby/TurnBasedMinecraft/common/Battle.java
src/main/java/com/burnedkirby/TurnBasedMinecraft/common/BattleUpdater.java
src/main/java/com/burnedkirby/TurnBasedMinecraft/common/TurnBasedMinecraftMod.java
src/main/resources/META-INF/mods.toml
src/main/resources/mcmod.info

index f0f910c872a0b1079f8d2f1705ccd5dc68faa329..1aeeb425dbc057de02fb257b1b24f51c4da19c1d 100644 (file)
@@ -1,5 +1,11 @@
 # Upcoming changes
 
+# Version 1.18.4
+
+Fix attacks not hitting due to "invulnerability frames".
+
+Change attacks to be applied approx 150ms apart.
+
 # Version 1.18.3
 
 [The ability to change server-side config from within the game using
index 2ec73f87093ff4a06edc7e05d3421aa4e74e1e8d..8a874f1a9007afbf438cae980f6d9769e99b290e 100644 (file)
--- a/README.md
+++ b/README.md
@@ -58,7 +58,7 @@ configured for them.)
 # Building
 
 Simply invoke `./gradlew build` in the mod directory and after some time the
-finished jar will be saved at "build/libs/TurnBasedMinecraft-1.18.3.jar"
+finished jar will be saved at "build/libs/TurnBasedMinecraft-1.18.4.jar"
 
 # Other notes
 
index 6a8529a07d87ffce92f9b6e92db1569af389e6fb..8898df13de3c21c3f7bb2339693552574c52258b 100644 (file)
@@ -14,7 +14,7 @@ apply plugin: 'net.minecraftforge.gradle'
 //apply plugin: 'eclipse'
 //apply plugin: 'maven-publish'
 
-version = "1.18.3"
+version = "1.18.4"
 group = "com.burnedkirby.TurnBasedMinecraft"
 archivesBaseName = "TurnBasedMinecraft"
 
index a54598e6a9a5f7ab5e32d4a6566b2cff05f6f391..4d8c8079987612859743e79a760111720e8867bf 100644 (file)
@@ -19,8 +19,7 @@ import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicInteger;
 
-public class Battle
-{
+public class Battle {
     private final int id;
     private Map<Integer, Combatant> sideA;
     private Map<Integer, Combatant> sideB;
@@ -28,59 +27,52 @@ public class Battle
     private PriorityQueue<Combatant> turnOrderQueue;
     private Queue<Combatant> sideAEntryQueue;
     private Queue<Combatant> sideBEntryQueue;
-    
+
     private State state;
     private AtomicInteger playerCount;
     private AtomicInteger undecidedCount;
     private long lastInstant;
     private long timer;
-    
+
     private boolean isServer;
     private boolean battleEnded;
-    
+
     private BattleManager battleManager;
 
     private Random random;
-    
+
     public String debugLog; // TODO remove after freeze bug has been found
 
     private ResourceKey<Level> dimension;
-    
-    public enum State
-    {
+
+    public enum State {
         DECISION(0),
         ACTION(1),
         DECISION_PLAYER_READY(2);
-        
+
         private int value;
         private static Map<Integer, State> map = new HashMap<Integer, State>();
-        
-        State(int value)
-        {
+
+        State(int value) {
             this.value = value;
         }
-        
-        public int getValue()
-        {
+
+        public int getValue() {
             return value;
         }
-        
-        static
-        {
-            for(State state : State.values())
-            {
+
+        static {
+            for (State state : State.values()) {
                 map.put(state.value, state);
             }
         }
-        
-        public static State valueOf(int stateType)
-        {
+
+        public static State valueOf(int stateType) {
             return map.get(stateType);
         }
     }
-    
-    public enum Decision
-    {
+
+    public enum Decision {
         UNDECIDED(0),
         ATTACK(1),
         DEFEND(2),
@@ -89,36 +81,30 @@ public class Battle
         SWITCH_ITEM(5),
         CREEPER_WAIT(6),
         CREEPER_EXPLODE(7);
-        
+
         private int value;
         private static Map<Integer, Decision> map = new HashMap<Integer, Decision>();
-        
-        Decision(int value)
-        {
+
+        Decision(int value) {
             this.value = value;
         }
-        
-        public int getValue()
-        {
+
+        public int getValue() {
             return value;
         }
-        
-        static
-        {
-            for(Decision decision : Decision.values())
-            {
+
+        static {
+            for (Decision decision : Decision.values()) {
                 map.put(decision.value, decision);
             }
         }
-        
-        public static Decision valueOf(int decisionType)
-        {
+
+        public static Decision valueOf(int decisionType) {
             return map.get(decisionType);
         }
     }
 
-    public Battle(BattleManager battleManager, int id, Collection<Entity> sideA, Collection<Entity> sideB, boolean isServer, ResourceKey<Level> dimension)
-    {
+    public Battle(BattleManager battleManager, int id, Collection<Entity> sideA, Collection<Entity> sideB, boolean isServer, ResourceKey<Level> dimension) {
         this.battleManager = battleManager;
         this.isServer = isServer;
         this.id = id;
@@ -132,37 +118,31 @@ public class Battle
         undecidedCount = new AtomicInteger(0);
         random = new Random();
         this.dimension = dimension;
-        if(sideA != null)
-        {
-            for(Entity e : sideA)
-            {
+        if (sideA != null) {
+            for (Entity e : sideA) {
                 EntityInfo entityInfo;
                 try {
                     entityInfo = TurnBasedMinecraftMod.proxy.getConfig().getCustomEntityInfoReference(e.getCustomName().getString());
-                } catch(NullPointerException exception) {
+                } catch (NullPointerException exception) {
                     entityInfo = null;
                 }
-                if(entityInfo == null)
-                {
+                if (entityInfo == null) {
                     entityInfo = TurnBasedMinecraftMod.proxy.getConfig().getMatchingEntityInfo(e);
                 }
 
-                if(entityInfo == null && !(e instanceof Player) && TurnBasedMinecraftMod.proxy.isServerRunning())
-                {
+                if (entityInfo == null && !(e instanceof Player) && TurnBasedMinecraftMod.proxy.isServerRunning()) {
                     continue;
                 }
                 Combatant newCombatant = new Combatant(e, entityInfo);
                 newCombatant.isSideA = true;
                 newCombatant.battleID = getId();
                 this.sideA.put(e.getId(), newCombatant);
-                if(e instanceof Player)
-                {
+                if (e instanceof Player) {
                     newCombatant.recalcSpeedOnCompare = true;
                     playerCount.incrementAndGet();
                     players.put(e.getId(), newCombatant);
                 }
-                if(TurnBasedMinecraftMod.proxy.getConfig().isFreezeCombatantsEnabled())
-                {
+                if (TurnBasedMinecraftMod.proxy.getConfig().isFreezeCombatantsEnabled()) {
                     newCombatant.x = e.getX();
                     newCombatant.z = e.getZ();
                     newCombatant.yaw = e.getXRot();
@@ -170,37 +150,31 @@ public class Battle
                 }
             }
         }
-        if(sideB != null)
-        {
-            for(Entity e : sideB)
-            {
+        if (sideB != null) {
+            for (Entity e : sideB) {
                 EntityInfo entityInfo;
                 try {
                     entityInfo = TurnBasedMinecraftMod.proxy.getConfig().getCustomEntityInfoReference(e.getCustomName().getString());
-                } catch(NullPointerException exception) {
+                } catch (NullPointerException exception) {
                     entityInfo = null;
                 }
-                if(entityInfo == null)
-                {
+                if (entityInfo == null) {
                     entityInfo = TurnBasedMinecraftMod.proxy.getConfig().getMatchingEntityInfo(e);
                 }
 
-                if(entityInfo == null && !(e instanceof Player) && TurnBasedMinecraftMod.proxy.isServerRunning())
-                {
+                if (entityInfo == null && !(e instanceof Player) && TurnBasedMinecraftMod.proxy.isServerRunning()) {
                     continue;
                 }
                 Combatant newCombatant = new Combatant(e, entityInfo);
                 newCombatant.isSideA = false;
                 newCombatant.battleID = getId();
                 this.sideB.put(e.getId(), newCombatant);
-                if(e instanceof Player)
-                {
+                if (e instanceof Player) {
                     newCombatant.recalcSpeedOnCompare = true;
                     playerCount.incrementAndGet();
                     players.put(e.getId(), newCombatant);
                 }
-                if(TurnBasedMinecraftMod.proxy.getConfig().isFreezeCombatantsEnabled())
-                {
+                if (TurnBasedMinecraftMod.proxy.getConfig().isFreezeCombatantsEnabled()) {
                     newCombatant.x = e.getX();
                     newCombatant.z = e.getZ();
                     newCombatant.yaw = e.getXRot();
@@ -208,229 +182,173 @@ public class Battle
                 }
             }
         }
-        
-        if(isServer)
-        {
-            for(Combatant c : this.sideA.values())
-            {
-                if(c.entityInfo != null)
-                {
+
+        if (isServer) {
+            for (Combatant c : this.sideA.values()) {
+                if (c.entityInfo != null) {
                     sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, c.entity.getId(), 0, id, c.entityInfo.category);
-                }
-                else if(c.entity instanceof Player)
-                {
+                } else if (c.entity instanceof Player) {
                     sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, c.entity.getId(), 0, id, "player");
-                }
-                else
-                {
+                } else {
                     sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, c.entity.getId(), 0, id);
                 }
             }
-            for(Combatant c : this.sideB.values())
-            {
-                if(c.entityInfo != null)
-                {
+            for (Combatant c : this.sideB.values()) {
+                if (c.entityInfo != null) {
                     sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, c.entity.getId(), 0, id, c.entityInfo.category);
-                }
-                else if(c.entity instanceof Player)
-                {
+                } else if (c.entity instanceof Player) {
                     sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, c.entity.getId(), 0, id, "player");
-                }
-                else
-                {
+                } else {
                     sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, c.entity.getId(), 0, id);
                 }
             }
         }
-        
+
         lastInstant = System.nanoTime();
         state = State.DECISION;
         undecidedCount.set(playerCount.get());
         timer = TurnBasedMinecraftMod.proxy.getConfig().getDecisionDurationNanos();
         battleEnded = false;
-        
+
         notifyPlayersBattleInfo();
     }
 
-    public int getId()
-    {
+    public int getId() {
         return id;
     }
-    
-    public Entity getCombatantEntity(int entityID)
-    {
+
+    public Entity getCombatantEntity(int entityID) {
         Combatant c = sideA.get(entityID);
-        if(c != null)
-        {
+        if (c != null) {
             return c.entity;
         }
         c = sideB.get(entityID);
-        if(c != null)
-        {
+        if (c != null) {
             return c.entity;
         }
         return null;
     }
-    
-    public boolean hasCombatant(int entityID)
-    {
-        for(Combatant c : sideAEntryQueue)
-        {
-            if(c.entity.getId() == entityID)
-            {
+
+    public boolean hasCombatant(int entityID) {
+        for (Combatant c : sideAEntryQueue) {
+            if (c.entity.getId() == entityID) {
                 return true;
             }
         }
-        for(Combatant c : sideBEntryQueue)
-        {
-            if(c.entity.getId() == entityID)
-            {
+        for (Combatant c : sideBEntryQueue) {
+            if (c.entity.getId() == entityID) {
                 return true;
             }
         }
         return sideA.containsKey(entityID) || sideB.containsKey(entityID);
     }
-    
-    public boolean hasCombatantInSideA(int entityID)
-    {
-        for(Combatant c : sideAEntryQueue)
-        {
-            if(c.entity.getId() == entityID)
-            {
+
+    public boolean hasCombatantInSideA(int entityID) {
+        for (Combatant c : sideAEntryQueue) {
+            if (c.entity.getId() == entityID) {
                 return true;
             }
         }
         return sideA.containsKey(entityID);
     }
-    
-    public void addCombatantToSideA(Entity e)
-    {
+
+    public void addCombatantToSideA(Entity e) {
         EntityInfo entityInfo;
         try {
             entityInfo = TurnBasedMinecraftMod.proxy.getConfig().getCustomEntityInfoReference(e.getCustomName().getString());
-        } catch(NullPointerException exception) {
+        } catch (NullPointerException exception) {
             entityInfo = null;
         }
-        if(entityInfo == null)
-        {
+        if (entityInfo == null) {
             entityInfo = TurnBasedMinecraftMod.proxy.getConfig().getMatchingEntityInfo(e);
         }
 
-        if(entityInfo == null && !(e instanceof Player) && TurnBasedMinecraftMod.proxy.isServerRunning())
-        {
+        if (entityInfo == null && !(e instanceof Player) && TurnBasedMinecraftMod.proxy.isServerRunning()) {
             return;
         }
         Combatant newCombatant = new Combatant(e, entityInfo);
         newCombatant.isSideA = true;
         newCombatant.battleID = getId();
-        if(isServer)
-        {
+        if (isServer) {
             sideAEntryQueue.add(newCombatant);
-        }
-        else
-        {
+        } else {
             sideA.put(e.getId(), newCombatant);
         }
-        if(e instanceof Player)
-        {
+        if (e instanceof Player) {
             newCombatant.recalcSpeedOnCompare = true;
             playerCount.incrementAndGet();
             players.put(e.getId(), newCombatant);
-            if(state == State.DECISION)
-            {
+            if (state == State.DECISION) {
                 undecidedCount.incrementAndGet();
             }
         }
-        if(TurnBasedMinecraftMod.proxy.getConfig().isFreezeCombatantsEnabled())
-        {
+        if (TurnBasedMinecraftMod.proxy.getConfig().isFreezeCombatantsEnabled()) {
             newCombatant.x = e.getX();
             newCombatant.z = e.getZ();
             newCombatant.yaw = e.getXRot();
             newCombatant.pitch = e.getYRot();
         }
-        if(isServer)
-        {
-            if(newCombatant.entityInfo != null)
-            {
+        if (isServer) {
+            if (newCombatant.entityInfo != null) {
                 sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, newCombatant.entity.getId(), 0, id, newCombatant.entityInfo.category);
-            }
-            else if(newCombatant.entity instanceof Player)
-            {
+            } else if (newCombatant.entity instanceof Player) {
                 sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, newCombatant.entity.getId(), 0, id, "player");
-            }
-            else
-            {
+            } else {
                 sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, newCombatant.entity.getId(), 0, id);
             }
         }
         notifyPlayersBattleInfo();
     }
-    
-    public void addCombatantToSideB(Entity e)
-    {
+
+    public void addCombatantToSideB(Entity e) {
         EntityInfo entityInfo;
         try {
             entityInfo = TurnBasedMinecraftMod.proxy.getConfig().getCustomEntityInfoReference(e.getCustomName().getString());
-        } catch(NullPointerException exception) {
+        } catch (NullPointerException exception) {
             entityInfo = null;
         }
-        if(entityInfo == null)
-        {
+        if (entityInfo == null) {
             entityInfo = TurnBasedMinecraftMod.proxy.getConfig().getMatchingEntityInfo(e);
         }
 
-        if(entityInfo == null && !(e instanceof Player) && TurnBasedMinecraftMod.proxy.isServerRunning())
-        {
+        if (entityInfo == null && !(e instanceof Player) && TurnBasedMinecraftMod.proxy.isServerRunning()) {
             return;
         }
         Combatant newCombatant = new Combatant(e, entityInfo);
         newCombatant.isSideA = false;
         newCombatant.battleID = getId();
-        if(isServer)
-        {
+        if (isServer) {
             sideBEntryQueue.add(newCombatant);
-        }
-        else
-        {
+        } else {
             sideB.put(e.getId(), newCombatant);
         }
-        if(e instanceof Player)
-        {
+        if (e instanceof Player) {
             newCombatant.recalcSpeedOnCompare = true;
             playerCount.incrementAndGet();
             players.put(e.getId(), newCombatant);
-            if(state == State.DECISION)
-            {
+            if (state == State.DECISION) {
                 undecidedCount.incrementAndGet();
             }
         }
-        if(TurnBasedMinecraftMod.proxy.getConfig().isFreezeCombatantsEnabled())
-        {
+        if (TurnBasedMinecraftMod.proxy.getConfig().isFreezeCombatantsEnabled()) {
             newCombatant.x = e.getX();
             newCombatant.z = e.getZ();
             newCombatant.yaw = e.getXRot();
             newCombatant.pitch = e.getYRot();
         }
-        if(isServer)
-        {
-            if(newCombatant.entityInfo != null)
-            {
+        if (isServer) {
+            if (newCombatant.entityInfo != null) {
                 sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, newCombatant.entity.getId(), 0, id, newCombatant.entityInfo.category);
-            }
-            else if(newCombatant.entity instanceof Player)
-            {
+            } else if (newCombatant.entity instanceof Player) {
                 sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, newCombatant.entity.getId(), 0, id, "player");
-            }
-            else
-            {
+            } else {
                 sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, newCombatant.entity.getId(), 0, id);
             }
         }
         notifyPlayersBattleInfo();
     }
-    
-    public void clearCombatants()
-    {
+
+    public void clearCombatants() {
         sideA.clear();
         sideB.clear();
         sideAEntryQueue.clear();
@@ -439,208 +357,163 @@ public class Battle
         playerCount.set(0);
         undecidedCount.set(0);
     }
-    
-    public Collection<Combatant> getSideA()
-    {
+
+    public Collection<Combatant> getSideA() {
         return sideA.values();
     }
-    
-    public Collection<Combatant> getSideB()
-    {
+
+    public Collection<Combatant> getSideB() {
         return sideB.values();
     }
-    
-    public Set<Map.Entry<Integer, Combatant>> getSideAEntrySet()
-    {
+
+    public Set<Map.Entry<Integer, Combatant>> getSideAEntrySet() {
         return sideA.entrySet();
     }
-    
-    public Set<Map.Entry<Integer, Combatant>> getSideBEntrySet()
-    {
+
+    public Set<Map.Entry<Integer, Combatant>> getSideBEntrySet() {
         return sideB.entrySet();
     }
-    
-    public Collection<Integer> getSideAIDs()
-    {
+
+    public Collection<Integer> getSideAIDs() {
         Collection<Integer> sideAIDs = new ArrayList<Integer>(sideA.size());
-        for(Combatant combatant : sideA.values())
-        {
+        for (Combatant combatant : sideA.values()) {
             sideAIDs.add(combatant.entity.getId());
         }
         return sideAIDs;
     }
-    
-    public Collection<Integer> getSideBIDs()
-    {
+
+    public Collection<Integer> getSideBIDs() {
         Collection<Integer> sideBIDs = new ArrayList<Integer>(sideB.size());
-        for(Combatant combatant : sideB.values())
-        {
+        for (Combatant combatant : sideB.values()) {
             sideBIDs.add(combatant.entity.getId());
         }
         return sideBIDs;
     }
-    
-    public Combatant getCombatantByID(int entityID)
-    {
+
+    public Combatant getCombatantByID(int entityID) {
         Combatant combatant = sideA.get(entityID);
-        if(combatant == null)
-        {
+        if (combatant == null) {
             combatant = sideB.get(entityID);
         }
         return combatant;
     }
-    
-    public void setDecision(int entityID, Decision decision, int targetIDOrItemID)
-    {
-        if(state != State.DECISION)
-        {
+
+    public void setDecision(int entityID, Decision decision, int targetIDOrItemID) {
+        if (state != State.DECISION) {
             return;
         }
         Combatant combatant = players.get(entityID);
-        if(combatant == null || combatant.decision != Decision.UNDECIDED)
-        {
+        if (combatant == null || combatant.decision != Decision.UNDECIDED) {
             return;
         }
         combatant.decision = decision;
-        if(decision == Decision.ATTACK)
-        {
+        if (decision == Decision.ATTACK) {
             combatant.targetEntityID = targetIDOrItemID;
-        }
-        else if(decision == Decision.USE_ITEM || decision == Decision.SWITCH_ITEM)
-        {
+        } else if (decision == Decision.USE_ITEM || decision == Decision.SWITCH_ITEM) {
             combatant.itemToUse = targetIDOrItemID;
         }
         undecidedCount.decrementAndGet();
     }
-    
-    public State getState()
-    {
+
+    public State getState() {
         return state;
     }
-    
-    public void setState(State state)
-    {
+
+    public void setState(State state) {
         this.state = state;
     }
-    
-    public long getTimerSeconds()
-    {
+
+    public long getTimerSeconds() {
         return timer / 1000000000;
     }
-    
-    public int getSize()
-    {
+
+    public int getSize() {
         int size = sideA.size() + sideB.size();
         size += sideAEntryQueue.size();
         size += sideBEntryQueue.size();
         return size;
     }
-    
-    protected void notifyPlayersBattleInfo()
-    {
-        if(!isServer)
-        {
+
+    protected void notifyPlayersBattleInfo() {
+        if (!isServer) {
             return;
         }
         PacketBattleInfo infoPacket = new PacketBattleInfo(getSideAIDs(), getSideBIDs(), timer);
-        for(Combatant p : players.values())
-        {
-            TurnBasedMinecraftMod.getHandler().send(PacketDistributor.PLAYER.with(() -> (ServerPlayer)p.entity), infoPacket);
+        for (Combatant p : players.values()) {
+            TurnBasedMinecraftMod.getHandler().send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) p.entity), infoPacket);
         }
     }
-    
-    protected void sendMessageToAllPlayers(PacketBattleMessage.MessageType type, int from, int to, int amount)
-    {
+
+    protected void sendMessageToAllPlayers(PacketBattleMessage.MessageType type, int from, int to, int amount) {
         sendMessageToAllPlayers(type, from, to, amount, new String());
     }
-    
-    protected void sendMessageToAllPlayers(PacketBattleMessage.MessageType type, int from, int to, int amount, String custom)
-    {
-        if(!isServer)
-        {
+
+    protected void sendMessageToAllPlayers(PacketBattleMessage.MessageType type, int from, int to, int amount, String custom) {
+        if (!isServer) {
             return;
         }
         PacketBattleMessage packet = new PacketBattleMessage(type, from, to, dimension, amount, custom);
-        for(Combatant p : players.values())
-        {
-            if(p.entity.isAlive())
-            {
+        for (Combatant p : players.values()) {
+            if (p.entity.isAlive()) {
                 TurnBasedMinecraftMod.getHandler().send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) p.entity), packet);
             }
         }
     }
-    
+
     /**
      * @return true if at least one combatant was removed
      */
-    private boolean healthCheck()
-    {
+    private boolean healthCheck() {
         boolean didRemove = false;
-        for(Iterator<Map.Entry<Integer, Combatant>> iter = sideA.entrySet().iterator(); iter.hasNext();)
-        {
+        for (Iterator<Map.Entry<Integer, Combatant>> iter = sideA.entrySet().iterator(); iter.hasNext(); ) {
             Map.Entry<Integer, Combatant> entry = iter.next();
-            if(!entry.getValue().entity.isAlive())
-            {
+            if (!entry.getValue().entity.isAlive()) {
                 iter.remove();
                 players.remove(entry.getKey());
                 removeCombatantPostRemove(entry.getValue());
                 didRemove = true;
                 String category = null;
-                if(entry.getValue().entityInfo != null)
-                {
+                if (entry.getValue().entityInfo != null) {
                     category = entry.getValue().entityInfo.category;
-                }
-                else if(entry.getValue().entity instanceof Player)
-                {
+                } else if (entry.getValue().entity instanceof Player) {
                     category = "player";
                 }
                 sendMessageToAllPlayers(PacketBattleMessage.MessageType.DIED, entry.getValue().entity.getId(), 0, 0, category);
             }
         }
-        for(Iterator<Map.Entry<Integer, Combatant>> iter = sideB.entrySet().iterator(); iter.hasNext();)
-        {
+        for (Iterator<Map.Entry<Integer, Combatant>> iter = sideB.entrySet().iterator(); iter.hasNext(); ) {
             Map.Entry<Integer, Combatant> entry = iter.next();
-            if(!entry.getValue().entity.isAlive())
-            {
+            if (!entry.getValue().entity.isAlive()) {
                 iter.remove();
                 players.remove(entry.getKey());
                 removeCombatantPostRemove(entry.getValue());
                 didRemove = true;
                 String category = null;
-                if(entry.getValue().entityInfo != null)
-                {
+                if (entry.getValue().entityInfo != null) {
                     category = entry.getValue().entityInfo.category;
-                }
-                else if(entry.getValue().entity instanceof Player)
-                {
+                } else if (entry.getValue().entity instanceof Player) {
                     category = "player";
                 }
                 sendMessageToAllPlayers(PacketBattleMessage.MessageType.DIED, entry.getValue().entity.getId(), 0, 0, category);
             }
         }
-        if(players.isEmpty() || sideA.isEmpty() || sideB.isEmpty())
-        {
+        if (players.isEmpty() || sideA.isEmpty() || sideB.isEmpty()) {
             battleEnded = true;
-        }
-        else if(didRemove)
-        {
+        } else if (didRemove) {
             resetUndecidedCount();
         }
-        
+
         return didRemove;
     }
-    
+
     /**
      * @return true if at least one combatant was removed
      */
-    private boolean isCreativeCheck()
-    {
+    private boolean isCreativeCheck() {
         boolean didRemove = false;
-        for(Iterator<Map.Entry<Integer, Combatant>> iter = players.entrySet().iterator(); iter.hasNext();)
-        {
+        for (Iterator<Map.Entry<Integer, Combatant>> iter = players.entrySet().iterator(); iter.hasNext(); ) {
             Map.Entry<Integer, Combatant> entry = iter.next();
-            if(entry.getValue().entity != null && ((Player)entry.getValue().entity).isCreative())
-            {
+            if (entry.getValue().entity != null && ((Player) entry.getValue().entity).isCreative()) {
                 sendMessageToAllPlayers(PacketBattleMessage.MessageType.BECAME_CREATIVE, entry.getValue().entity.getId(), 0, 0);
                 iter.remove();
                 sideA.remove(entry.getKey());
@@ -650,60 +523,48 @@ public class Battle
                 didRemove = true;
             }
         }
-        if(didRemove)
-        {
+        if (didRemove) {
             resetUndecidedCount();
         }
-        
+
         return didRemove;
     }
-    
-    private void resetUndecidedCount()
-    {
-        if(state == State.DECISION)
-        {
+
+    private void resetUndecidedCount() {
+        if (state == State.DECISION) {
             undecidedCount.set(0);
-            for(Combatant p : players.values())
-            {
-                if(p.decision == Decision.UNDECIDED)
-                {
+            for (Combatant p : players.values()) {
+                if (p.decision == Decision.UNDECIDED) {
                     undecidedCount.incrementAndGet();
                 }
             }
         }
     }
-    
-    private void enforceFreezePositions()
-    {
-        for(Combatant c : sideA.values())
-        {
+
+    private void enforceFreezePositions() {
+        for (Combatant c : sideA.values()) {
             c.entity.setPos(c.x, c.entity.getY(), c.z);
             c.entity.setYBodyRot(c.yaw);
             c.entity.setYHeadRot(c.pitch);
         }
-        for(Combatant c : sideB.values())
-        {
+        for (Combatant c : sideB.values()) {
             c.entity.setPos(c.x, c.entity.getY(), c.z);
             c.entity.setYBodyRot(c.yaw);
             c.entity.setYHeadRot(c.pitch);
         }
     }
-    
-    private void removeCombatant(Combatant c)
-    {
+
+    private void removeCombatant(Combatant c) {
         sideA.remove(c.entity.getId());
         sideB.remove(c.entity.getId());
-        if(players.remove(c.entity.getId()) != null)
-        {
+        if (players.remove(c.entity.getId()) != null) {
             playerCount.decrementAndGet();
         }
         removeCombatantPostRemove(c);
     }
-    
-    private void removeCombatantPostRemove(Combatant c)
-    {
-        if(c.entity instanceof Player)
-        {
+
+    private void removeCombatantPostRemove(Combatant c) {
+        if (c.entity instanceof Player) {
             TurnBasedMinecraftMod.getHandler().send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) c.entity), new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, 0, 0, dimension, 0));
         }
         battleManager.addRecentlyLeftBattle(c);
@@ -712,33 +573,30 @@ public class Battle
     public void forceRemoveCombatant(EntityIDDimPair e) {
         sideA.remove(e.id);
         sideB.remove(e.id);
-        if(players.remove(e.id) != null) {
+        if (players.remove(e.id) != null) {
             playerCount.decrementAndGet();
         }
-        for(Iterator<Combatant> iter = sideAEntryQueue.iterator(); iter.hasNext();) {
+        for (Iterator<Combatant> iter = sideAEntryQueue.iterator(); iter.hasNext(); ) {
             Combatant c = iter.next();
-            if(c.entity.getId() == e.id) {
+            if (c.entity.getId() == e.id) {
                 iter.remove();
                 break;
             }
         }
-        for(Iterator<Combatant> iter = sideBEntryQueue.iterator(); iter.hasNext();) {
+        for (Iterator<Combatant> iter = sideBEntryQueue.iterator(); iter.hasNext(); ) {
             Combatant c = iter.next();
-            if(c.entity.getId() == e.id) {
+            if (c.entity.getId() == e.id) {
                 iter.remove();
                 break;
             }
         }
     }
 
-    private void setDecisionState()
-    {
-        for(Combatant c : sideA.values())
-        {
+    private void setDecisionState() {
+        for (Combatant c : sideA.values()) {
             c.decision = Decision.UNDECIDED;
         }
-        for(Combatant c : sideB.values())
-        {
+        for (Combatant c : sideB.values()) {
             c.decision = Decision.UNDECIDED;
         }
         state = State.DECISION;
@@ -748,19 +606,14 @@ public class Battle
     /**
      * @return True if battle has ended
      */
-    public boolean update()
-    {
-        if(!isServer)
-        {
+    public boolean update() {
+        if (!isServer) {
             return false;
-        }
-        else if(battleEnded)
-        {
+        } else if (battleEnded) {
             Collection<Combatant> combatants = new ArrayList<Combatant>();
             combatants.addAll(sideA.values());
             combatants.addAll(sideB.values());
-            for(Combatant c : combatants)
-            {
+            for (Combatant c : combatants) {
                 removeCombatant(c);
             }
             return true;
@@ -768,154 +621,120 @@ public class Battle
         long nextInstant = System.nanoTime();
         long dt = nextInstant - lastInstant;
         lastInstant = nextInstant;
-        try
-        {
+        try {
             return update(dt);
-        } catch (Throwable t)
-        {
+        } catch (Throwable t) {
             TurnBasedMinecraftMod.logger.error("Update: ", t);
             setDecisionState();
             boolean changed = false;
-            if(healthCheck())
-            {
+            if (healthCheck()) {
                 changed = true;
             }
-            if(isCreativeCheck())
-            {
+            if (isCreativeCheck()) {
                 changed = true;
             }
             sendMessageToAllPlayers(PacketBattleMessage.MessageType.TURN_END, 0, 0, 1);
-            if(changed)
-            {
+            if (changed) {
                 notifyPlayersBattleInfo();
             }
             return battleEnded;
         }
     }
-    
-    private boolean update(final long dt)
-    {
-        if(battleEnded)
-        {
+
+    private boolean update(final long dt) {
+        if (battleEnded) {
             Collection<Combatant> combatants = new ArrayList<Combatant>();
             combatants.addAll(sideA.values());
             combatants.addAll(sideB.values());
-            for(Combatant c : combatants)
-            {
+            for (Combatant c : combatants) {
                 removeCombatant(c);
             }
             return true;
         }
         boolean combatantsChanged = false;
-        for(Combatant c = sideAEntryQueue.poll(); c != null; c = sideAEntryQueue.poll())
-        {
+        for (Combatant c = sideAEntryQueue.poll(); c != null; c = sideAEntryQueue.poll()) {
             sideA.put(c.entity.getId(), c);
             combatantsChanged = true;
         }
-        for(Combatant c = sideBEntryQueue.poll(); c != null; c = sideBEntryQueue.poll())
-        {
+        for (Combatant c = sideBEntryQueue.poll(); c != null; c = sideBEntryQueue.poll()) {
             sideB.put(c.entity.getId(), c);
             combatantsChanged = true;
         }
-        if(TurnBasedMinecraftMod.proxy.getConfig().isFreezeCombatantsEnabled())
-        {
+        if (TurnBasedMinecraftMod.proxy.getConfig().isFreezeCombatantsEnabled()) {
             enforceFreezePositions();
         }
         defuseCreepers();
-        switch(state)
-        {
-        case DECISION:
-            timer -= dt;
-            if(timer <= 0 || undecidedCount.get() <= 0)
-            {
-                for(Combatant c : sideA.values())
-                {
-                    // picking decision for sideA non-players
-                    if(!(c.entity instanceof Player) && c.decision == Decision.UNDECIDED && c.entityInfo != null)
-                    {
-                        if(c.entity instanceof Creeper) {
-                            if(c.creeperTurns++ < TurnBasedMinecraftMod.proxy.getConfig().getCreeperExplodeTurn()) {
-                                c.decision = Decision.CREEPER_WAIT;
-                            } else {
-                                c.decision = Decision.CREEPER_EXPLODE;
+        switch (state) {
+            case DECISION:
+                timer -= dt;
+                if (timer <= 0 || undecidedCount.get() <= 0) {
+                    for (Combatant c : sideA.values()) {
+                        // picking decision for sideA non-players
+                        if (!(c.entity instanceof Player) && c.decision == Decision.UNDECIDED && c.entityInfo != null) {
+                            if (c.entity instanceof Creeper) {
+                                if (c.creeperTurns++ < TurnBasedMinecraftMod.proxy.getConfig().getCreeperExplodeTurn()) {
+                                    c.decision = Decision.CREEPER_WAIT;
+                                } else {
+                                    c.decision = Decision.CREEPER_EXPLODE;
+                                }
+                                continue;
+                            }
+                            int percentage = random.nextInt(100);
+                            if (percentage < c.entityInfo.decisionAttack) {
+                                c.decision = Decision.ATTACK;
+                            } else if (percentage - c.entityInfo.decisionAttack < c.entityInfo.decisionDefend) {
+                                c.decision = Decision.DEFEND;
+                            } else if (percentage - c.entityInfo.decisionAttack - c.entityInfo.decisionDefend < c.entityInfo.decisionFlee) {
+                                c.decision = Decision.FLEE;
                             }
-                            continue;
-                        }
-                        int percentage = random.nextInt(100);
-                        if(percentage < c.entityInfo.decisionAttack)
-                        {
-                            c.decision = Decision.ATTACK;
-                        }
-                        else if(percentage - c.entityInfo.decisionAttack < c.entityInfo.decisionDefend)
-                        {
-                            c.decision = Decision.DEFEND;
-                        }
-                        else if(percentage - c.entityInfo.decisionAttack - c.entityInfo.decisionDefend < c.entityInfo.decisionFlee)
-                        {
-                            c.decision = Decision.FLEE;
                         }
                     }
-                }
-                for(Combatant c : sideB.values())
-                {
-                    if(!(c.entity instanceof Player) && c.decision == Decision.UNDECIDED && c.entityInfo != null)
-                    {
-                        if(c.entity instanceof Creeper) {
-                            if(c.creeperTurns++ < TurnBasedMinecraftMod.proxy.getConfig().getCreeperExplodeTurn()) {
-                                c.decision = Decision.CREEPER_WAIT;
-                            } else {
-                                c.decision = Decision.CREEPER_EXPLODE;
+                    for (Combatant c : sideB.values()) {
+                        if (!(c.entity instanceof Player) && c.decision == Decision.UNDECIDED && c.entityInfo != null) {
+                            if (c.entity instanceof Creeper) {
+                                if (c.creeperTurns++ < TurnBasedMinecraftMod.proxy.getConfig().getCreeperExplodeTurn()) {
+                                    c.decision = Decision.CREEPER_WAIT;
+                                } else {
+                                    c.decision = Decision.CREEPER_EXPLODE;
+                                }
+                                continue;
+                            }
+                            int percentage = random.nextInt(100);
+                            if (percentage < c.entityInfo.decisionAttack) {
+                                c.decision = Decision.ATTACK;
+                            } else if (percentage - c.entityInfo.decisionAttack < c.entityInfo.decisionDefend) {
+                                c.decision = Decision.DEFEND;
+                            } else if (percentage - c.entityInfo.decisionAttack - c.entityInfo.decisionDefend < c.entityInfo.decisionFlee) {
+                                c.decision = Decision.FLEE;
                             }
-                            continue;
-                        }
-                        int percentage = random.nextInt(100);
-                        if(percentage < c.entityInfo.decisionAttack)
-                        {
-                            c.decision = Decision.ATTACK;
-                        }
-                        else if(percentage - c.entityInfo.decisionAttack < c.entityInfo.decisionDefend)
-                        {
-                            c.decision = Decision.DEFEND;
-                        }
-                        else if(percentage - c.entityInfo.decisionAttack - c.entityInfo.decisionDefend < c.entityInfo.decisionFlee)
-                        {
-                            c.decision = Decision.FLEE;
                         }
                     }
+                    state = State.ACTION;
+                    timer = TurnBasedMinecraftMod.proxy.getConfig().getDecisionDurationNanos();
+                    sendMessageToAllPlayers(PacketBattleMessage.MessageType.TURN_BEGIN, 0, 0, 0);
+                    turnOrderQueue.clear();
+                    for (Combatant c : sideA.values()) {
+                        turnOrderQueue.add(c);
+                    }
+                    for (Combatant c : sideB.values()) {
+                        turnOrderQueue.add(c);
+                    }
+                    return update(0);
+                } else {
+                    if (healthCheck()) {
+                        combatantsChanged = true;
+                    }
+                    if (isCreativeCheck()) {
+                        combatantsChanged = true;
+                    }
                 }
-                state = State.ACTION;
-                timer = TurnBasedMinecraftMod.proxy.getConfig().getDecisionDurationNanos();
-                sendMessageToAllPlayers(PacketBattleMessage.MessageType.TURN_BEGIN, 0, 0, 0);
-                turnOrderQueue.clear();
-                for(Combatant c : sideA.values())
-                {
-                    turnOrderQueue.add(c);
-                }
-                for(Combatant c : sideB.values())
-                {
-                    turnOrderQueue.add(c);
-                }
-                return update(0);
-            }
-            else
-            {
-                if(healthCheck())
-                {
-                    combatantsChanged = true;
-                }
-                if(isCreativeCheck())
-                {
-                    combatantsChanged = true;
-                }
-            }
-            break;
-        case ACTION:
-            {
-                for(Combatant next = turnOrderQueue.poll(); next != null; next = turnOrderQueue.poll())
-                {
-                    if(!next.entity.isAlive())
-                    {
-                        continue;
+                break;
+            case ACTION: {
+                do {
+                    // depend on BattleUpdater's tick limit as rate-of-update for doing Battle decisions
+                    Combatant next = turnOrderQueue.poll();
+                    if (next == null || !next.entity.isAlive()) {
+                        break;
                     }
 
                     debugLog = next.entity.getDisplayName().getString();
@@ -924,590 +743,492 @@ public class Battle
 
                     Decision decision = next.decision;
                     next.decision = Decision.UNDECIDED;
-                    
-                    switch(decision)
-                    {
-                    case UNDECIDED:
-                        debugLog += " undecided";
-                        sendMessageToAllPlayers(PacketBattleMessage.MessageType.DID_NOTHING, next.entity.getId(), 0, 0);
-                        break;
-                    case ATTACK:
-                        debugLog += " attack";
-                        Combatant target = null;
-                        if(next.entity instanceof Player)
-                        {
-                            debugLog += " as player";
-                            target = sideA.get(next.targetEntityID);
-                            if(target == null)
-                            {
-                                target = sideB.get(next.targetEntityID);
-                            }
-                            if(target == null || !target.entity.isAlive() || target == next)
-                            {
-                                continue;
-                            }
-                            ItemStack heldItemStack = ((Player)next.entity).getMainHandItem();
-                            if(heldItemStack.getItem() instanceof BowItem)
-                            {
-                                debugLog += " with bow";
-                                if(Utility.doesPlayerHaveArrows((Player)next.entity))
-                                {
-                                    final Entity nextEntity = next.entity;
-                                    final Entity targetEntity = target.entity;
-                                    final float yawDirection = Utility.yawDirection(next.entity.getX(), next.entity.getZ(), target.entity.getX(), target.entity.getZ());
-                                    final float pitchDirection = Utility.pitchDirection(next.entity.getX(), next.entity.getY(), next.entity.getZ(), target.entity.getX(), target.entity.getY(), target.entity.getZ());
-                                    final int randomTimeLeft = random.nextInt(heldItemStack.getItem().getUseDuration(heldItemStack) / 3);
-                                    if(TurnBasedMinecraftMod.proxy.getConfig().isFreezeCombatantsEnabled())
-                                    {
-                                        next.yaw = yawDirection;
-                                        next.pitch = pitchDirection;
-                                    }
-                                    // have player look at attack target
-                                    ((ServerPlayer)nextEntity).connection.teleport(nextEntity.getX(), nextEntity.getY(), nextEntity.getZ(), yawDirection, pitchDirection);
-                                    BowItem itemBow = (BowItem)heldItemStack.getItem();
-                                    TurnBasedMinecraftMod.proxy.getAttackerViaBowSet().add(new AttackerViaBow(nextEntity, getId()));
-                                    itemBow.releaseUsing(((Player)nextEntity).getMainHandItem(), nextEntity.level, (LivingEntity) nextEntity, randomTimeLeft);
-                                    sendMessageToAllPlayers(PacketBattleMessage.MessageType.FIRED_ARROW, nextEntity.getId(), targetEntity.getId(), 0);
+
+                    switch (decision) {
+                        case UNDECIDED:
+                            debugLog += " undecided";
+                            sendMessageToAllPlayers(PacketBattleMessage.MessageType.DID_NOTHING, next.entity.getId(), 0, 0);
+                            break;
+                        case ATTACK:
+                            debugLog += " attack";
+                            Combatant target = null;
+                            if (next.entity instanceof Player) {
+                                debugLog += " as player";
+                                target = sideA.get(next.targetEntityID);
+                                if (target == null) {
+                                    target = sideB.get(next.targetEntityID);
                                 }
-                                else
-                                {
-                                    sendMessageToAllPlayers(PacketBattleMessage.MessageType.BOW_NO_AMMO, next.entity.getId(), 0, 0);
+                                if (target == null || !target.entity.isAlive() || target == next) {
+                                    continue;
                                 }
-                                continue;
-                            }
-                            debugLog += " without bow";
-                            int hitChance = TurnBasedMinecraftMod.proxy.getConfig().getPlayerAttackProbability();
-                            if(target.entity instanceof Player)
-                            {
-                                hitChance = hitChance * (100 - TurnBasedMinecraftMod.proxy.getConfig().getPlayerEvasion()) / 100;
-                            }
-                            else
-                            {
-                                hitChance = hitChance * (100 - target.entityInfo.evasion) / 100;
-                            }
-                            if(hitChance < TurnBasedMinecraftMod.proxy.getConfig().getMinimumHitPercentage())
-                            {
-                                hitChance = TurnBasedMinecraftMod.proxy.getConfig().getMinimumHitPercentage();
-                            }
-                            if(random.nextInt(100) < hitChance)
-                            {
-                                if(target.remainingDefenses <= 0)
-                                {
-                                    debugLog += " hit success";
-                                    // attack
-                                    final Entity nextEntity = next.entity;
-                                    final Entity targetEntity = target.entity;
-                                    final EntityInfo targetEntityInfo = target.entityInfo;
-                                    final float yawDirection = Utility.yawDirection(next.entity.getX(), next.entity.getZ(), target.entity.getX(), target.entity.getZ());
-                                    final float pitchDirection = Utility.pitchDirection(next.entity.getX(), next.entity.getY(), next.entity.getZ(), target.entity.getX(), target.entity.getY(), target.entity.getZ());
-                                    final boolean defenseDamageTriggered;
-                                    if(!(targetEntity instanceof Player) && targetEntityInfo.defenseDamage > 0 && targetEntityInfo.defenseDamageProbability > 0)
-                                    {
-                                        if(random.nextInt(100) < targetEntityInfo.defenseDamageProbability)
-                                        {
-                                            defenseDamageTriggered = true;
-                                        }
-                                        else
-                                        {
-                                            defenseDamageTriggered = false;
+                                ItemStack heldItemStack = ((Player) next.entity).getMainHandItem();
+                                if (heldItemStack.getItem() instanceof BowItem) {
+                                    debugLog += " with bow";
+                                    if (Utility.doesPlayerHaveArrows((Player) next.entity)) {
+                                        final Entity nextEntity = next.entity;
+                                        final Entity targetEntity = target.entity;
+                                        final float yawDirection = Utility.yawDirection(next.entity.getX(), next.entity.getZ(), target.entity.getX(), target.entity.getZ());
+                                        final float pitchDirection = Utility.pitchDirection(next.entity.getX(), next.entity.getY(), next.entity.getZ(), target.entity.getX(), target.entity.getY(), target.entity.getZ());
+                                        final int randomTimeLeft = random.nextInt(heldItemStack.getItem().getUseDuration(heldItemStack) / 3);
+                                        if (TurnBasedMinecraftMod.proxy.getConfig().isFreezeCombatantsEnabled()) {
+                                            next.yaw = yawDirection;
+                                            next.pitch = pitchDirection;
                                         }
+                                        // have player look at attack target
+                                        ((ServerPlayer) nextEntity).connection.teleport(nextEntity.getX(), nextEntity.getY(), nextEntity.getZ(), yawDirection, pitchDirection);
+                                        BowItem itemBow = (BowItem) heldItemStack.getItem();
+                                        TurnBasedMinecraftMod.proxy.getAttackerViaBowSet().add(new AttackerViaBow(nextEntity, getId()));
+                                        itemBow.releaseUsing(((Player) nextEntity).getMainHandItem(), nextEntity.level, (LivingEntity) nextEntity, randomTimeLeft);
+                                        sendMessageToAllPlayers(PacketBattleMessage.MessageType.FIRED_ARROW, nextEntity.getId(), targetEntity.getId(), 0);
+                                    } else {
+                                        sendMessageToAllPlayers(PacketBattleMessage.MessageType.BOW_NO_AMMO, next.entity.getId(), 0, 0);
                                     }
-                                    else
-                                    {
-                                        defenseDamageTriggered = false;
-                                    }
-                                    if(TurnBasedMinecraftMod.proxy.getConfig().isFreezeCombatantsEnabled())
-                                    {
-                                        next.yaw = yawDirection;
-                                        next.pitch = pitchDirection;
-                                    }
-                                    // have player look at attack target
-                                    ((ServerPlayer)nextEntity).connection.teleport(nextEntity.getX(), nextEntity.getY(), nextEntity.getZ(), yawDirection, pitchDirection);
-                                    TurnBasedMinecraftMod.proxy.setAttackingEntity(nextEntity);
-                                    TurnBasedMinecraftMod.proxy.setAttackingDamage(0);
-                                    ((Player)nextEntity).attack(targetEntity);
-                                    TurnBasedMinecraftMod.proxy.setAttackingEntity(null);
-                                    sendMessageToAllPlayers(PacketBattleMessage.MessageType.ATTACK, nextEntity.getId(), targetEntity.getId(), TurnBasedMinecraftMod.proxy.getAttackingDamage());
-                                    if(defenseDamageTriggered)
-                                    {
-                                        // defense damage
-                                        DamageSource defenseDamageSource = DamageSource.mobAttack((LivingEntity) targetEntity);
-                                        TurnBasedMinecraftMod.proxy.setAttackingEntity(targetEntity);
-                                        nextEntity.hurt(defenseDamageSource, targetEntityInfo.defenseDamage);
-                                        TurnBasedMinecraftMod.proxy.setAttackingEntity(null);
-                                        sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENSE_DAMAGE, targetEntity.getId(), nextEntity.getId(), targetEntityInfo.defenseDamage);
-                                    }
+                                    continue;
                                 }
-                                else
-                                {
-                                    debugLog += " hit blocked";
-                                    // blocked
-                                    --target.remainingDefenses;
-                                    sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFEND, target.entity.getId(), next.entity.getId(), 0);
+                                debugLog += " without bow";
+                                int hitChance = TurnBasedMinecraftMod.proxy.getConfig().getPlayerAttackProbability();
+                                if (target.entity instanceof Player) {
+                                    hitChance = hitChance * (100 - TurnBasedMinecraftMod.proxy.getConfig().getPlayerEvasion()) / 100;
+                                } else {
+                                    hitChance = hitChance * (100 - target.entityInfo.evasion) / 100;
                                 }
-                            }
-                            else
-                            {
-                                debugLog += " hit missed";
-                                // miss
-                                sendMessageToAllPlayers(PacketBattleMessage.MessageType.MISS, next.entity.getId(), target.entity.getId(), 0);
-                            }
-                        }
-                        else
-                        {
-                            debugLog += " as mob";
-                            LivingEntity attackTarget = ((Mob)next.entity).getTarget();
-                            if(attackTarget != null && hasCombatant(attackTarget.getId()))
-                            {
-                                debugLog += " to targeted";
-                                target = getCombatantByID(attackTarget.getId());
-                            }
-                            else
-                            {
-                                debugLog += " to random other side";
-                                if(next.isSideA)
-                                {
-                                    if(sideB.size() > 0)
-                                    {
-                                        int randomTargetIndex = random.nextInt(sideB.size());
-                                        for(Combatant c : sideB.values())
-                                        {
-                                            if(randomTargetIndex-- == 0)
-                                            {
-                                                target = c;
-                                                break;
+                                if (hitChance < TurnBasedMinecraftMod.proxy.getConfig().getMinimumHitPercentage()) {
+                                    hitChance = TurnBasedMinecraftMod.proxy.getConfig().getMinimumHitPercentage();
+                                }
+                                if (random.nextInt(100) < hitChance) {
+                                    if (target.remainingDefenses <= 0) {
+                                        debugLog += " hit success";
+                                        // attack
+                                        final Entity nextEntity = next.entity;
+                                        final Entity targetEntity = target.entity;
+                                        final EntityInfo targetEntityInfo = target.entityInfo;
+                                        final float yawDirection = Utility.yawDirection(next.entity.getX(), next.entity.getZ(), target.entity.getX(), target.entity.getZ());
+                                        final float pitchDirection = Utility.pitchDirection(next.entity.getX(), next.entity.getY(), next.entity.getZ(), target.entity.getX(), target.entity.getY(), target.entity.getZ());
+                                        final boolean defenseDamageTriggered;
+                                        if (!(targetEntity instanceof Player) && targetEntityInfo.defenseDamage > 0 && targetEntityInfo.defenseDamageProbability > 0) {
+                                            if (random.nextInt(100) < targetEntityInfo.defenseDamageProbability) {
+                                                defenseDamageTriggered = true;
+                                            } else {
+                                                defenseDamageTriggered = false;
                                             }
+                                        } else {
+                                            defenseDamageTriggered = false;
+                                        }
+                                        if (TurnBasedMinecraftMod.proxy.getConfig().isFreezeCombatantsEnabled()) {
+                                            next.yaw = yawDirection;
+                                            next.pitch = pitchDirection;
                                         }
+                                        // have player look at attack target
+                                        ((ServerPlayer) nextEntity).connection.teleport(nextEntity.getX(), nextEntity.getY(), nextEntity.getZ(), yawDirection, pitchDirection);
+                                        TurnBasedMinecraftMod.proxy.setAttackingEntity(nextEntity);
+                                        TurnBasedMinecraftMod.proxy.setAttackingDamage(0);
+                                        ((Player) nextEntity).attack(targetEntity);
+                                        TurnBasedMinecraftMod.proxy.setAttackingEntity(null);
+                                        sendMessageToAllPlayers(PacketBattleMessage.MessageType.ATTACK, nextEntity.getId(), targetEntity.getId(), TurnBasedMinecraftMod.proxy.getAttackingDamage());
+                                        if (defenseDamageTriggered) {
+                                            // defense damage
+                                            DamageSource defenseDamageSource = DamageSource.mobAttack((LivingEntity) targetEntity);
+                                            TurnBasedMinecraftMod.proxy.setAttackingEntity(targetEntity);
+                                            nextEntity.invulnerableTime = 0;
+                                            nextEntity.hurt(defenseDamageSource, targetEntityInfo.defenseDamage);
+                                            TurnBasedMinecraftMod.proxy.setAttackingEntity(null);
+                                            sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENSE_DAMAGE, targetEntity.getId(), nextEntity.getId(), targetEntityInfo.defenseDamage);
+                                        }
+                                    } else {
+                                        debugLog += " hit blocked";
+                                        // blocked
+                                        --target.remainingDefenses;
+                                        sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFEND, target.entity.getId(), next.entity.getId(), 0);
                                     }
+                                } else {
+                                    debugLog += " hit missed";
+                                    // miss
+                                    sendMessageToAllPlayers(PacketBattleMessage.MessageType.MISS, next.entity.getId(), target.entity.getId(), 0);
                                 }
-                                else
-                                {
-                                    if(sideA.size() > 0)
-                                    {
-                                        int randomTargetIndex = random.nextInt(sideA.size());
-                                        for(Combatant c : sideA.values())
-                                        {
-                                            if(randomTargetIndex-- == 0)
-                                            {
-                                                target = c;
-                                                break;
+                            } else {
+                                debugLog += " as mob";
+                                LivingEntity attackTarget = ((Mob) next.entity).getTarget();
+                                if (attackTarget != null && hasCombatant(attackTarget.getId())) {
+                                    debugLog += " to targeted";
+                                    target = getCombatantByID(attackTarget.getId());
+                                } else {
+                                    debugLog += " to random other side";
+                                    if (next.isSideA) {
+                                        if (sideB.size() > 0) {
+                                            int randomTargetIndex = random.nextInt(sideB.size());
+                                            for (Combatant c : sideB.values()) {
+                                                if (randomTargetIndex-- == 0) {
+                                                    target = c;
+                                                    break;
+                                                }
+                                            }
+                                        }
+                                    } else {
+                                        if (sideA.size() > 0) {
+                                            int randomTargetIndex = random.nextInt(sideA.size());
+                                            for (Combatant c : sideA.values()) {
+                                                if (randomTargetIndex-- == 0) {
+                                                    target = c;
+                                                    break;
+                                                }
                                             }
                                         }
                                     }
                                 }
-                            }
-                            if(target == null || !target.entity.isAlive() || target == next)
-                            {
-                                continue;
-                            }
-                            int hitChance = next.entityInfo.attackProbability;
-                            if(target.entity instanceof Player)
-                            {
-                                hitChance = hitChance * (100 - TurnBasedMinecraftMod.proxy.getConfig().getPlayerEvasion()) / 100;
-                            }
-                            else
-                            {
-                                hitChance = hitChance * (100 - target.entityInfo.evasion) / 100;
-                            }
-                            if(hitChance < TurnBasedMinecraftMod.proxy.getConfig().getMinimumHitPercentage())
-                            {
-                                hitChance = TurnBasedMinecraftMod.proxy.getConfig().getMinimumHitPercentage();
-                            }
-                            if(random.nextInt(100) < hitChance)
-                            {
-                                if(target.remainingDefenses <= 0)
-                                {
-                                    debugLog += " hit success";
-                                    DamageSource damageSource = DamageSource.mobAttack((LivingEntity)next.entity);
-                                    int damageAmount = next.entityInfo.attackPower;
-                                    if(next.entityInfo.attackVariance > 0)
-                                    {
-                                        damageAmount += random.nextInt(next.entityInfo.attackVariance * 2 + 1) - next.entityInfo.attackVariance;
-                                    }
-                                    if(damageAmount < 0)
-                                    {
-                                        damageAmount = 0;
-                                    }
-                                    // attack
-                                    final Entity nextEntity = next.entity;
-                                    final EntityInfo nextEntityInfo = next.entityInfo;
-                                    final Entity targetEntity = target.entity;
-                                    final EntityInfo targetEntityInfo = target.entityInfo;
-                                    final int finalDamageAmount = damageAmount;
-                                    final boolean defenseDamageTriggered;
-                                    final boolean attackEffectTriggered;
-
-                                    if(!(targetEntity instanceof Player) && targetEntityInfo.defenseDamage > 0 && targetEntityInfo.defenseDamageProbability > 0)
-                                    {
-                                        if(random.nextInt(100) < targetEntityInfo.defenseDamageProbability)
-                                        {
-                                            defenseDamageTriggered = true;
+                                if (target == null || !target.entity.isAlive() || target == next) {
+                                    continue;
+                                }
+                                int hitChance = next.entityInfo.attackProbability;
+                                if (target.entity instanceof Player) {
+                                    hitChance = hitChance * (100 - TurnBasedMinecraftMod.proxy.getConfig().getPlayerEvasion()) / 100;
+                                } else {
+                                    hitChance = hitChance * (100 - target.entityInfo.evasion) / 100;
+                                }
+                                if (hitChance < TurnBasedMinecraftMod.proxy.getConfig().getMinimumHitPercentage()) {
+                                    hitChance = TurnBasedMinecraftMod.proxy.getConfig().getMinimumHitPercentage();
+                                }
+                                if (random.nextInt(100) < hitChance) {
+                                    if (target.remainingDefenses <= 0) {
+                                        debugLog += " hit success";
+                                        DamageSource damageSource = DamageSource.mobAttack((LivingEntity) next.entity);
+                                        int damageAmount = next.entityInfo.attackPower;
+                                        if (next.entityInfo.attackVariance > 0) {
+                                            damageAmount += random.nextInt(next.entityInfo.attackVariance * 2 + 1) - next.entityInfo.attackVariance;
                                         }
-                                        else
-                                        {
-                                            defenseDamageTriggered = false;
+                                        if (damageAmount < 0) {
+                                            damageAmount = 0;
                                         }
-                                    }
-                                    else
-                                    {
-                                        defenseDamageTriggered = false;
-                                    }
+                                        // attack
+                                        final Entity nextEntity = next.entity;
+                                        final EntityInfo nextEntityInfo = next.entityInfo;
+                                        final Entity targetEntity = target.entity;
+                                        final EntityInfo targetEntityInfo = target.entityInfo;
+                                        final int finalDamageAmount = damageAmount;
+                                        final boolean defenseDamageTriggered;
+                                        final boolean attackEffectTriggered;
 
-                                    if(nextEntityInfo.attackEffect != EntityInfo.Effect.UNKNOWN && nextEntityInfo.attackEffectProbability > 0)
-                                    {
-                                        if(random.nextInt(100) < nextEntityInfo.attackEffectProbability)
-                                        {
-                                            attackEffectTriggered = true;
+                                        if (!(targetEntity instanceof Player) && targetEntityInfo.defenseDamage > 0 && targetEntityInfo.defenseDamageProbability > 0) {
+                                            if (random.nextInt(100) < targetEntityInfo.defenseDamageProbability) {
+                                                defenseDamageTriggered = true;
+                                            } else {
+                                                defenseDamageTriggered = false;
+                                            }
+                                        } else {
+                                            defenseDamageTriggered = false;
                                         }
-                                        else
-                                        {
+
+                                        if (nextEntityInfo.attackEffect != EntityInfo.Effect.UNKNOWN && nextEntityInfo.attackEffectProbability > 0) {
+                                            if (random.nextInt(100) < nextEntityInfo.attackEffectProbability) {
+                                                attackEffectTriggered = true;
+                                            } else {
+                                                attackEffectTriggered = false;
+                                            }
+                                        } else {
                                             attackEffectTriggered = false;
                                         }
-                                    }
-                                    else
-                                    {
-                                        attackEffectTriggered = false;
-                                    }
 
-                                    TurnBasedMinecraftMod.proxy.setAttackingEntity(nextEntity);
-                                    targetEntity.hurt(damageSource, finalDamageAmount);
-                                    TurnBasedMinecraftMod.proxy.setAttackingEntity(null);
-                                    sendMessageToAllPlayers(PacketBattleMessage.MessageType.ATTACK, nextEntity.getId(), targetEntity.getId(), finalDamageAmount);
-                                    if(defenseDamageTriggered)
-                                    {
-                                        // defense damage
-                                        DamageSource defenseDamageSource = DamageSource.mobAttack((LivingEntity)targetEntity);
-                                        TurnBasedMinecraftMod.proxy.setAttackingEntity(targetEntity);
-                                        nextEntity.hurt(defenseDamageSource, targetEntityInfo.defenseDamage);
+                                        TurnBasedMinecraftMod.proxy.setAttackingEntity(nextEntity);
+                                        targetEntity.invulnerableTime = 0;
+                                        targetEntity.hurt(damageSource, finalDamageAmount);
                                         TurnBasedMinecraftMod.proxy.setAttackingEntity(null);
-                                        sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENSE_DAMAGE, targetEntity.getId(), nextEntity.getId(), targetEntityInfo.defenseDamage);
-                                    }
-                                    // attack effect
-                                    if(attackEffectTriggered)
-                                    {
-                                        nextEntityInfo.attackEffect.applyEffectToEntity((LivingEntity)targetEntity);
-                                        sendMessageToAllPlayers(PacketBattleMessage.MessageType.WAS_AFFECTED, nextEntity.getId(), targetEntity.getId(), 0, nextEntityInfo.attackEffect.getAffectedString());
+                                        sendMessageToAllPlayers(PacketBattleMessage.MessageType.ATTACK, nextEntity.getId(), targetEntity.getId(), finalDamageAmount);
+                                        if (defenseDamageTriggered) {
+                                            // defense damage
+                                            DamageSource defenseDamageSource = DamageSource.mobAttack((LivingEntity) targetEntity);
+                                            TurnBasedMinecraftMod.proxy.setAttackingEntity(targetEntity);
+                                            nextEntity.invulnerableTime = 0;
+                                            nextEntity.hurt(defenseDamageSource, targetEntityInfo.defenseDamage);
+                                            TurnBasedMinecraftMod.proxy.setAttackingEntity(null);
+                                            sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENSE_DAMAGE, targetEntity.getId(), nextEntity.getId(), targetEntityInfo.defenseDamage);
+                                        }
+                                        // attack effect
+                                        if (attackEffectTriggered) {
+                                            nextEntityInfo.attackEffect.applyEffectToEntity((LivingEntity) targetEntity);
+                                            sendMessageToAllPlayers(PacketBattleMessage.MessageType.WAS_AFFECTED, nextEntity.getId(), targetEntity.getId(), 0, nextEntityInfo.attackEffect.getAffectedString());
+                                        }
+                                    } else {
+                                        debugLog += " hit blocked";
+                                        // blocked
+                                        --target.remainingDefenses;
+                                        sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFEND, target.entity.getId(), next.entity.getId(), 0);
                                     }
+                                } else {
+                                    debugLog += " hit missed";
+                                    // miss
+                                    sendMessageToAllPlayers(PacketBattleMessage.MessageType.MISS, next.entity.getId(), target.entity.getId(), 0);
                                 }
-                                else
-                                {
-                                    debugLog += " hit blocked";
-                                    // blocked
-                                    --target.remainingDefenses;
-                                    sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFEND, target.entity.getId(), next.entity.getId(), 0);
-                                }
-                            }
-                            else
-                            {
-                                debugLog += " hit missed";
-                                // miss
-                                sendMessageToAllPlayers(PacketBattleMessage.MessageType.MISS, next.entity.getId(), target.entity.getId(), 0);
                             }
-                        }
-                        break;
-                    case DEFEND:
-                        debugLog += " defend";
-                        next.remainingDefenses = TurnBasedMinecraftMod.proxy.getConfig().getDefenseDuration();
-                        sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENDING, next.entity.getId(), 0, 0);
-                        break;
-                    case FLEE:
-                        debugLog += " flee";
-                        int fastestEnemySpeed = 0;
-                        if(next.isSideA)
-                        {
-                            for(Combatant c : sideB.values())
-                            {
-                                if(c.entity instanceof Player)
-                                {
-                                    int playerSpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerSpeed();
-                                    if (((Player) c.entity).hasEffect(MobEffects.MOVEMENT_SPEED)) {
-                                        playerSpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerHasteSpeed();
-                                    } else if (((Player) c.entity).hasEffect(MobEffects.MOVEMENT_SLOWDOWN)) {
-                                        playerSpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerSlowSpeed();
-                                    }
-                                    if(playerSpeed > fastestEnemySpeed)
-                                    {
-                                        fastestEnemySpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerSpeed();
+                            break;
+                        case DEFEND:
+                            debugLog += " defend";
+                            next.remainingDefenses = TurnBasedMinecraftMod.proxy.getConfig().getDefenseDuration();
+                            sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENDING, next.entity.getId(), 0, 0);
+                            break;
+                        case FLEE:
+                            debugLog += " flee";
+                            int fastestEnemySpeed = 0;
+                            if (next.isSideA) {
+                                for (Combatant c : sideB.values()) {
+                                    if (c.entity instanceof Player) {
+                                        int playerSpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerSpeed();
+                                        if (((Player) c.entity).hasEffect(MobEffects.MOVEMENT_SPEED)) {
+                                            playerSpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerHasteSpeed();
+                                        } else if (((Player) c.entity).hasEffect(MobEffects.MOVEMENT_SLOWDOWN)) {
+                                            playerSpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerSlowSpeed();
+                                        }
+                                        if (playerSpeed > fastestEnemySpeed) {
+                                            fastestEnemySpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerSpeed();
+                                        }
+                                    } else {
+                                        if (c.entityInfo.speed > fastestEnemySpeed) {
+                                            fastestEnemySpeed = c.entityInfo.speed;
+                                        }
                                     }
                                 }
-                                else
-                                {
-                                    if(c.entityInfo.speed > fastestEnemySpeed)
-                                    {
-                                        fastestEnemySpeed = c.entityInfo.speed;
+                            } else {
+                                for (Combatant c : sideA.values()) {
+                                    if (c.entity instanceof Player) {
+                                        int playerSpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerSpeed();
+                                        if (((Player) c.entity).hasEffect(MobEffects.MOVEMENT_SPEED)) {
+                                            playerSpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerHasteSpeed();
+                                        } else if (((Player) c.entity).hasEffect(MobEffects.MOVEMENT_SLOWDOWN)) {
+                                            playerSpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerSlowSpeed();
+                                        }
+                                        if (playerSpeed > fastestEnemySpeed) {
+                                            fastestEnemySpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerSpeed();
+                                        }
+                                    } else {
+                                        if (c.entityInfo.speed > fastestEnemySpeed) {
+                                            fastestEnemySpeed = c.entityInfo.speed;
+                                        }
                                     }
                                 }
                             }
-                        }
-                        else
-                        {
-                            for(Combatant c : sideA.values())
-                            {
-                                if(c.entity instanceof Player)
-                                {
-                                    int playerSpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerSpeed();
-                                    if (((Player) c.entity).hasEffect(MobEffects.MOVEMENT_SPEED)) {
-                                        playerSpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerHasteSpeed();
-                                    } else if (((Player) c.entity).hasEffect(MobEffects.MOVEMENT_SLOWDOWN)) {
-                                        playerSpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerSlowSpeed();
-                                    }
-                                    if(playerSpeed > fastestEnemySpeed)
-                                    {
-                                        fastestEnemySpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerSpeed();
-                                    }
+                            int fleeProbability = 0;
+                            if (next.entity instanceof Player) {
+                                int playerSpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerSpeed();
+                                if (((Player) next.entity).hasEffect(MobEffects.MOVEMENT_SPEED)) {
+                                    playerSpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerHasteSpeed();
+                                } else if (((Player) next.entity).hasEffect(MobEffects.MOVEMENT_SLOWDOWN)) {
+                                    playerSpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerSlowSpeed();
                                 }
-                                else
-                                {
-                                    if(c.entityInfo.speed > fastestEnemySpeed)
-                                    {
-                                        fastestEnemySpeed = c.entityInfo.speed;
-                                    }
+                                if (fastestEnemySpeed >= playerSpeed) {
+                                    fleeProbability = TurnBasedMinecraftMod.proxy.getConfig().getFleeBadProbability();
+                                } else {
+                                    fleeProbability = TurnBasedMinecraftMod.proxy.getConfig().getFleeGoodProbability();
+                                }
+                            } else {
+                                if (fastestEnemySpeed >= next.entityInfo.speed) {
+                                    fleeProbability = TurnBasedMinecraftMod.proxy.getConfig().getFleeBadProbability();
+                                } else {
+                                    fleeProbability = TurnBasedMinecraftMod.proxy.getConfig().getFleeGoodProbability();
                                 }
                             }
-                        }
-                        int fleeProbability = 0;
-                        if(next.entity instanceof Player)
-                        {
-                            int playerSpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerSpeed();
-                            if (((Player) next.entity).hasEffect(MobEffects.MOVEMENT_SPEED)) {
-                                playerSpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerHasteSpeed();
-                            } else if (((Player) next.entity).hasEffect(MobEffects.MOVEMENT_SLOWDOWN)) {
-                                playerSpeed = TurnBasedMinecraftMod.proxy.getConfig().getPlayerSlowSpeed();
-                            }
-                            if(fastestEnemySpeed >= playerSpeed)
-                            {
-                                fleeProbability = TurnBasedMinecraftMod.proxy.getConfig().getFleeBadProbability();
-                            }
-                            else
-                            {
-                                fleeProbability = TurnBasedMinecraftMod.proxy.getConfig().getFleeGoodProbability();
-                            }
-                        }
-                        else
-                        {
-                            if(fastestEnemySpeed >= next.entityInfo.speed)
-                            {
-                                fleeProbability = TurnBasedMinecraftMod.proxy.getConfig().getFleeBadProbability();
-                            }
-                            else
-                            {
-                                fleeProbability = TurnBasedMinecraftMod.proxy.getConfig().getFleeGoodProbability();
-                            }
-                        }
-                        if(random.nextInt(100) < fleeProbability)
-                        {
-                            debugLog += " success";
-                            // flee success
-                            combatantsChanged = true;
-                            String fleeingCategory = new String();
-                            if(next.entityInfo != null)
-                            {
-                                fleeingCategory = next.entityInfo.category;
-                            }
-                            else if(next.entity instanceof Player)
-                            {
-                                fleeingCategory = "player";
+                            if (random.nextInt(100) < fleeProbability) {
+                                debugLog += " success";
+                                // flee success
+                                combatantsChanged = true;
+                                String fleeingCategory = new String();
+                                if (next.entityInfo != null) {
+                                    fleeingCategory = next.entityInfo.category;
+                                } else if (next.entity instanceof Player) {
+                                    fleeingCategory = "player";
+                                }
+                                removeCombatant(next);
+                                sendMessageToAllPlayers(PacketBattleMessage.MessageType.FLEE, next.entity.getId(), 0, 1, fleeingCategory);
+                            } else {
+                                debugLog += " fail";
+                                // flee fail
+                                sendMessageToAllPlayers(PacketBattleMessage.MessageType.FLEE, next.entity.getId(), 0, 0);
                             }
-                            removeCombatant(next);
-                            sendMessageToAllPlayers(PacketBattleMessage.MessageType.FLEE, next.entity.getId(), 0, 1, fleeingCategory);
-                        }
-                        else
-                        {
-                            debugLog += " fail";
-                            // flee fail
-                            sendMessageToAllPlayers(PacketBattleMessage.MessageType.FLEE, next.entity.getId(), 0, 0);
-                        }
-                        break;
-                    case USE_ITEM:
-                        debugLog += " use item";
-                        if(next.itemToUse < 0 || next.itemToUse > 8)
-                        {
-                            debugLog += " invalid";
-                            sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getId(), 0, PacketBattleMessage.UsedItemAction.USED_INVALID.getValue());
                             break;
-                        }
-                        ItemStack targetItemStack = ((Player) next.entity).getInventory().getItem(next.itemToUse);
-                        Item targetItem = targetItemStack.getItem();
-                        if(targetItem == null)
-                        {
-                            debugLog += " null";
-                            sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getId(), 0, PacketBattleMessage.UsedItemAction.USED_NOTHING.getValue());
-                            break;
-                        } else if(targetItem.isEdible()) {
-                            debugLog += " food";
-                            sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getId(), 0, PacketBattleMessage.UsedItemAction.USED_FOOD.getValue(), targetItemStack.getDisplayName().getString());
-                            final Entity nextEntity = next.entity;
-                            final int nextItemToUse = next.itemToUse;
-                            ((Player) nextEntity).getInventory().setItem(nextItemToUse, targetItem.finishUsingItem(targetItemStack, nextEntity.level, (LivingEntity)nextEntity));
-                        } else {
-                            // then check vanilla foods
-                            if (targetItem.getItemCategory() == CreativeModeTab.TAB_FOOD && targetItem.isEdible()) {
+                        case USE_ITEM:
+                            debugLog += " use item";
+                            if (next.itemToUse < 0 || next.itemToUse > 8) {
+                                debugLog += " invalid";
+                                sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getId(), 0, PacketBattleMessage.UsedItemAction.USED_INVALID.getValue());
+                                break;
+                            }
+                            ItemStack targetItemStack = ((Player) next.entity).getInventory().getItem(next.itemToUse);
+                            Item targetItem = targetItemStack.getItem();
+                            if (targetItem == null) {
+                                debugLog += " null";
+                                sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getId(), 0, PacketBattleMessage.UsedItemAction.USED_NOTHING.getValue());
+                                break;
+                            } else if (targetItem.isEdible()) {
                                 debugLog += " food";
                                 sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getId(), 0, PacketBattleMessage.UsedItemAction.USED_FOOD.getValue(), targetItemStack.getDisplayName().getString());
                                 final Entity nextEntity = next.entity;
                                 final int nextItemToUse = next.itemToUse;
                                 ((Player) nextEntity).getInventory().setItem(nextItemToUse, targetItem.finishUsingItem(targetItemStack, nextEntity.level, (LivingEntity) nextEntity));
-                            } else if (targetItem instanceof PotionItem) {
-                                debugLog += " potion";
-                                sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getId(), 0, PacketBattleMessage.UsedItemAction.USED_POTION.getValue(), targetItemStack.getDisplayName().getString());
-                                final Entity nextEntity = next.entity;
-                                final int nextItemToUse = next.itemToUse;
-                                ((Player) nextEntity).getInventory().setItem(nextItemToUse, targetItem.finishUsingItem(targetItemStack, nextEntity.level, (LivingEntity) nextEntity));
                             } else {
-                                debugLog += " non-consumable";
-                                sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getId(), 0, PacketBattleMessage.UsedItemAction.USED_INVALID.getValue(), targetItemStack.getDisplayName().getString());
+                                // then check vanilla foods
+                                if (targetItem.getItemCategory() == CreativeModeTab.TAB_FOOD && targetItem.isEdible()) {
+                                    debugLog += " food";
+                                    sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getId(), 0, PacketBattleMessage.UsedItemAction.USED_FOOD.getValue(), targetItemStack.getDisplayName().getString());
+                                    final Entity nextEntity = next.entity;
+                                    final int nextItemToUse = next.itemToUse;
+                                    ((Player) nextEntity).getInventory().setItem(nextItemToUse, targetItem.finishUsingItem(targetItemStack, nextEntity.level, (LivingEntity) nextEntity));
+                                } else if (targetItem instanceof PotionItem) {
+                                    debugLog += " potion";
+                                    sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getId(), 0, PacketBattleMessage.UsedItemAction.USED_POTION.getValue(), targetItemStack.getDisplayName().getString());
+                                    final Entity nextEntity = next.entity;
+                                    final int nextItemToUse = next.itemToUse;
+                                    ((Player) nextEntity).getInventory().setItem(nextItemToUse, targetItem.finishUsingItem(targetItemStack, nextEntity.level, (LivingEntity) nextEntity));
+                                } else {
+                                    debugLog += " non-consumable";
+                                    sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getId(), 0, PacketBattleMessage.UsedItemAction.USED_INVALID.getValue(), targetItemStack.getDisplayName().getString());
+                                }
                             }
-                        }
-                        break;
-                    case SWITCH_ITEM: {
-                        debugLog += " switch item";
-                        if (next.itemToUse < 0 || next.itemToUse > 8) {
-                            sendMessageToAllPlayers(PacketBattleMessage.MessageType.SWITCHED_ITEM, next.entity.getId(), 0, 0);
                             break;
-                        }
-                        final Entity nextEntity = next.entity;
-                        final int nextItemToUse = next.itemToUse;
-                        ((Player) nextEntity).getInventory().selected = nextItemToUse;
-                        sendMessageToAllPlayers(PacketBattleMessage.MessageType.SWITCHED_ITEM, next.entity.getId(), 0, 1);
-                    }
-                        break;
-                    case CREEPER_WAIT:
-                        debugLog += " creeper wait";
-                        if(next.creeperTurns < TurnBasedMinecraftMod.proxy.getConfig().getCreeperExplodeTurn()) {
-                            sendMessageToAllPlayers(PacketBattleMessage.MessageType.CREEPER_WAIT, next.entity.getId(), 0, 0);
-                        } else {
-                            sendMessageToAllPlayers(PacketBattleMessage.MessageType.CREEPER_WAIT_FINAL, next.entity.getId(), 0, 0);
+                        case SWITCH_ITEM: {
+                            debugLog += " switch item";
+                            if (next.itemToUse < 0 || next.itemToUse > 8) {
+                                sendMessageToAllPlayers(PacketBattleMessage.MessageType.SWITCHED_ITEM, next.entity.getId(), 0, 0);
+                                break;
+                            }
+                            final Entity nextEntity = next.entity;
+                            final int nextItemToUse = next.itemToUse;
+                            ((Player) nextEntity).getInventory().selected = nextItemToUse;
+                            sendMessageToAllPlayers(PacketBattleMessage.MessageType.SWITCHED_ITEM, next.entity.getId(), 0, 1);
                         }
                         break;
-                    case CREEPER_EXPLODE: {
-                        debugLog += " creeper explode";
-                        sendMessageToAllPlayers(PacketBattleMessage.MessageType.CREEPER_EXPLODE, next.entity.getId(), 0, 0);
-                        final Entity nextEntity = next.entity;
-                        final EntityInfo nextEntityInfo = next.entityInfo;
-                        for (Combatant c : sideA.values()) {
-                            if (c.entity.getId() != next.entity.getId()) {
-                                int hitChance = next.entityInfo.attackProbability;
-                                if (c.entity instanceof Player) {
-                                    hitChance = hitChance * (100 - TurnBasedMinecraftMod.proxy.getConfig().getPlayerEvasion()) / 100;
-                                } else {
-                                    hitChance = hitChance * (100 - c.entityInfo.evasion) / 100;
-                                }
-                                if (hitChance < TurnBasedMinecraftMod.proxy.getConfig().getMinimumHitPercentage()) {
-                                    hitChance = TurnBasedMinecraftMod.proxy.getConfig().getMinimumHitPercentage();
-                                }
-                                if (random.nextInt(100) < hitChance) {
-                                    final Entity targetEntity = c.entity;
-                                    final EntityInfo targetEntityInfo = c.entityInfo;
-                                    int damageAmount = nextEntityInfo.attackPower;
-                                    if (nextEntityInfo.attackVariance > 0) {
-                                        damageAmount += random.nextInt(nextEntityInfo.attackVariance * 2 + 1) - nextEntityInfo.attackVariance;
+                        case CREEPER_WAIT:
+                            debugLog += " creeper wait";
+                            if (next.creeperTurns < TurnBasedMinecraftMod.proxy.getConfig().getCreeperExplodeTurn()) {
+                                sendMessageToAllPlayers(PacketBattleMessage.MessageType.CREEPER_WAIT, next.entity.getId(), 0, 0);
+                            } else {
+                                sendMessageToAllPlayers(PacketBattleMessage.MessageType.CREEPER_WAIT_FINAL, next.entity.getId(), 0, 0);
+                            }
+                            break;
+                        case CREEPER_EXPLODE: {
+                            debugLog += " creeper explode";
+                            sendMessageToAllPlayers(PacketBattleMessage.MessageType.CREEPER_EXPLODE, next.entity.getId(), 0, 0);
+                            final Entity nextEntity = next.entity;
+                            final EntityInfo nextEntityInfo = next.entityInfo;
+                            for (Combatant c : sideA.values()) {
+                                if (c.entity.getId() != next.entity.getId()) {
+                                    int hitChance = next.entityInfo.attackProbability;
+                                    if (c.entity instanceof Player) {
+                                        hitChance = hitChance * (100 - TurnBasedMinecraftMod.proxy.getConfig().getPlayerEvasion()) / 100;
+                                    } else {
+                                        hitChance = hitChance * (100 - c.entityInfo.evasion) / 100;
                                     }
-                                    if (damageAmount < 0) {
-                                        damageAmount = 0;
+                                    if (hitChance < TurnBasedMinecraftMod.proxy.getConfig().getMinimumHitPercentage()) {
+                                        hitChance = TurnBasedMinecraftMod.proxy.getConfig().getMinimumHitPercentage();
                                     }
-                                    final int finalDamageAmount = damageAmount;
-                                    final boolean attackEffectTriggered;
-                                    if (nextEntityInfo.attackEffect != EntityInfo.Effect.UNKNOWN && nextEntityInfo.attackEffectProbability > 0) {
-                                        if (random.nextInt(100) < nextEntityInfo.attackEffectProbability) {
-                                            attackEffectTriggered = true;
+                                    if (random.nextInt(100) < hitChance) {
+                                        final Entity targetEntity = c.entity;
+                                        final EntityInfo targetEntityInfo = c.entityInfo;
+                                        int damageAmount = nextEntityInfo.attackPower;
+                                        if (nextEntityInfo.attackVariance > 0) {
+                                            damageAmount += random.nextInt(nextEntityInfo.attackVariance * 2 + 1) - nextEntityInfo.attackVariance;
+                                        }
+                                        if (damageAmount < 0) {
+                                            damageAmount = 0;
+                                        }
+                                        final int finalDamageAmount = damageAmount;
+                                        final boolean attackEffectTriggered;
+                                        if (nextEntityInfo.attackEffect != EntityInfo.Effect.UNKNOWN && nextEntityInfo.attackEffectProbability > 0) {
+                                            if (random.nextInt(100) < nextEntityInfo.attackEffectProbability) {
+                                                attackEffectTriggered = true;
+                                            } else {
+                                                attackEffectTriggered = false;
+                                            }
                                         } else {
                                             attackEffectTriggered = false;
                                         }
-                                    } else {
-                                        attackEffectTriggered = false;
-                                    }
 
-                                    TurnBasedMinecraftMod.proxy.setAttackingEntity(nextEntity);
-                                    targetEntity.hurt(DamageSource.mobAttack((LivingEntity) nextEntity), finalDamageAmount);
-                                    TurnBasedMinecraftMod.proxy.setAttackingEntity(null);
-                                    sendMessageToAllPlayers(PacketBattleMessage.MessageType.ATTACK, nextEntity.getId(), targetEntity.getId(), finalDamageAmount);
-                                    if(attackEffectTriggered) {
-                                        nextEntityInfo.attackEffect.applyEffectToEntity((LivingEntity)targetEntity);
-                                        sendMessageToAllPlayers(PacketBattleMessage.MessageType.WAS_AFFECTED, nextEntity.getId(), targetEntity.getId(), 0, nextEntityInfo.attackEffect.getAffectedString());
+                                        TurnBasedMinecraftMod.proxy.setAttackingEntity(nextEntity);
+                                        targetEntity.invulnerableTime = 0;
+                                        targetEntity.hurt(DamageSource.mobAttack((LivingEntity) nextEntity), finalDamageAmount);
+                                        TurnBasedMinecraftMod.proxy.setAttackingEntity(null);
+                                        sendMessageToAllPlayers(PacketBattleMessage.MessageType.ATTACK, nextEntity.getId(), targetEntity.getId(), finalDamageAmount);
+                                        if (attackEffectTriggered) {
+                                            nextEntityInfo.attackEffect.applyEffectToEntity((LivingEntity) targetEntity);
+                                            sendMessageToAllPlayers(PacketBattleMessage.MessageType.WAS_AFFECTED, nextEntity.getId(), targetEntity.getId(), 0, nextEntityInfo.attackEffect.getAffectedString());
+                                        }
                                     }
                                 }
                             }
-                        }
-                        for(Combatant c : sideB.values()) {
-                            if (c.entity.getId() != next.entity.getId()) {
-                                int hitChance = next.entityInfo.attackProbability;
-                                if (c.entity instanceof Player) {
-                                    hitChance = hitChance * (100 - TurnBasedMinecraftMod.proxy.getConfig().getPlayerEvasion()) / 100;
-                                } else {
-                                    hitChance = hitChance * (100 - c.entityInfo.evasion) / 100;
-                                }
-                                if (hitChance < TurnBasedMinecraftMod.proxy.getConfig().getMinimumHitPercentage()) {
-                                    hitChance = TurnBasedMinecraftMod.proxy.getConfig().getMinimumHitPercentage();
-                                }
-                                if (random.nextInt(100) < hitChance) {
-                                    final Entity targetEntity = c.entity;
-                                    final EntityInfo targetEntityInfo = c.entityInfo;
-                                    int damageAmount = nextEntityInfo.attackPower;
-                                    if (nextEntityInfo.attackVariance > 0) {
-                                        damageAmount += random.nextInt(nextEntityInfo.attackVariance * 2 + 1) - nextEntityInfo.attackVariance;
+                            for (Combatant c : sideB.values()) {
+                                if (c.entity.getId() != next.entity.getId()) {
+                                    int hitChance = next.entityInfo.attackProbability;
+                                    if (c.entity instanceof Player) {
+                                        hitChance = hitChance * (100 - TurnBasedMinecraftMod.proxy.getConfig().getPlayerEvasion()) / 100;
+                                    } else {
+                                        hitChance = hitChance * (100 - c.entityInfo.evasion) / 100;
                                     }
-                                    if (damageAmount < 0) {
-                                        damageAmount = 0;
+                                    if (hitChance < TurnBasedMinecraftMod.proxy.getConfig().getMinimumHitPercentage()) {
+                                        hitChance = TurnBasedMinecraftMod.proxy.getConfig().getMinimumHitPercentage();
                                     }
-                                    final int finalDamageAmount = damageAmount;
-                                    final boolean attackEffectTriggered;
-                                    if (nextEntityInfo.attackEffect != EntityInfo.Effect.UNKNOWN && nextEntityInfo.attackEffectProbability > 0) {
-                                        if (random.nextInt(100) < nextEntityInfo.attackEffectProbability) {
-                                            attackEffectTriggered = true;
+                                    if (random.nextInt(100) < hitChance) {
+                                        final Entity targetEntity = c.entity;
+                                        final EntityInfo targetEntityInfo = c.entityInfo;
+                                        int damageAmount = nextEntityInfo.attackPower;
+                                        if (nextEntityInfo.attackVariance > 0) {
+                                            damageAmount += random.nextInt(nextEntityInfo.attackVariance * 2 + 1) - nextEntityInfo.attackVariance;
+                                        }
+                                        if (damageAmount < 0) {
+                                            damageAmount = 0;
+                                        }
+                                        final int finalDamageAmount = damageAmount;
+                                        final boolean attackEffectTriggered;
+                                        if (nextEntityInfo.attackEffect != EntityInfo.Effect.UNKNOWN && nextEntityInfo.attackEffectProbability > 0) {
+                                            if (random.nextInt(100) < nextEntityInfo.attackEffectProbability) {
+                                                attackEffectTriggered = true;
+                                            } else {
+                                                attackEffectTriggered = false;
+                                            }
                                         } else {
                                             attackEffectTriggered = false;
                                         }
-                                    } else {
-                                        attackEffectTriggered = false;
-                                    }
 
-                                    TurnBasedMinecraftMod.proxy.setAttackingEntity(nextEntity);
-                                    targetEntity.hurt(DamageSource.mobAttack((LivingEntity) nextEntity), finalDamageAmount);
-                                    TurnBasedMinecraftMod.proxy.setAttackingEntity(null);
-                                    sendMessageToAllPlayers(PacketBattleMessage.MessageType.ATTACK, nextEntity.getId(), targetEntity.getId(), finalDamageAmount);
-                                    if(attackEffectTriggered) {
-                                        nextEntityInfo.attackEffect.applyEffectToEntity((LivingEntity)targetEntity);
-                                        sendMessageToAllPlayers(PacketBattleMessage.MessageType.WAS_AFFECTED, nextEntity.getId(), targetEntity.getId(), 0, nextEntityInfo.attackEffect.getAffectedString());
+                                        TurnBasedMinecraftMod.proxy.setAttackingEntity(nextEntity);
+                                        targetEntity.invulnerableTime = 0;
+                                        targetEntity.hurt(DamageSource.mobAttack((LivingEntity) nextEntity), finalDamageAmount);
+                                        TurnBasedMinecraftMod.proxy.setAttackingEntity(null);
+                                        sendMessageToAllPlayers(PacketBattleMessage.MessageType.ATTACK, nextEntity.getId(), targetEntity.getId(), finalDamageAmount);
+                                        if (attackEffectTriggered) {
+                                            nextEntityInfo.attackEffect.applyEffectToEntity((LivingEntity) targetEntity);
+                                            sendMessageToAllPlayers(PacketBattleMessage.MessageType.WAS_AFFECTED, nextEntity.getId(), targetEntity.getId(), 0, nextEntityInfo.attackEffect.getAffectedString());
+                                        }
                                     }
                                 }
                             }
+                            ((Creeper) nextEntity).setSwellDir(1000000);
                         }
-                        ((Creeper)nextEntity).setSwellDir(1000000);
-                    }
                         break;
                     }
+                } while (false);
+                debugLog = "Action almost end";
+                if (turnOrderQueue.isEmpty()) {
+                    setDecisionState();
+                    if (healthCheck()) {
+                        combatantsChanged = true;
+                    }
+                    if (isCreativeCheck()) {
+                        combatantsChanged = true;
+                    }
+                    debugLog += ", adding task";
+                    sendMessageToAllPlayers(PacketBattleMessage.MessageType.TURN_END, 0, 0, 0);
                 }
-                debugLog = "Actions almost end";
-                setDecisionState();
-                if(healthCheck())
-                {
-                    combatantsChanged = true;
-                }
-                if(isCreativeCheck())
-                {
-                    combatantsChanged = true;
-                }
-                debugLog += ", adding task";
-                sendMessageToAllPlayers(PacketBattleMessage.MessageType.TURN_END, 0, 0, 0);
                 debugLog = "Actions end";
                 break;
             } // case ACTION
-        default:
-            state = State.DECISION;
-            break;
+            default:
+                state = State.DECISION;
+                break;
         } // switch(state)
         debugLog = "Update almost end";
-        if(combatantsChanged)
-        {
+        if (combatantsChanged) {
             notifyPlayersBattleInfo();
         }
-        if(battleEnded)
-        {
+        if (battleEnded) {
             Collection<Combatant> combatants = new ArrayList<Combatant>();
             combatants.addAll(sideA.values());
             combatants.addAll(sideB.values());
-            for(Combatant c : combatants)
-            {
+            for (Combatant c : combatants) {
                 removeCombatant(c);
             }
         }
@@ -1516,19 +1237,19 @@ public class Battle
     } // update(final long dt)
 
     private void defuseCreepers() {
-        for(Combatant c : sideA.values()) {
-            if(c.entity instanceof Creeper) {
-                if(c.creeperTurns <= TurnBasedMinecraftMod.proxy.getConfig().getCreeperExplodeTurn()) {
-                    ((Creeper)c.entity).setSwellDir(-10);
+        for (Combatant c : sideA.values()) {
+            if (c.entity instanceof Creeper) {
+                if (c.creeperTurns <= TurnBasedMinecraftMod.proxy.getConfig().getCreeperExplodeTurn()) {
+                    ((Creeper) c.entity).setSwellDir(-10);
                 } else {
-                    ((Creeper)c.entity).setSwellDir(1000000);
+                    ((Creeper) c.entity).setSwellDir(1000000);
                 }
             }
         }
-        for(Combatant c : sideB.values()) {
-            if(c.entity instanceof Creeper) {
-                if(c.creeperTurns <= TurnBasedMinecraftMod.proxy.getConfig().getCreeperExplodeTurn()) {
-                    ((Creeper)c.entity).setSwellDir(-10);
+        for (Combatant c : sideB.values()) {
+            if (c.entity instanceof Creeper) {
+                if (c.creeperTurns <= TurnBasedMinecraftMod.proxy.getConfig().getCreeperExplodeTurn()) {
+                    ((Creeper) c.entity).setSwellDir(-10);
                 } else {
                     ((Creeper) c.entity).setSwellDir(1000000);
                 }
index 6e28699b20bf3a039d30c3b8e6481c7a1574f7fb..b4bd274c0c3e9498444498c555f7f7998f5f4abf 100644 (file)
@@ -11,7 +11,7 @@ public class BattleUpdater
     private BattleManager manager;
     private AtomicBoolean isRunning;
     private int tick;
-    private final int tickLimit = 10;
+    private final int tickLimit = 3;
 
     public BattleUpdater(BattleManager manager)
     {
index a8daded404ebf92f43810aeddb6abdb324c5ba04..b7b35ee31b246d7b33c49e7897fa1d38d24a5bc0 100644 (file)
@@ -38,7 +38,7 @@ import org.apache.logging.log4j.Logger;
 public class TurnBasedMinecraftMod {
     public static final String MODID = "com_burnedkirby_turnbasedminecraft";
     public static final String NAME = "Turn Based Minecraft Mod";
-    public static final String VERSION = "1.18.3";
+    public static final String VERSION = "1.18.4";
     public static final String CONFIG_FILENAME = "TBM_Config.toml";
     public static final String DEFAULT_CONFIG_FILENAME = "TBM_Config_DEFAULT.toml";
     public static final String CONFIG_DIRECTORY = "config/TurnBasedMinecraft/";
index ce115f72d602413bae188d4daa33ed97ef9c0219..6e8ba6138bdbf39bd1ec7ff05627a4c30e2119d2 100644 (file)
@@ -15,7 +15,7 @@ license="MIT"
 # The modid of the mod
 modId="com_burnedkirby_turnbasedminecraft" #mandatory
 # The version number of the mod - there's a few well known ${} variables useable here or just hardcode it
-version="1.18.3" #mandatory
+version="1.18.4" #mandatory
  # A display name for the mod
 displayName="TurnBasedMinecraftMod" #mandatory
 # A URL to query for updates for this mod. See the JSON update specification <here>
index d0667d3144363e7bde88f861c04a57296951dec9..ef97da44450c6fd26317eb6a014c063e679649f4 100644 (file)
@@ -3,7 +3,7 @@
   "modid": "com_burnedkirby_turnbasedminecraft",
   "name": "Turn Based Minecraft",
   "description": "Changes battles to be turn-based.",
-  "version": "1.18.3",
+  "version": "1.18.4",
   "mcversion": "1.18.2",
   "url": "",
   "updateUrl": "",