package com.seodisparate.TurnBasedMinecraft;
-import net.minecraft.init.Blocks;
+import org.apache.logging.log4j.Logger;
+
+import com.seodisparate.TurnBasedMinecraft.common.BattleManager;
+
+import net.minecraft.entity.Entity;
+import net.minecraftforge.event.entity.living.LivingAttackEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
-import org.apache.logging.log4j.Logger;
@Mod(modid = TurnBasedMinecraftMod.MODID, name = TurnBasedMinecraftMod.NAME, version = TurnBasedMinecraftMod.VERSION)
public class TurnBasedMinecraftMod
public static final String VERSION = "1.0";
private static Logger logger;
+ private static BattleManager battleManager;
+
+ public static Entity attackingEntity;
@EventHandler
public void preInit(FMLPreInitializationEvent event)
@EventHandler
public void init(FMLInitializationEvent event)
{
- // some example code
- logger.info("DIRT BLOCK >> {}", Blocks.DIRT.getRegistryName());
+ battleManager = new BattleManager();
+ }
+
+ @EventHandler
+ public void entityAttacked(LivingAttackEvent event)
+ {
+ if(!event.getEntity().equals(attackingEntity) && battleManager.checkAttack(event))
+ {
+ logger.debug("Canceled LivingAttackEvent between " + attackingEntity + " and " + event.getEntity());
+ event.setCanceled(true);
+ }
}
}
--- /dev/null
+package com.seodisparate.TurnBasedMinecraft.common;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Map;
+
+import net.minecraft.entity.Entity;
+
+public class Battle
+{
+ private int id;
+ private Map<Integer, Entity> sideA;
+ private Map<Integer, Entity> sideB;
+
+ private Instant lastUpdated;
+
+ public Battle(int id, Collection<Entity> sideA, Collection<Entity> sideB)
+ {
+ this.id = id;
+ this.sideA = new Hashtable<Integer, Entity>();
+ this.sideB = new Hashtable<Integer, Entity>();
+ for(Entity e : sideA)
+ {
+ this.sideA.put(e.getEntityId(), e);
+ }
+ for(Entity e : sideB)
+ {
+ this.sideB.put(e.getEntityId(), e);
+ }
+
+ lastUpdated = null;
+ }
+
+ public int getId()
+ {
+ return id;
+ }
+
+ public boolean hasCombatant(int entityID)
+ {
+ return sideA.containsKey(entityID) || sideB.containsKey(entityID);
+ }
+
+ public boolean hasCombatantInSideA(int entityID)
+ {
+ return sideA.containsKey(entityID);
+ }
+
+ public void addCombatantToSideA(Entity e)
+ {
+ sideA.put(e.getEntityId(), e);
+ }
+
+ public void addCombatantToSideB(Entity e)
+ {
+ sideB.put(e.getEntityId(), e);
+ }
+
+ public void update()
+ {
+ if(lastUpdated == null)
+ {
+ lastUpdated = Instant.now();
+ update(Duration.ZERO);
+ }
+ else
+ {
+ Instant now = Instant.now();
+ update(Duration.between(lastUpdated, now));
+ lastUpdated = now;
+ }
+ }
+
+ private void update(Duration dt)
+ {
+ }
+}
--- /dev/null
+package com.seodisparate.TurnBasedMinecraft.common;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Map;
+
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraftforge.event.entity.living.LivingAttackEvent;
+
+public class BattleManager
+{
+ private int IDCounter = 0;
+ protected Map<Integer, Battle> battleMap;
+ private Thread updaterThread;
+
+ public BattleManager()
+ {
+ battleMap = new Hashtable<Integer, Battle>();
+ updaterThread = new Thread(new BattleUpdater(this));
+ updaterThread.start();
+ }
+
+ /**
+ * Either creates a new Battle, adds a combatant to an existing Battle, or does
+ * nothing, depending on if a player is involved and/or an entity is currently
+ * in battle.
+ *
+ * @param event
+ * @return True if event should be canceled
+ */
+ public boolean checkAttack(final LivingAttackEvent event)
+ {
+ // check if one is in battle
+ Entity inBattle = null;
+ Entity notInBattle = null;
+ Battle battle = null;
+ for(Battle b : battleMap.values())
+ {
+ if(b.hasCombatant(event.getSource().getTrueSource().getEntityId()))
+ {
+ inBattle = event.getSource().getTrueSource();
+ battle = b;
+ break;
+ }
+ }
+ if(inBattle != null)
+ {
+ notInBattle = event.getEntity();
+ } else
+ {
+ notInBattle = event.getSource().getTrueSource();
+ }
+ for(Battle b : battleMap.values())
+ {
+ if(b.hasCombatant(event.getEntity().getEntityId()))
+ {
+ if(inBattle != null)
+ {
+ // both combatants in battle
+ return true;
+ }
+ inBattle = event.getEntity();
+ battle = b;
+ break;
+ }
+ }
+ if(inBattle == null)
+ {
+ // neither entity is in battle
+ if(event.getEntity() instanceof EntityPlayer || event.getSource().getTrueSource() instanceof EntityPlayer)
+ {
+ // at least one of the entities is a player, create Battle
+ Collection<Entity> sideA = new ArrayList<Entity>(1);
+ Collection<Entity> sideB = new ArrayList<Entity>(1);
+ sideA.add(event.getEntity());
+ sideB.add(event.getSource().getTrueSource());
+ createBattle(sideA, sideB);
+ }
+ return false;
+ }
+
+ // at this point only one entity is in battle, so add entity to other side
+ if(battle.hasCombatantInSideA(inBattle.getEntityId()))
+ {
+ battle.addCombatantToSideB(notInBattle);
+ }
+ else
+ {
+ battle.addCombatantToSideA(notInBattle);
+ }
+ return true;
+ }
+
+ private Battle createBattle(Collection<Entity> sideA, Collection<Entity> sideB)
+ {
+ while(battleMap.containsKey(IDCounter))
+ {
+ ++IDCounter;
+ }
+ Battle newBattle = new Battle(IDCounter, sideA, sideB);
+ battleMap.put(IDCounter, newBattle);
+ return newBattle;
+ }
+}
--- /dev/null
+package com.seodisparate.TurnBasedMinecraft.common;
+
+public class BattleUpdater implements Runnable
+{
+ BattleManager manager;
+
+ public BattleUpdater(BattleManager manager)
+ {
+ this.manager = manager;
+ }
+
+ @Override
+ public void run()
+ {
+ for(Battle e : manager.battleMap.values())
+ {
+ e.update();
+ }
+ try { Thread.sleep(250); } catch (Exception e) { /* ignored */ }
+ }
+}
\ No newline at end of file