diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/client/ClientProxy.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/client/ClientProxy.java index 35a1367..3089355 100644 --- a/src/main/java/com/seodisparate/TurnBasedMinecraft/client/ClientProxy.java +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/client/ClientProxy.java @@ -224,6 +224,6 @@ public class ClientProxy extends CommonProxy @Override public void createLocalBattle(int id) { - localBattle = new Battle(id, null, null, false); + localBattle = new Battle(null, id, null, null, false); } } diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/AttackEventHandler.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/AttackEventHandler.java index 4a33b59..ecf3f47 100644 --- a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/AttackEventHandler.java +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/AttackEventHandler.java @@ -64,13 +64,20 @@ public class AttackEventHandler { return; } - - if(!isAttackerValid(event) + Config config = TurnBasedMinecraftMod.proxy.getConfig(); + BattleManager battleManager = TurnBasedMinecraftMod.proxy.getBattleManager(); + if((event.getEntity() != null && battleManager.isRecentlyLeftBattle(event.getEntity().getEntityId())) + || (event.getSource().getTrueSource() != null && battleManager.isRecentlyLeftBattle(event.getSource().getTrueSource().getEntityId()))) + { + event.setCanceled(true); + return; + } + else if(!isAttackerValid(event) && event.getEntity() != null && event.getSource().getTrueSource() != null - && !TurnBasedMinecraftMod.proxy.getConfig().getBattleIgnoringPlayers().contains(event.getSource().getTrueSource().getEntityId()) - && !TurnBasedMinecraftMod.proxy.getConfig().getBattleIgnoringPlayers().contains(event.getEntity().getEntityId()) - && TurnBasedMinecraftMod.proxy.getBattleManager().checkAttack(event)) + && !config.getBattleIgnoringPlayers().contains(event.getSource().getTrueSource().getEntityId()) + && !config.getBattleIgnoringPlayers().contains(event.getEntity().getEntityId()) + && battleManager.checkAttack(event)) { // TurnBasedMinecraftMod.logger.debug("Canceled LivingAttackEvent between " + TurnBasedMinecraftMod.commonProxy.getAttackingEntity() + " and " + event.getEntity()); event.setCanceled(true); @@ -88,14 +95,19 @@ public class AttackEventHandler @SubscribeEvent public void entityTargeted(LivingSetAttackTargetEvent event) { - if(event.getEntity().world.isRemote || TurnBasedMinecraftMod.proxy.getConfig().isOldBattleBehaviorEnabled()) + Config config = TurnBasedMinecraftMod.proxy.getConfig(); + BattleManager battleManager = TurnBasedMinecraftMod.proxy.getBattleManager(); + if(event.getEntity().world.isRemote + || config.isOldBattleBehaviorEnabled() + || (event.getEntity() != null && battleManager.isRecentlyLeftBattle(event.getEntity().getEntityId())) + || (event.getTarget() != null && battleManager.isRecentlyLeftBattle(event.getTarget().getEntityId()))) { return; } else if(event.getEntity() != null && event.getTarget() != null - && !TurnBasedMinecraftMod.proxy.getConfig().getBattleIgnoringPlayers().contains(event.getEntity().getEntityId()) - && !TurnBasedMinecraftMod.proxy.getConfig().getBattleIgnoringPlayers().contains(event.getTarget().getEntityId())) + && !config.getBattleIgnoringPlayers().contains(event.getEntity().getEntityId()) + && !config.getBattleIgnoringPlayers().contains(event.getTarget().getEntityId())) { TurnBasedMinecraftMod.proxy.getBattleManager().checkTargeted(event); } diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Battle.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Battle.java index d40ca3f..3960512 100644 --- a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Battle.java +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Battle.java @@ -49,6 +49,8 @@ public class Battle private boolean isServer; private boolean battleEnded; + private BattleManager battleManager; + public enum State { DECISION(0), @@ -118,8 +120,9 @@ public class Battle } } - public Battle(int id, Collection sideA, Collection sideB, boolean isServer) + public Battle(BattleManager battleManager, int id, Collection sideA, Collection sideB, boolean isServer) { + this.battleManager = battleManager; this.isServer = isServer; this.id = id; this.sideA = new Hashtable(); @@ -515,16 +518,12 @@ public class Battle */ private boolean healthCheck() { - Queue removeQueue = new ArrayDeque(); + Queue removeQueue = new ArrayDeque(); for(Combatant c : sideA.values()) { if(!c.entity.isEntityAlive()) { - removeQueue.add(c.entity.getEntityId()); - if(c.entity instanceof EntityPlayer) - { - TurnBasedMinecraftMod.NWINSTANCE.sendTo(new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, c.entity.getEntityId(), 0, 0), (EntityPlayerMP)c.entity); - } + removeQueue.add(c); String category = new String(); if(c.entityInfo != null) { @@ -541,11 +540,7 @@ public class Battle { if(!c.entity.isEntityAlive()) { - removeQueue.add(c.entity.getEntityId()); - if(c.entity instanceof EntityPlayer) - { - TurnBasedMinecraftMod.NWINSTANCE.sendTo(new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, c.entity.getEntityId(), 0, 0), (EntityPlayerMP)c.entity); - } + removeQueue.add(c); String category = new String(); if(c.entityInfo != null) { @@ -559,14 +554,9 @@ public class Battle } } boolean didRemove = !removeQueue.isEmpty(); - for(Integer toRemove = removeQueue.poll(); toRemove != null; toRemove = removeQueue.poll()) + for(Combatant toRemove = removeQueue.poll(); toRemove != null; toRemove = removeQueue.poll()) { - sideA.remove(toRemove); - sideB.remove(toRemove); - if(players.remove(toRemove) != null) - { - playerCount.decrementAndGet(); - } + removeCombatant(toRemove); } if(players.isEmpty() || sideA.isEmpty() || sideB.isEmpty()) { @@ -586,24 +576,20 @@ public class Battle */ private boolean isCreativeCheck() { - Queue removeQueue = new ArrayDeque(); + Queue removeQueue = new ArrayDeque(); for(Combatant c : players.values()) { if(c.entity != null && ((EntityPlayer)c.entity).isCreative()) { - TurnBasedMinecraftMod.NWINSTANCE.sendTo(new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, c.entity.getEntityId(), 0, 0), (EntityPlayerMP)c.entity); - removeQueue.add(c.entity.getEntityId()); + removeQueue.add(c); } } boolean didRemove = false; - for(Integer toRemove = removeQueue.poll(); toRemove != null; toRemove = removeQueue.poll()) + for(Combatant toRemove = removeQueue.poll(); toRemove != null; toRemove = removeQueue.poll()) { didRemove = true; - sideA.remove(toRemove); - sideB.remove(toRemove); - players.remove(toRemove); - playerCount.decrementAndGet(); - sendMessageToAllPlayers(PacketBattleMessage.MessageType.BECAME_CREATIVE, toRemove, 0, 0); + removeCombatant(toRemove); + sendMessageToAllPlayers(PacketBattleMessage.MessageType.BECAME_CREATIVE, toRemove.entity.getEntityId(), 0, 0); } if(didRemove) { @@ -640,6 +626,18 @@ public class Battle } } + private void removeCombatant(Combatant c) + { + sideA.remove(c.entity.getEntityId()); + sideB.remove(c.entity.getEntityId()); + if(players.remove(c.entity.getEntityId()) != null) + { + playerCount.decrementAndGet(); + TurnBasedMinecraftMod.NWINSTANCE.sendTo(new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, 0, 0, 0), (EntityPlayerMP)c.entity); + } + battleManager.addRecentlyLeftBattle(c); + } + /** * @return True if battle has ended */ @@ -651,6 +649,13 @@ public class Battle } else if(battleEnded) { + Collection combatants = new ArrayList(); + combatants.addAll(sideA.values()); + combatants.addAll(sideB.values()); + for(Combatant c : combatants) + { + removeCombatant(c); + } return true; } long nextInstant = System.nanoTime(); @@ -663,6 +668,13 @@ public class Battle { if(battleEnded) { + Collection combatants = new ArrayList(); + combatants.addAll(sideA.values()); + combatants.addAll(sideB.values()); + for(Combatant c : combatants) + { + removeCombatant(c); + } return true; } boolean combatantsChanged = false; @@ -1066,14 +1078,6 @@ public class Battle if((int)(Math.random() * 100) < fleeProbability) { // flee success - if(next.isSideA) - { - sideA.remove(next.entity.getEntityId()); - } - else - { - sideB.remove(next.entity.getEntityId()); - } combatantsChanged = true; String fleeingCategory = new String(); if(next.entityInfo != null) @@ -1085,12 +1089,7 @@ public class Battle fleeingCategory = "player"; } sendMessageToAllPlayers(PacketBattleMessage.MessageType.FLEE, next.entity.getEntityId(), 0, 1, fleeingCategory); - if(next.entity instanceof EntityPlayer) - { - players.remove(next.entity.getEntityId()); - playerCount.decrementAndGet(); - TurnBasedMinecraftMod.NWINSTANCE.sendTo(new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, 0, 0, 0), (EntityPlayerMP)next.entity); - } + removeCombatant(next); } else { @@ -1180,6 +1179,16 @@ public class Battle { notifyPlayersBattleInfo(); } + if(battleEnded) + { + Collection combatants = new ArrayList(); + combatants.addAll(sideA.values()); + combatants.addAll(sideB.values()); + for(Combatant c : combatants) + { + removeCombatant(c); + } + } return battleEnded; } // update(final long dt) } diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/BattleManager.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/BattleManager.java index 4532c4f..6fbb8f5 100644 --- a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/BattleManager.java +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/BattleManager.java @@ -1,14 +1,22 @@ package com.seodisparate.TurnBasedMinecraft.common; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; import java.util.Hashtable; import java.util.Map; +import java.util.Queue; +import java.util.Set; import org.apache.logging.log4j.Logger; +import com.seodisparate.TurnBasedMinecraft.common.networking.PacketGeneralMessage; + import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent; @@ -19,6 +27,7 @@ public class BattleManager private Thread updaterThread; private BattleUpdater battleUpdater; private Logger logger; + private Map recentlyLeftBattle; public BattleManager(Logger logger) { @@ -27,6 +36,7 @@ public class BattleManager battleUpdater = new BattleUpdater(this); updaterThread = new Thread(battleUpdater); updaterThread.start(); + recentlyLeftBattle = new HashMap(); } /** @@ -245,7 +255,7 @@ public class BattleManager { ++IDCounter; } - Battle newBattle = new Battle(IDCounter, sideA, sideB, true); + Battle newBattle = new Battle(this, IDCounter, sideA, sideB, true); battleMap.put(IDCounter, newBattle); newBattle.notifyPlayersBattleInfo(); return newBattle; @@ -263,4 +273,50 @@ public class BattleManager updaterThread = null; battleMap.clear(); } + + protected void addRecentlyLeftBattle(Combatant c) + { + c.time = System.nanoTime(); + Config config = TurnBasedMinecraftMod.proxy.getConfig(); + if(c.entity instanceof EntityPlayerMP) + { + TurnBasedMinecraftMod.NWINSTANCE.sendTo(new PacketGeneralMessage("You just left battle! " + config.getLeaveBattleCooldownSeconds() + " seconds until you can attack/be-attacked again!"), (EntityPlayerMP)c.entity); + } + synchronized(recentlyLeftBattle) + { + recentlyLeftBattle.put(c.entity.getEntityId(), c); + } + } + + protected void updateRecentlyLeftBattle() + { + long current = System.nanoTime(); + Queue removeQueue = new ArrayDeque(); + synchronized(recentlyLeftBattle) + { + for(Combatant c : recentlyLeftBattle.values()) + { + if(current - c.time > TurnBasedMinecraftMod.proxy.getConfig().getLeaveBattleCooldownNanos()) + { + removeQueue.add(c); + } + } + for(Combatant c = removeQueue.poll(); c != null; c = removeQueue.poll()) + { + if(c.entity instanceof EntityPlayerMP) + { + TurnBasedMinecraftMod.NWINSTANCE.sendTo(new PacketGeneralMessage("Timer ended, you can now attack/be-attacked again."), (EntityPlayerMP)c.entity); + } + recentlyLeftBattle.remove(c.entity.getEntityId()); + } + } + } + + public boolean isRecentlyLeftBattle(int entityID) + { + synchronized(recentlyLeftBattle) + { + return recentlyLeftBattle.containsKey(entityID); + } + } } \ No newline at end of file diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/BattleUpdater.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/BattleUpdater.java index 8b8e4ba..9698187 100644 --- a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/BattleUpdater.java +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/BattleUpdater.java @@ -33,6 +33,7 @@ public class BattleUpdater implements Runnable { manager.battleMap.remove(ended); } + manager.updateRecentlyLeftBattle(); try { Thread.sleep(250); } catch (Throwable t) { /* ignored */ } } } diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Combatant.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Combatant.java index 559aa49..16368b4 100644 --- a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Combatant.java +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Combatant.java @@ -24,6 +24,7 @@ public class Combatant public double z; public float yaw; public float pitch; + public long time; public Combatant() { diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/CommandTBMEnableAll.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/CommandTBMEnableAll.java index 77d2f0a..303ddb9 100644 --- a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/CommandTBMEnableAll.java +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/CommandTBMEnableAll.java @@ -5,7 +5,6 @@ import com.seodisparate.TurnBasedMinecraft.common.networking.PacketGeneralMessag import net.minecraft.command.CommandBase; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; -import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Config.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Config.java index 7e868b0..143694b 100644 --- a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Config.java +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Config.java @@ -8,7 +8,6 @@ import java.io.IOException; import java.io.InputStream; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -49,6 +48,7 @@ public class Config private boolean onlyOPsSelfDisableTB = true; private boolean battleDisabledForAll = false; private boolean oldBattleBehaviorEnabled = false; + private int leaveBattleCooldownSeconds = 5; public Config(Logger logger) { @@ -175,6 +175,18 @@ public class Config { continue; } + else if(xmlReader.getLocalName().equals("LeaveBattleCooldown")) + { + leaveBattleCooldownSeconds = Integer.parseInt(xmlReader.getElementText()); + if(leaveBattleCooldownSeconds <= 0) + { + leaveBattleCooldownSeconds = 1; + } + else if(leaveBattleCooldownSeconds > 10) + { + leaveBattleCooldownSeconds = 10; + } + } else if(xmlReader.getLocalName().equals("OldBattleBehavior")) { if(xmlReader.getElementText().toLowerCase().equals("false")) @@ -634,4 +646,14 @@ public class Config { return oldBattleBehaviorEnabled; } + + public int getLeaveBattleCooldownSeconds() + { + return leaveBattleCooldownSeconds; + } + + public long getLeaveBattleCooldownNanos() + { + return (long)leaveBattleCooldownSeconds * 1000000000L; + } } diff --git a/src/main/resources/assets/TurnBasedMinecraft/TBM_Config.xml b/src/main/resources/assets/TurnBasedMinecraft/TBM_Config.xml index 750d4a3..17c0838 100644 --- a/src/main/resources/assets/TurnBasedMinecraft/TBM_Config.xml +++ b/src/main/resources/assets/TurnBasedMinecraft/TBM_Config.xml @@ -1,6 +1,8 @@ 5 + + 5 false